diff --git a/src/umbraco.cms/businesslogic/Packager/Installer.cs b/src/umbraco.cms/businesslogic/Packager/Installer.cs index 46e101425c..bc1c062631 100644 --- a/src/umbraco.cms/businesslogic/Packager/Installer.cs +++ b/src/umbraco.cms/businesslogic/Packager/Installer.cs @@ -12,10 +12,8 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Packaging; using umbraco.cms.businesslogic.web; -using umbraco.cms.businesslogic.propertytype; using umbraco.BusinessLogic; using System.Diagnostics; -using System.Security; using umbraco.cms.businesslogic.macro; using umbraco.cms.businesslogic.template; using umbraco.interfaces; @@ -188,8 +186,16 @@ namespace umbraco.cms.businesslogic.packager // Check if the file is a valid package if (fi.Extension.ToLower() == ".umb") { - tempDir = UnPack(fi.FullName, deleteFile); - LoadConfig(tempDir); + try + { + tempDir = UnPack(fi.FullName, deleteFile); + LoadConfig(tempDir); + } + catch (Exception exception) + { + LogHelper.Error(string.Format("Error importing file {0}", fi.FullName), exception); + throw; + } } else throw new Exception("Error - file isn't a package (doesn't have a .umb extension). Check if the file automatically got named '.zip' upon download."); @@ -272,57 +278,57 @@ namespace umbraco.cms.businesslogic.packager //string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath; string basePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath; - foreach (XmlNode n in Config.DocumentElement.SelectNodes("//file")) + try { - var destPath = GetFileName(basePath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath"))); - var sourceFile = GetFileName(tempDir, XmlHelper.GetNodeValue(n.SelectSingleNode("guid"))); - var destFile = GetFileName(destPath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); - - // Create the destination directory if it doesn't exist - if (Directory.Exists(destPath) == false) - Directory.CreateDirectory(destPath); - //If a file with this name exists, delete it - else if (File.Exists(destFile)) - File.Delete(destFile); - - // Copy the file - // SJ: Note - this used to do a move but some packages included the same file to be - // copied to multiple locations like so: - // - // - // my-icon.png - // /umbraco/Images/ - // my-icon.png - // - // - // my-icon.png - // /App_Plugins/MyPlugin/Images - // my-icon.png - // - // - // Since this file unzips as a flat list of files, moving the file the first time means - // that when you try to do that a second time, it would result in a FileNotFoundException - try + foreach (XmlNode n in Config.DocumentElement.SelectNodes("//file")) { + var destPath = GetFileName(basePath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath"))); + var sourceFile = GetFileName(tempDir, XmlHelper.GetNodeValue(n.SelectSingleNode("guid"))); + var destFile = GetFileName(destPath, XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + + // Create the destination directory if it doesn't exist + if (Directory.Exists(destPath) == false) + Directory.CreateDirectory(destPath); + //If a file with this name exists, delete it + else if (File.Exists(destFile)) + File.Delete(destFile); + + // Copy the file + // SJ: Note - this used to do a move but some packages included the same file to be + // copied to multiple locations like so: + // + // + // my-icon.png + // /umbraco/Images/ + // my-icon.png + // + // + // my-icon.png + // /App_Plugins/MyPlugin/Images + // my-icon.png + // + // + // Since this file unzips as a flat list of files, moving the file the first time means + // that when you try to do that a second time, it would result in a FileNotFoundException File.Copy(sourceFile, destFile); + + //PPH log file install + insPack.Data.Files.Add(XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + } - catch (Exception exception) + + // Once we're done copying, remove all the files + foreach (XmlNode n in Config.DocumentElement.SelectNodes("//file")) { - // Make sure to log the error before throwing so package devs know where to look for the problem - LogHelper.Error(string.Format("Error copying file from {0} to {1}", sourceFile, destFile), exception); - throw; + var sourceFile = GetFileName(tempDir, XmlHelper.GetNodeValue(n.SelectSingleNode("guid"))); + if (File.Exists(sourceFile)) + File.Delete(sourceFile); } - - //PPH log file install - insPack.Data.Files.Add(XmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + XmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); } - - // Once we're done copying, remove all the files - foreach (XmlNode n in Config.DocumentElement.SelectNodes("//file")) + catch (Exception exception) { - var sourceFile = GetFileName(tempDir, XmlHelper.GetNodeValue(n.SelectSingleNode("guid"))); - if (File.Exists(sourceFile)) - File.Delete(sourceFile); + LogHelper.Error("Package install error", exception); + throw; } // log that a user has install files @@ -334,8 +340,6 @@ namespace umbraco.cms.businesslogic.packager } insPack.Save(); - - } } @@ -345,160 +349,169 @@ namespace umbraco.cms.businesslogic.packager () => "Installing business logic for package id " + packageId + " into temp folder " + tempDir, () => "Package business logic installation complete for package id " + packageId)) { - //retrieve the manifest to continue installation - var insPack = InstalledPackage.GetById(packageId); - //bool saveNeeded = false; - - // Get current user, with a fallback - var currentUser = new User(0); - - //if there's a context, try to resolve the user - this will return null if there is a context but no - // user found when there are old/invalid cookies lying around most likely during installation. - // in that case we'll keep using the admin user - if (string.IsNullOrEmpty(BasePages.UmbracoEnsuredPage.umbracoUserContextID) == false) + InstalledPackage insPack; + try { - if (BasePages.UmbracoEnsuredPage.ValidateUserContextID(BasePages.UmbracoEnsuredPage.umbracoUserContextID)) + //retrieve the manifest to continue installation + insPack = InstalledPackage.GetById(packageId); + //bool saveNeeded = false; + + // Get current user, with a fallback + var currentUser = new User(0); + + //if there's a context, try to resolve the user - this will return null if there is a context but no + // user found when there are old/invalid cookies lying around most likely during installation. + // in that case we'll keep using the admin user + if (string.IsNullOrEmpty(BasePages.UmbracoEnsuredPage.umbracoUserContextID) == false) { - var userById = User.GetCurrent(); - if (userById != null) - currentUser = userById; - } - } - - - //Xml as XElement which is used with the new PackagingService - var rootElement = Config.DocumentElement.GetXElement(); - var packagingService = ApplicationContext.Current.Services.PackagingService; - - //Perhaps it would have been a good idea to put the following into methods eh?!? - - #region DataTypes - var dataTypeElement = rootElement.Descendants("DataTypes").FirstOrDefault(); - if (dataTypeElement != null) - { - var dataTypeDefinitions = packagingService.ImportDataTypeDefinitions(dataTypeElement, currentUser.Id); - foreach (var dataTypeDefinition in dataTypeDefinitions) - { - insPack.Data.DataTypes.Add(dataTypeDefinition.Id.ToString(CultureInfo.InvariantCulture)); - } - } - #endregion - - #region Languages - var languageItemsElement = rootElement.Descendants("Languages").FirstOrDefault(); - if (languageItemsElement != null) - { - var insertedLanguages = packagingService.ImportLanguages(languageItemsElement); - insPack.Data.Languages.AddRange(insertedLanguages.Select(l => l.Id.ToString())); - } - - #endregion - - #region Dictionary items - var dictionaryItemsElement = rootElement.Descendants("DictionaryItems").FirstOrDefault(); - if (dictionaryItemsElement != null) - { - var insertedDictionaryItems = packagingService.ImportDictionaryItems(dictionaryItemsElement); - insPack.Data.DictionaryItems.AddRange(insertedDictionaryItems.Select(d => d.Id.ToString())); - } - #endregion - - #region Macros - foreach (XmlNode n in Config.DocumentElement.SelectNodes("//macro")) - { - //TODO: Fix this, this should not use the legacy API - Macro m = Macro.Import(n); - - if (m != null) - { - insPack.Data.Macros.Add(m.Id.ToString(CultureInfo.InvariantCulture)); - //saveNeeded = true; - } - } - - //if (saveNeeded) { insPack.Save(); saveNeeded = false; } - #endregion - - #region Templates - var templateElement = rootElement.Descendants("Templates").FirstOrDefault(); - if (templateElement != null) - { - var templates = packagingService.ImportTemplates(templateElement, currentUser.Id); - foreach (var template in templates) - { - insPack.Data.Templates.Add(template.Id.ToString(CultureInfo.InvariantCulture)); - } - } - #endregion - - #region DocumentTypes - //Check whether the root element is a doc type rather then a complete package - var docTypeElement = rootElement.Name.LocalName.Equals("DocumentType") || - rootElement.Name.LocalName.Equals("DocumentTypes") - ? rootElement - : rootElement.Descendants("DocumentTypes").FirstOrDefault(); - - if (docTypeElement != null) - { - var contentTypes = packagingService.ImportContentTypes(docTypeElement, currentUser.Id); - foreach (var contentType in contentTypes) - { - insPack.Data.Documenttypes.Add(contentType.Id.ToString(CultureInfo.InvariantCulture)); - //saveNeeded = true; - } - } - #endregion - - #region Stylesheets - foreach (XmlNode n in Config.DocumentElement.SelectNodes("Stylesheets/Stylesheet")) - { - StyleSheet s = StyleSheet.Import(n, currentUser); - - insPack.Data.Stylesheets.Add(s.Id.ToString()); - //saveNeeded = true; - } - - //if (saveNeeded) { insPack.Save(); saveNeeded = false; } - #endregion - - #region Documents - var documentElement = rootElement.Descendants("DocumentSet").FirstOrDefault(); - if (documentElement != null) - { - var content = packagingService.ImportContent(documentElement, -1, currentUser.Id); - var firstContentItem = content.First(); - insPack.Data.ContentNodeId = firstContentItem.Id.ToString(CultureInfo.InvariantCulture); - } - #endregion - - #region Package Actions - foreach (XmlNode n in Config.DocumentElement.SelectNodes("Actions/Action")) - { - if (n.Attributes["undo"] == null || n.Attributes["undo"].Value == "true") - { - insPack.Data.Actions += n.OuterXml; - } - - //Run the actions tagged only for 'install' - - if (n.Attributes["runat"] != null && n.Attributes["runat"].Value == "install") - { - var alias = n.Attributes["alias"] != null ? n.Attributes["alias"].Value : ""; - - if (alias.IsNullOrWhiteSpace() == false) + if (BasePages.UmbracoEnsuredPage.ValidateUserContextID(BasePages.UmbracoEnsuredPage.umbracoUserContextID)) { - PackageAction.RunPackageAction(insPack.Data.Name, alias, n); + var userById = User.GetCurrent(); + if (userById != null) + currentUser = userById; } } + + + //Xml as XElement which is used with the new PackagingService + var rootElement = Config.DocumentElement.GetXElement(); + var packagingService = ApplicationContext.Current.Services.PackagingService; + + //Perhaps it would have been a good idea to put the following into methods eh?!? + + #region DataTypes + var dataTypeElement = rootElement.Descendants("DataTypes").FirstOrDefault(); + if (dataTypeElement != null) + { + var dataTypeDefinitions = packagingService.ImportDataTypeDefinitions(dataTypeElement, currentUser.Id); + foreach (var dataTypeDefinition in dataTypeDefinitions) + { + insPack.Data.DataTypes.Add(dataTypeDefinition.Id.ToString(CultureInfo.InvariantCulture)); + } + } + #endregion + + #region Languages + var languageItemsElement = rootElement.Descendants("Languages").FirstOrDefault(); + if (languageItemsElement != null) + { + var insertedLanguages = packagingService.ImportLanguages(languageItemsElement); + insPack.Data.Languages.AddRange(insertedLanguages.Select(l => l.Id.ToString())); + } + + #endregion + + #region Dictionary items + var dictionaryItemsElement = rootElement.Descendants("DictionaryItems").FirstOrDefault(); + if (dictionaryItemsElement != null) + { + var insertedDictionaryItems = packagingService.ImportDictionaryItems(dictionaryItemsElement); + insPack.Data.DictionaryItems.AddRange(insertedDictionaryItems.Select(d => d.Id.ToString())); + } + #endregion + + #region Macros + foreach (XmlNode n in Config.DocumentElement.SelectNodes("//macro")) + { + //TODO: Fix this, this should not use the legacy API + Macro m = Macro.Import(n); + + if (m != null) + { + insPack.Data.Macros.Add(m.Id.ToString(CultureInfo.InvariantCulture)); + //saveNeeded = true; + } + } + + //if (saveNeeded) { insPack.Save(); saveNeeded = false; } + #endregion + + #region Templates + var templateElement = rootElement.Descendants("Templates").FirstOrDefault(); + if (templateElement != null) + { + var templates = packagingService.ImportTemplates(templateElement, currentUser.Id); + foreach (var template in templates) + { + insPack.Data.Templates.Add(template.Id.ToString(CultureInfo.InvariantCulture)); + } + } + #endregion + + #region DocumentTypes + //Check whether the root element is a doc type rather then a complete package + var docTypeElement = rootElement.Name.LocalName.Equals("DocumentType") || + rootElement.Name.LocalName.Equals("DocumentTypes") + ? rootElement + : rootElement.Descendants("DocumentTypes").FirstOrDefault(); + + if (docTypeElement != null) + { + var contentTypes = packagingService.ImportContentTypes(docTypeElement, currentUser.Id); + foreach (var contentType in contentTypes) + { + insPack.Data.Documenttypes.Add(contentType.Id.ToString(CultureInfo.InvariantCulture)); + //saveNeeded = true; + } + } + #endregion + + #region Stylesheets + foreach (XmlNode n in Config.DocumentElement.SelectNodes("Stylesheets/Stylesheet")) + { + StyleSheet s = StyleSheet.Import(n, currentUser); + + insPack.Data.Stylesheets.Add(s.Id.ToString()); + //saveNeeded = true; + } + + //if (saveNeeded) { insPack.Save(); saveNeeded = false; } + #endregion + + #region Documents + var documentElement = rootElement.Descendants("DocumentSet").FirstOrDefault(); + if (documentElement != null) + { + var content = packagingService.ImportContent(documentElement, -1, currentUser.Id); + var firstContentItem = content.First(); + insPack.Data.ContentNodeId = firstContentItem.Id.ToString(CultureInfo.InvariantCulture); + } + #endregion + + #region Package Actions + foreach (XmlNode n in Config.DocumentElement.SelectNodes("Actions/Action")) + { + if (n.Attributes["undo"] == null || n.Attributes["undo"].Value == "true") + { + insPack.Data.Actions += n.OuterXml; + } + + //Run the actions tagged only for 'install' + + if (n.Attributes["runat"] != null && n.Attributes["runat"].Value == "install") + { + var alias = n.Attributes["alias"] != null ? n.Attributes["alias"].Value : ""; + + if (alias.IsNullOrWhiteSpace() == false) + { + PackageAction.RunPackageAction(insPack.Data.Name, alias, n); + } + } + } + #endregion + + // Trigger update of Apps / Trees config. + // (These are ApplicationStartupHandlers so just instantiating them will trigger them) + new ApplicationRegistrar(); + new ApplicationTreeRegistrar(); + + insPack.Save(); + } + catch (Exception exception) + { + LogHelper.Error("Error installing businesslogic", exception); + throw; } - #endregion - - // Trigger update of Apps / Trees config. - // (These are ApplicationStartupHandlers so just instantiating them will trigger them) - new ApplicationRegistrar(); - new ApplicationTreeRegistrar(); - - insPack.Save(); OnPackageBusinessLogicInstalled(insPack); }