using System; using System.Xml; using System.Xml.XPath; using System.Collections.Generic; using System.ComponentModel; using System.IO; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; using Umbraco.Core.Logging; namespace umbraco.cms.businesslogic.packager { /// /// This is the xml data for installed packages. This is not the same xml as a pckage format! /// public class data { private static XmlDocument _source; public static XmlDocument Source { get { return _source; } } public static void Reload(string dataSource) { //do some error checking and create the folders/files if they don't exist if (!File.Exists(dataSource)) { if (!Directory.Exists(IOHelper.MapPath(Settings.PackagerRoot))) { Directory.CreateDirectory(IOHelper.MapPath(Settings.PackagerRoot)); } if (!Directory.Exists(IOHelper.MapPath(Settings.PackagesStorage))) { Directory.CreateDirectory(IOHelper.MapPath(Settings.PackagesStorage)); } if (!Directory.Exists(IOHelper.MapPath(Settings.InstalledPackagesStorage))) { Directory.CreateDirectory(IOHelper.MapPath(Settings.InstalledPackagesStorage)); } using (StreamWriter sw = File.CreateText(dataSource)) { sw.Write(umbraco.cms.businesslogic.Packager.FileResources.PackageFiles.Packages); sw.Flush(); } } if (_source == null) { _source = new XmlDocument(); } //error checking here if (File.Exists(dataSource)) { var isEmpty = false; using (var sr = new StreamReader(dataSource)) { if (sr.ReadToEnd().IsNullOrWhiteSpace()) { isEmpty = true; } } if (isEmpty) { File.WriteAllText(dataSource, @""); } } _source.Load(dataSource); } public static XmlNode GetFromId(int Id, string dataSource, bool reload) { if (reload) Reload(dataSource); return Source.SelectSingleNode("/packages/package [@id = '" + Id.ToString().ToUpper() + "']"); } public static XmlNode GetFromGuid(string guid, string dataSource, bool reload) { if (reload) Reload(dataSource); return Source.SelectSingleNode("/packages/package [@packageGuid = '" + guid + "']"); } public static PackageInstance MakeNew(string Name, string dataSource) { Reload(dataSource); int maxId = 1; // Find max id foreach (XmlNode n in Source.SelectNodes("packages/package")) { if (int.Parse(n.Attributes.GetNamedItem("id").Value) >= maxId) maxId = int.Parse(n.Attributes.GetNamedItem("id").Value) + 1; } XmlElement instance = Source.CreateElement("package"); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "id", maxId.ToString())); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "version", "")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "name", Name)); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "folder", Guid.NewGuid().ToString())); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "packagepath", "")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "repositoryGuid", "")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "iconUrl", "")); //set to current version instance.Attributes.Append(XmlHelper.AddAttribute(Source, "umbVersion", UmbracoVersion.Current.ToString(3))); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "packageGuid", Guid.NewGuid().ToString())); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "hasUpdate", "false")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "enableSkins", "false")); instance.Attributes.Append(XmlHelper.AddAttribute(Source, "skinRepoGuid", "")); XmlElement license = Source.CreateElement("license"); license.InnerText = "MIT License"; license.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "http://opensource.org/licenses/MIT")); instance.AppendChild(license); XmlElement author = Source.CreateElement("author"); author.InnerText = ""; author.Attributes.Append(XmlHelper.AddAttribute(Source, "url", "")); instance.AppendChild(author); instance.AppendChild(XmlHelper.AddTextNode(Source, "readme", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "actions", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "datatypes", "")); XmlElement content = Source.CreateElement("content"); content.InnerText = ""; content.Attributes.Append(XmlHelper.AddAttribute(Source, "nodeId", "")); content.Attributes.Append(XmlHelper.AddAttribute(Source, "loadChildNodes", "false")); instance.AppendChild(content); instance.AppendChild(XmlHelper.AddTextNode(Source, "templates", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "stylesheets", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "documenttypes", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "macros", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "files", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "languages", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "dictionaryitems", "")); instance.AppendChild(XmlHelper.AddTextNode(Source, "loadcontrol", "")); Source.SelectSingleNode("packages").AppendChild(instance); Source.Save(dataSource); var retVal = data.Package(maxId, dataSource); return retVal; } public static PackageInstance Package(int id, string datasource) { return ConvertXmlToPackage(GetFromId(id, datasource, true)); } public static PackageInstance Package(string guid, string datasource) { XmlNode node = GetFromGuid(guid, datasource, true); if (node != null) return ConvertXmlToPackage(node); else return new PackageInstance(); } public static List GetAllPackages(string dataSource) { Reload(dataSource); XmlNodeList nList = data.Source.SelectNodes("packages/package"); List retVal = new List(); for (int i = 0; i < nList.Count; i++) { try { retVal.Add(ConvertXmlToPackage(nList[i])); } catch (Exception ex) { LogHelper.Error("An error occurred in GetAllPackages", ex); } } return retVal; } private static PackageInstance ConvertXmlToPackage(XmlNode n) { PackageInstance retVal = new PackageInstance(); if (n != null) { retVal.Id = int.Parse(SafeAttribute("id", n)); retVal.Name = SafeAttribute("name", n); retVal.Folder = SafeAttribute("folder", n); retVal.PackagePath = SafeAttribute("packagepath", n); retVal.Version = SafeAttribute("version", n); retVal.Url = SafeAttribute("url", n); retVal.RepositoryGuid = SafeAttribute("repositoryGuid", n); retVal.PackageGuid = SafeAttribute("packageGuid", n); retVal.HasUpdate = bool.Parse(SafeAttribute("hasUpdate", n)); retVal.IconUrl = SafeAttribute("iconUrl", n); var umbVersion = SafeAttribute("umbVersion", n); Version parsedVersion; if (umbVersion.IsNullOrWhiteSpace() == false && Version.TryParse(umbVersion, out parsedVersion)) { retVal.UmbracoVersion = parsedVersion; } bool enableSkins = false; bool.TryParse(SafeAttribute("enableSkins", n), out enableSkins); retVal.EnableSkins = enableSkins; retVal.SkinRepoGuid = string.IsNullOrEmpty(SafeAttribute("skinRepoGuid", n)) ? Guid.Empty : new Guid(SafeAttribute("skinRepoGuid", n)); retVal.License = SafeNodeValue(n.SelectSingleNode("license")); retVal.LicenseUrl = n.SelectSingleNode("license").Attributes.GetNamedItem("url").Value; retVal.Author = SafeNodeValue(n.SelectSingleNode("author")); retVal.AuthorUrl = SafeAttribute("url", n.SelectSingleNode("author")); retVal.Readme = SafeNodeValue(n.SelectSingleNode("readme")); retVal.Actions = SafeNodeInnerXml(n.SelectSingleNode("actions")); retVal.ContentNodeId = SafeAttribute("nodeId", n.SelectSingleNode("content")); retVal.ContentLoadChildNodes = bool.Parse(SafeAttribute("loadChildNodes", n.SelectSingleNode("content"))); retVal.Macros = new List(SafeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); retVal.Macros = new List(SafeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); retVal.Templates = new List(SafeNodeValue(n.SelectSingleNode("templates")).Trim(',').Split(',')); retVal.Stylesheets = new List(SafeNodeValue(n.SelectSingleNode("stylesheets")).Trim(',').Split(',')); retVal.Documenttypes = new List(SafeNodeValue(n.SelectSingleNode("documenttypes")).Trim(',').Split(',')); retVal.Languages = new List(SafeNodeValue(n.SelectSingleNode("languages")).Trim(',').Split(',')); retVal.DictionaryItems = new List(SafeNodeValue(n.SelectSingleNode("dictionaryitems")).Trim(',').Split(',')); retVal.DataTypes = new List(SafeNodeValue(n.SelectSingleNode("datatypes")).Trim(',').Split(',')); XmlNodeList xmlFiles = n.SelectNodes("files/file"); retVal.Files = new List(); for (int i = 0; i < xmlFiles.Count; i++) retVal.Files.Add(xmlFiles[i].InnerText); retVal.LoadControl = SafeNodeValue(n.SelectSingleNode("loadcontrol")); } return retVal; } public static void Delete(int Id, string dataSource) { Reload(dataSource); // Remove physical xml file if any //PackageInstance p = new PackageInstance(Id); //TODO DELETE PACKAGE FOLDER... //p.Folder XmlNode n = data.GetFromId(Id, dataSource, true); if (n != null) { data.Source.SelectSingleNode("/packages").RemoveChild(n); data.Source.Save(dataSource); } } [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("This method is no longer in use and will be removed in the future")] public static void UpdateValue(XmlNode n, string Value) { if (n.FirstChild != null) n.FirstChild.Value = Value; else { n.AppendChild(Source.CreateTextNode(Value)); } } public static void Save(PackageInstance package, string dataSource) { Reload(dataSource); var xmlDef = GetFromId(package.Id, dataSource, false); XmlHelper.SetAttribute(Source, xmlDef, "name", package.Name); XmlHelper.SetAttribute(Source, xmlDef, "version", package.Version); XmlHelper.SetAttribute(Source, xmlDef, "url", package.Url); XmlHelper.SetAttribute(Source, xmlDef, "packagepath", package.PackagePath); XmlHelper.SetAttribute(Source, xmlDef, "repositoryGuid", package.RepositoryGuid); XmlHelper.SetAttribute(Source, xmlDef, "packageGuid", package.PackageGuid); XmlHelper.SetAttribute(Source, xmlDef, "hasUpdate", package.HasUpdate.ToString()); XmlHelper.SetAttribute(Source, xmlDef, "enableSkins", package.EnableSkins.ToString()); XmlHelper.SetAttribute(Source, xmlDef, "skinRepoGuid", package.SkinRepoGuid.ToString()); XmlHelper.SetAttribute(Source, xmlDef, "iconUrl", package.IconUrl); if (package.UmbracoVersion != null) { XmlHelper.SetAttribute(Source, xmlDef, "umbVersion", package.UmbracoVersion.ToString(3)); } var licenseNode = xmlDef.SelectSingleNode("license"); if (licenseNode == null) { licenseNode = Source.CreateElement("license"); xmlDef.AppendChild(licenseNode); } licenseNode.InnerText = package.License; XmlHelper.SetAttribute(Source, licenseNode, "url", package.LicenseUrl); var authorNode = xmlDef.SelectSingleNode("author"); if (authorNode == null) { authorNode = Source.CreateElement("author"); xmlDef.AppendChild(authorNode); } authorNode.InnerText = package.Author; XmlHelper.SetAttribute(Source, authorNode, "url", package.AuthorUrl); XmlHelper.SetCDataNode(Source, xmlDef, "readme", package.Readme); XmlHelper.SetInnerXmlNode(Source, xmlDef, "actions", package.Actions); var contentNode = xmlDef.SelectSingleNode("content"); if (contentNode == null) { contentNode = Source.CreateElement("content"); xmlDef.AppendChild(contentNode); } XmlHelper.SetAttribute(Source, contentNode, "nodeId", package.ContentNodeId); XmlHelper.SetAttribute(Source, contentNode, "loadChildNodes", package.ContentLoadChildNodes.ToString()); XmlHelper.SetTextNode(Source, xmlDef, "macros", JoinList(package.Macros, ',')); XmlHelper.SetTextNode(Source, xmlDef, "templates", JoinList(package.Templates, ',')); XmlHelper.SetTextNode(Source, xmlDef, "stylesheets", JoinList(package.Stylesheets, ',')); XmlHelper.SetTextNode(Source, xmlDef, "documenttypes", JoinList(package.Documenttypes, ',')); XmlHelper.SetTextNode(Source, xmlDef, "languages", JoinList(package.Languages, ',')); XmlHelper.SetTextNode(Source, xmlDef, "dictionaryitems", JoinList(package.DictionaryItems, ',')); XmlHelper.SetTextNode(Source, xmlDef, "datatypes", JoinList(package.DataTypes, ',')); var filesNode = xmlDef.SelectSingleNode("files"); if (filesNode == null) { filesNode = Source.CreateElement("files"); xmlDef.AppendChild(filesNode); } filesNode.InnerXml = ""; foreach (var fileStr in package.Files) { if (string.IsNullOrWhiteSpace(fileStr) == false) filesNode.AppendChild(XmlHelper.AddTextNode(Source, "file", fileStr)); } XmlHelper.SetTextNode(Source, xmlDef, "loadcontrol", package.LoadControl); Source.Save(dataSource); } private static string SafeAttribute(string name, XmlNode n) { return n.Attributes == null || n.Attributes[name] == null ? string.Empty : n.Attributes[name].Value; } private static string SafeNodeValue(XmlNode n) { try { return XmlHelper.GetNodeValue(n); } catch { return string.Empty; } } private static string SafeNodeInnerXml(XmlNode n) { try { return n.InnerXml; } catch { return string.Empty; } } private static string JoinList(List list, char seperator) { string retVal = ""; foreach (string str in list) { retVal += str + seperator; } return retVal.Trim(seperator); } public data() { } } }