예제 #1
0
 //
 //====================================================================================================
 //
 public static void processAfterSave_AddonCollection(CoreController core, bool isDelete, string contentName, int recordID, string recordName, int recordParentID, bool useContentWatchLink)
 {
     //
     // -- if this is an add or delete, manage the collection folders
     if (isDelete)
     {
         //
         // todo - if a collection is deleted, consider deleting the collection folder (or saving as archive)
     }
     else
     {
         //
         // -- add or modify collection, verify collection /addon folder
         var addonCollection = AddonCollectionModel.create <AddonCollectionModel>(core.cpParent, recordID);
         if (addonCollection != null)
         {
             string CollectionVersionFolderName = CollectionFolderController.verifyCollectionVersionFolderName(core, addonCollection.ccguid, addonCollection.name);
             if (string.IsNullOrEmpty(CollectionVersionFolderName))
             {
                 //
                 // -- new collection
                 string CollectionVersionFolder = AddonController.getPrivateFilesAddonPath() + CollectionVersionFolderName;
                 core.privateFiles.createPath(CollectionVersionFolder);
                 CollectionFolderController.updateCollectionFolderConfig(core, addonCollection.name, addonCollection.ccguid, core.dateTimeNowMockable, CollectionVersionFolderName);
             }
         }
     }
 }
예제 #2
0
        //
        //====================================================================================================
        /// <summary>
        /// Install a collectionZip from the Collection Library (registry, distribution, etc.)
        /// downloads the collection to a private folder
        /// Calls installCollectionFromCollectionFolder.
        /// </summary>
        /// <param name="core"></param>
        /// <param name="collectionGuid"></param>
        /// <param name="return_ErrorMessage"></param>
        /// <param name="ImportFromCollectionsGuidList"></param>
        /// <param name="IsNewBuild"></param>
        /// <param name="repair"></param>
        /// <param name="nonCriticalErrorList"></param>
        /// <param name="logPrefix"></param>
        /// <param name="collectionsInstalledList"></param>
        /// <returns></returns>
        public static bool installCollectionFromLibrary(CoreController core, bool isDependency, Stack <string> contextLog, string collectionGuid, ref string return_ErrorMessage, bool IsNewBuild, bool repair, ref List <string> nonCriticalErrorList, string logPrefix, ref List <string> collectionsInstalledList)
        {
            bool UpgradeOK = true;

            try {
                //
                contextLog.Push(MethodInfo.GetCurrentMethod().Name + ", [" + collectionGuid + "]");
                //
                collectionGuid = GenericController.normalizeGuid(collectionGuid);
                if (string.IsNullOrWhiteSpace(collectionGuid))
                {
                    LogController.logWarn(core, "installCollectionFromRemoteRepo, collectionGuid is null");
                }
                else if (!collectionsInstalledList.Contains(collectionGuid.ToLower(CultureInfo.InvariantCulture)))
                {
                    //
                    // Download all files for this collection and build the collection folder(s)
                    string tempFilesDownloadPath = AddonController.getPrivateFilesAddonPath() + Contensive.Processor.Controllers.GenericController.getGUIDNaked() + "\\";
                    core.tempFiles.createPath(tempFilesDownloadPath);
                    //
                    // -- download the collection file into the download path from the collectionGuid provided
                    DateTime CollectionLastModifiedDate = default;
                    if (CollectionLibraryController.downloadCollectionFromLibrary(core, tempFilesDownloadPath, collectionGuid, ref CollectionLastModifiedDate, ref return_ErrorMessage))
                    {
                        //
                        // -- build the collection folders for all collection files in the download path and created a list of collection Guids that need to be installed
                        var collectionsDownloaded = new List <string>();
                        CollectionInstallController.installCollectionsFromTempFolder(core, isDependency, contextLog, tempFilesDownloadPath, ref return_ErrorMessage, ref collectionsInstalledList, IsNewBuild, repair, ref nonCriticalErrorList, logPrefix, true, ref collectionsDownloaded);
                    }
                    //
                    // -- delete the temporary install folder
                    core.tempFiles.deleteFolder(tempFilesDownloadPath);
                    //
                    // -- invalidate cache
                    core.cache.invalidateAll();
                }
            } catch (Exception ex) {
                LogController.logError(core, ex);
                throw;
            } finally {
                contextLog.Pop();
            }
            return(UpgradeOK);
        }
예제 #3
0
        //
        //====================================================================================================
        /// <summary>
        /// GetAjaxDefaultAddonOptionStringClass remote method
        /// </summary>
        /// <param name="cp"></param>
        /// <returns></returns>
        public override object Execute(Contensive.BaseClasses.CPBaseClass cp)
        {
            string returnHtml = "";

            try {
                using (CoreController core = ((CPClass)cp).core) {
                    using (var csData = new CsModel(core)) {
                        string AddonGuid = core.docProperties.getText("guid");
                        csData.open(AddonModel.tableMetadata.contentName, "ccguid=" + DbController.encodeSQLText(AddonGuid));
                        if (csData.ok())
                        {
                            string addonArgumentList = csData.getText("argumentlist");
                            bool   addonIsInline     = csData.getBoolean("IsInline");
                            string jsonCommand       = "";
                            returnHtml = AddonController.getDefaultAddonOptions(core, addonArgumentList, AddonGuid, addonIsInline, csData.getText("name"), ref jsonCommand);
                        }
                    }
                }
            } catch (Exception ex) {
                cp.Site.ErrorReport(ex);
            }
            return(returnHtml);
        }
        //
        //====================================================================================================
        /// <summary>
        /// Return the collectionList file stored in the root of the addon folder.
        /// </summary>
        /// <returns></returns>
        public static string getCollectionFolderConfigXml(CoreController core)
        {
            string returnXml = "";

            try {
                string LastChangeDate             = "";
                string FolderName                 = null;
                string collectionFilePathFilename = null;
                string CollectionGuid             = null;
                string Collectionname             = null;
                //
                collectionFilePathFilename = AddonController.getPrivateFilesAddonPath() + "Collections.xml";
                returnXml = core.privateFiles.readFileText(collectionFilePathFilename);
                if (string.IsNullOrWhiteSpace(returnXml))
                {
                    //
                    LogController.logInfo(core, "Collection Folder XML is blank, rebuild start");
                    //
                    List <FolderDetail> FolderList = core.privateFiles.getFolderList(AddonController.getPrivateFilesAddonPath());
                    //
                    LogController.logInfo(core, "Collection Folder XML rebuild, FolderList.count [" + FolderList.Count + "]");
                    //
                    if (FolderList.Count > 0)
                    {
                        var collectionsFound = new List <string>();
                        foreach (FolderDetail folder in FolderList)
                        {
                            FolderName = folder.Name;
                            if (FolderName.Length > 34)
                            {
                                if (GenericController.toLCase(FolderName.left(4)) != "temp")
                                {
                                    CollectionGuid = FolderName.Substring(FolderName.Length - 32);
                                    Collectionname = FolderName.left(FolderName.Length - CollectionGuid.Length - 1);
                                    CollectionGuid = CollectionGuid.left(8) + "-" + CollectionGuid.Substring(8, 4) + "-" + CollectionGuid.Substring(12, 4) + "-" + CollectionGuid.Substring(16, 4) + "-" + CollectionGuid.Substring(20);
                                    CollectionGuid = "{" + CollectionGuid + "}";
                                    if (collectionsFound.Contains(CollectionGuid))
                                    {
                                        //
                                        // -- folder with duplicate Guid not allowed. throw;ception and block the folder
                                        LogController.logError(core, new GenericException("Add-on Collection Folder contains a mulitple collection folders with the same guid, [" + CollectionGuid + "], duplicate folder ignored [" + folder.Name + "]. Remove or Combine the mulitple instances. Then delete the collections.xml file and it will regenerate without the duplicate."));
                                    }
                                    else
                                    {
                                        collectionsFound.Add(CollectionGuid);
                                        List <FolderDetail> SubFolderList = core.privateFiles.getFolderList(AddonController.getPrivateFilesAddonPath() + FolderName + "\\");
                                        if (SubFolderList.Count > 0)
                                        {
                                            FolderDetail lastSubFolder = SubFolderList.Last <FolderDetail>();
                                            FolderName     = FolderName + "\\" + lastSubFolder.Name;
                                            LastChangeDate = lastSubFolder.Name.Substring(4, 2) + "/" + lastSubFolder.Name.Substring(6, 2) + "/" + lastSubFolder.Name.left(4);
                                            if (!GenericController.isDate(LastChangeDate))
                                            {
                                                LastChangeDate = "";
                                            }
                                        }
                                        returnXml += Environment.NewLine + "\t<Collection>";
                                        returnXml += Environment.NewLine + "\t\t<name>" + Collectionname + "</name>";
                                        returnXml += Environment.NewLine + "\t\t<guid>" + CollectionGuid + "</guid>";
                                        returnXml += Environment.NewLine + "\t\t<lastchangedate>" + LastChangeDate + "</lastchangedate>";
                                        returnXml += Environment.NewLine + "\t\t<path>" + FolderName + "</path>";
                                        returnXml += Environment.NewLine + "\t</Collection>";
                                    }
                                }
                            }
                        }
                    }
                    returnXml = "<CollectionList>" + returnXml + Environment.NewLine + "</CollectionList>";
                    core.privateFiles.saveFile(collectionFilePathFilename, returnXml);
                    //
                    LogController.logInfo(core, "Collection Folder XML is blank, rebuild finished and saved");
                    //
                }
            } catch (Exception ex) {
                LogController.logError(core, ex);
                throw;
            }
            return(returnXml);
        }
예제 #5
0
        public static IAddonController Control <TAddon>(this TAddon addon) where TAddon : IAddonContract
        {
            var ctrl = new AddonController(addon);

            return(ctrl);
        }
예제 #6
0
        //
        //====================================================================================================
        /// <summary>
        /// execute vb script
        /// </summary>
        /// <param name="addon"></param>
        /// <param name="Code"></param>
        /// <param name="EntryPoint"></param>
        /// <param name="ScriptingTimeout"></param>
        /// <param name="ScriptName"></param>
        /// <returns></returns>
        public static string execute_Script_VBScript(CoreController core, ref AddonModel addon)
        {
            string returnText = "";

            try {
                // todo - move locals
                using (var engine = new Microsoft.ClearScript.Windows.VBScriptEngine()) {
                    //var engine = new Microsoft.ClearScript.Windows.VBScriptEngine(Microsoft.ClearScript.Windows.WindowsScriptEngineFlags.EnableDebugging);
                    string entryPoint = addon.scriptingEntryPoint;
                    if (string.IsNullOrEmpty(entryPoint))
                    {
                        //
                        // -- compatibility mode, if no entry point given, if the code starts with "function myFuncton()" and add "call myFunction()"
                        int pos = addon.scriptingCode.IndexOf("function", StringComparison.CurrentCultureIgnoreCase);
                        if (pos >= 0)
                        {
                            entryPoint = addon.scriptingCode.Substring(pos + 9);
                            pos        = entryPoint.IndexOf("\r");
                            if (pos > 0)
                            {
                                entryPoint = entryPoint.Substring(0, pos);
                            }
                            pos = entryPoint.IndexOf("\n");
                            if (pos > 0)
                            {
                                entryPoint = entryPoint.Substring(0, pos);
                            }
                            pos = entryPoint.IndexOf("(");
                            if (pos > 0)
                            {
                                entryPoint = entryPoint.Substring(0, pos);
                            }
                        }
                    }
                    else
                    {
                        //
                        // -- etnry point provided, remove "()" if included and add to code
                        int pos = entryPoint.IndexOf("(");
                        if (pos > 0)
                        {
                            entryPoint = entryPoint.Substring(0, pos);
                        }
                    }
                    //
                    // -- adding cclib
                    try {
                        MainCsvScriptCompatibilityClass mainCsv = new MainCsvScriptCompatibilityClass(core);
                        engine.AddHostObject("ccLib", mainCsv);
                    } catch (Microsoft.ClearScript.ScriptEngineException ex) {
                        string errorMessage = getScriptEngineExceptionMessage(ex, "Adding cclib compatibility object ");
                        LogController.logError(core, ex, errorMessage);
                        throw new GenericException(errorMessage, ex);
                    } catch (Exception ex) {
                        LogController.logError(core, ex);
                        throw;
                    }
                    //
                    // -- adding cp
                    try {
                        engine.AddHostObject("cp", core.cpParent);
                    } catch (Microsoft.ClearScript.ScriptEngineException ex) {
                        string errorMessage = getScriptEngineExceptionMessage(ex, "Adding cp object ");
                        LogController.logError(core, ex, errorMessage);
                        throw new GenericException(errorMessage, ex);
                    } catch (Exception ex) {
                        LogController.logError(core, ex);
                        throw;
                    }
                    //
                    // -- execute code
                    try {
                        engine.Execute(addon.scriptingCode);
                        object returnObj = engine.Evaluate(entryPoint);
                        if (returnObj != null)
                        {
                            if (returnObj.GetType() == typeof(String))
                            {
                                returnText = (String)returnObj;
                            }
                        }
                    } catch (Microsoft.ClearScript.ScriptEngineException ex) {
                        string errorMessage = getScriptEngineExceptionMessage(ex, "executing script ");
                        LogController.logError(core, ex, errorMessage);
                        throw new GenericException(errorMessage, ex);
                    } catch (Exception ex) {
                        string addonDescription = AddonController.getAddonDescription(core, addon);
                        string errorMessage     = "Error executing addon script, " + addonDescription;
                        throw new GenericException(errorMessage, ex);
                    }
                }
            } catch (Exception ex) {
                LogController.logError(core, ex);
                throw;
            }
            return(returnText);
        }
예제 #7
0
        //====================================================================================================
        //
        public static void housekeep(CoreController core)
        {
            try {
                //
                LogController.logInfo(core, "HousekeepDaily, addon folder");
                //
                bool        loadOK = true;
                XmlDocument Doc    = new XmlDocument();
                string      hint   = "";
                try {
                    string collectionFileFilename = AddonController.getPrivateFilesAddonPath() + "Collections.xml";
                    string collectionFileContent  = core.privateFiles.readFileText(collectionFileFilename);
                    Doc.LoadXml(collectionFileContent);
                } catch (Exception ex) {
                    LogController.logInfo(core, "RegisterAddonFolder, Hint=[" + hint + "], Error loading Collections.xml file, ex [" + ex + "]");
                    loadOK = false;
                }
                if (loadOK)
                {
                    //
                    LogController.logInfo(core, "Collection.xml loaded ok");
                    //
                    if (GenericController.toLCase(Doc.DocumentElement.Name) != GenericController.toLCase(CollectionListRootNode))
                    {
                        LogController.logInfo(core, "RegisterAddonFolder, Hint=[" + hint + "], The Collections.xml file has an invalid root node, [" + Doc.DocumentElement.Name + "] was received and [" + CollectionListRootNode + "] was expected.");
                    }
                    else
                    {
                        //
                        LogController.logInfo(core, "Collection.xml root name ok");
                        //
                        {
                            int NodeCnt = 0;
                            foreach (XmlNode LocalListNode in Doc.DocumentElement.ChildNodes)
                            {
                                //
                                // Get the collection path
                                //
                                string   collectionPath = "";
                                string   localGuid      = "";
                                string   localName      = "no name found";
                                DateTime lastChangeDate = default;
                                if (LocalListNode.Name.ToLower(CultureInfo.InvariantCulture).Equals("collection"))
                                {
                                    localGuid = "";
                                    foreach (XmlNode CollectionNode in LocalListNode.ChildNodes)
                                    {
                                        switch (CollectionNode.Name.ToLower(CultureInfo.InvariantCulture))
                                        {
                                        case "name":
                                            //
                                            localName = CollectionNode.InnerText.ToLower(CultureInfo.InvariantCulture);
                                            break;

                                        case "guid":
                                            //
                                            localGuid = CollectionNode.InnerText.ToLower(CultureInfo.InvariantCulture);
                                            break;

                                        case "path":
                                            //
                                            collectionPath = CollectionNode.InnerText.ToLower(CultureInfo.InvariantCulture);
                                            break;

                                        case "lastchangedate":
                                            lastChangeDate = GenericController.encodeDate(CollectionNode.InnerText);
                                            break;

                                        default:
                                            LogController.logWarn(core, "Collection node contains unrecognized child [" + CollectionNode.Name.ToLower(CultureInfo.InvariantCulture) + "]");
                                            break;
                                        }
                                    }
                                }
                                //
                                LogController.logInfo(core, "Node[" + NodeCnt + "], LocalName=[" + localName + "], LastChangeDate=[" + lastChangeDate + "], CollectionPath=[" + collectionPath + "], LocalGuid=[" + localGuid + "]");
                                //
                                // Go through all subpaths of the collection path, register the version match, unregister all others
                                //
                                if (string.IsNullOrEmpty(collectionPath))
                                {
                                    //
                                    LogController.logInfo(core, "no collection path, skipping");
                                    //
                                }
                                else
                                {
                                    collectionPath = GenericController.toLCase(collectionPath);
                                    string CollectionRootPath = collectionPath;
                                    int    Pos = CollectionRootPath.LastIndexOf("\\") + 1;
                                    if (Pos <= 0)
                                    {
                                        //
                                        LogController.logInfo(core, "CollectionPath has no '\\', skipping");
                                        //
                                    }
                                    else
                                    {
                                        CollectionRootPath = CollectionRootPath.left(Pos - 1);
                                        string Path = AddonController.getPrivateFilesAddonPath() + CollectionRootPath + "\\";
                                        List <FolderDetail> folderList = new List <FolderDetail>();
                                        if (core.privateFiles.pathExists(Path))
                                        {
                                            folderList = core.privateFiles.getFolderList(Path);
                                        }
                                        if (folderList.Count == 0)
                                        {
                                            //
                                            LogController.logInfo(core, "no subfolders found in physical path [" + Path + "], skipping");
                                            //
                                        }
                                        else
                                        {
                                            int folderPtr = -1;
                                            foreach (FolderDetail dir in folderList)
                                            {
                                                folderPtr += 1;
                                                //
                                                // -- check for empty foler name
                                                if (string.IsNullOrEmpty(dir.Name))
                                                {
                                                    //
                                                    LogController.logInfo(core, "....empty folder skipped [" + dir.Name + "]");
                                                    continue;
                                                }
                                                //
                                                // -- preserve folder in use
                                                if (CollectionRootPath + "\\" + dir.Name == collectionPath)
                                                {
                                                    LogController.logInfo(core, "....active folder preserved [" + dir.Name + "]");
                                                    continue;
                                                }
                                                //
                                                // preserve last three folders
                                                if (folderPtr >= (folderList.Count - 3))
                                                {
                                                    LogController.logInfo(core, "....last 3 folders reserved [" + dir.Name + "]");
                                                    continue;
                                                }
                                                //
                                                LogController.logInfo(core, "....Deleting unused folder [" + Path + dir.Name + "]");
                                                core.privateFiles.deleteFolder(Path + dir.Name);
                                            }
                                        }
                                    }
                                }
                                NodeCnt += 1;
                            }
                        }
                    }
                }
                //
                LogController.logInfo(core, "Exiting RegisterAddonFolder");
            } catch (Exception ex) {
                LogController.logError(core, ex);
            }
        }
예제 #8
0
        //
        // ====================================================================================================
        /// <summary>
        /// create the colleciton zip file and return the pathFilename in the Cdn
        /// </summary>
        /// <param name="cp"></param>
        /// <param name="collectionId"></param>
        /// <returns></returns>
        public static string createCollectionZip_returnCdnPathFilename(CPBaseClass cp, AddonCollectionModel collection)
        {
            string cdnExportZip_Filename = "";

            try {
                if ((collection == null))
                {
                    //
                    // -- exit with error
                    cp.UserError.Add("The collection you selected could not be found");
                    return(string.Empty);
                }
                using (CPCSBaseClass CS = cp.CSNew()) {
                    CS.OpenRecord("Add-on Collections", collection.id);
                    if (!CS.OK())
                    {
                        //
                        // -- exit with error
                        cp.UserError.Add("The collection you selected could not be found");
                        return(string.Empty);
                    }
                    string collectionXml  = "<?xml version=\"1.0\" encoding=\"windows-1252\"?>";
                    string CollectionGuid = CS.GetText("ccGuid");
                    if (CollectionGuid == "")
                    {
                        CollectionGuid = cp.Utils.CreateGuid();
                        CS.SetField("ccGuid", CollectionGuid);
                    }
                    string onInstallAddonGuid = "";
                    if ((CS.FieldOK("onInstallAddonId")))
                    {
                        int onInstallAddonId = CS.GetInteger("onInstallAddonId");
                        if ((onInstallAddonId > 0))
                        {
                            AddonModel addon = AddonModel.create <AddonModel>(cp, onInstallAddonId);
                            if ((addon != null))
                            {
                                onInstallAddonGuid = addon.ccguid;
                            }
                        }
                    }
                    string CollectionName = CS.GetText("name");
                    collectionXml        += System.Environment.NewLine + "<Collection";
                    collectionXml        += " name=\"" + CollectionName + "\"";
                    collectionXml        += " guid=\"" + CollectionGuid + "\"";
                    collectionXml        += " system=\"" + GenericController.getYesNo(CS.GetBoolean("system")) + "\"";
                    collectionXml        += " updatable=\"" + GenericController.getYesNo(CS.GetBoolean("updatable")) + "\"";
                    collectionXml        += " blockNavigatorNode=\"" + GenericController.getYesNo(CS.GetBoolean("blockNavigatorNode")) + "\"";
                    collectionXml        += " onInstallAddonGuid=\"" + onInstallAddonGuid + "\"";
                    collectionXml        += ">";
                    cdnExportZip_Filename = encodeFilename(cp, CollectionName + ".zip");
                    List <string> tempPathFileList = new List <string>();
                    string        tempExportPath   = "CollectionExport" + Guid.NewGuid().ToString() + @"\";
                    //
                    // --resource executable files
                    string        wwwFileList          = CS.GetText("wwwFileList");
                    string        ContentFileList      = CS.GetText("ContentFileList");
                    List <string> execFileList         = ExportResourceListController.getResourceFileList(cp, CS.GetText("execFileList"), CollectionGuid);
                    string        execResourceNodeList = ExportResourceListController.getResourceNodeList(cp, execFileList, CollectionGuid, tempPathFileList, tempExportPath);
                    //
                    // helpLink
                    //
                    if (CS.FieldOK("HelpLink"))
                    {
                        collectionXml += System.Environment.NewLine + "\t" + "<HelpLink>" + System.Net.WebUtility.HtmlEncode(CS.GetText("HelpLink")) + "</HelpLink>";
                    }
                    //
                    // Help
                    //
                    collectionXml += System.Environment.NewLine + "\t" + "<Help>" + System.Net.WebUtility.HtmlEncode(CS.GetText("Help")) + "</Help>";
                    //
                    // Addons
                    //
                    string IncludeSharedStyleGuidList = "";
                    string IncludeModuleGuidList      = "";
                    foreach (var addon in DbBaseModel.createList <AddonModel>(cp, "collectionid=" + collection.id))
                    {
                        //
                        // -- style sheet is in the wwwroot
                        if (!string.IsNullOrEmpty(addon.stylesLinkHref))
                        {
                            string filename = addon.stylesLinkHref.Replace("/", "\\");
                            if (filename.Substring(0, 1).Equals(@"\"))
                            {
                                filename = filename.Substring(1);
                            }
                            if (!cp.WwwFiles.FileExists(filename))
                            {
                                cp.WwwFiles.Save(filename, @"/* css file created as exported for addon [" + addon.name + "], collection [" + collection.name + "] in site [" + cp.Site.Name + "] */");
                            }
                            wwwFileList += System.Environment.NewLine + addon.stylesLinkHref;
                        }
                        //
                        // -- js is in the wwwroot
                        if (!string.IsNullOrEmpty(addon.jsHeadScriptSrc))
                        {
                            string filename = addon.jsHeadScriptSrc.Replace("/", "\\");
                            if (filename.Substring(0, 1).Equals(@"\"))
                            {
                                filename = filename.Substring(1);
                            }
                            if (!cp.WwwFiles.FileExists(filename))
                            {
                                cp.WwwFiles.Save(filename, @"// javascript file created as exported for addon [" + addon.name + "], collection [" + collection.name + "] in site [" + cp.Site.Name + "]");
                            }
                            wwwFileList += System.Environment.NewLine + addon.jsHeadScriptSrc;
                        }
                        collectionXml += ExportAddonController.getAddonNode(cp, addon.id, ref IncludeModuleGuidList, ref IncludeSharedStyleGuidList);
                    }
                    //
                    // Layouts
                    foreach (var layout in DbBaseModel.createList <LayoutModel>(cp, "(installedByCollectionId=" + collection.id + ")"))
                    {
                        collectionXml += ExportLayoutController.get(cp, layout);
                    }
                    //
                    // Templates
                    foreach (var template in DbBaseModel.createList <PageTemplateModel>(cp, "(collectionId=" + collection.id + ")"))
                    {
                        collectionXml += ExportTemplateController.get(cp, template);
                    }
                    //
                    // Data Records
                    string DataRecordList = CS.GetText("DataRecordList");
                    collectionXml += ExportDataRecordController.getNodeList(cp, DataRecordList, tempPathFileList, tempExportPath);
                    //
                    // CDef
                    foreach (Contensive.Models.Db.ContentModel content in createListFromCollection(cp, collection.id))
                    {
                        if ((string.IsNullOrEmpty(content.ccguid)))
                        {
                            content.ccguid = cp.Utils.CreateGuid();
                            content.save(cp);
                        }
                        XmlController xmlTool = new XmlController(cp);
                        string        Node    = xmlTool.GetXMLContentDefinition3(content.name);
                        //
                        // remove the <collection> top node
                        //
                        int Pos = Strings.InStr(1, Node, "<cdef", CompareMethod.Text);
                        if (Pos > 0)
                        {
                            Node = Strings.Mid(Node, Pos);
                            Pos  = Strings.InStr(1, Node, "</cdef>", CompareMethod.Text);
                            if (Pos > 0)
                            {
                                Node           = Strings.Mid(Node, 1, Pos + 6);
                                collectionXml += System.Environment.NewLine + "\t" + Node;
                            }
                        }
                    }
                    //
                    // Scripting Modules
                    if (IncludeModuleGuidList != "")
                    {
                        string[] Modules = Strings.Split(IncludeModuleGuidList, System.Environment.NewLine);
                        for (var Ptr = 0; Ptr <= Information.UBound(Modules); Ptr++)
                        {
                            string ModuleGuid = Modules[Ptr];
                            if (ModuleGuid != "")
                            {
                                using (CPCSBaseClass CS2 = cp.CSNew()) {
                                    CS2.Open("Scripting Modules", "ccguid=" + cp.Db.EncodeSQLText(ModuleGuid));
                                    if (CS2.OK())
                                    {
                                        string Code = CS2.GetText("code").Trim();
                                        Code           = EncodeCData(Code);
                                        collectionXml += System.Environment.NewLine + "\t" + "<ScriptingModule Name=\"" + System.Net.WebUtility.HtmlEncode(CS2.GetText("name")) + "\" guid=\"" + ModuleGuid + "\">" + Code + "</ScriptingModule>";
                                    }
                                    CS2.Close();
                                }
                            }
                        }
                    }
                    //
                    // shared styles
                    string[] recordGuids;
                    string   recordGuid;
                    if ((IncludeSharedStyleGuidList != ""))
                    {
                        recordGuids = Strings.Split(IncludeSharedStyleGuidList, System.Environment.NewLine);
                        for (var Ptr = 0; Ptr <= Information.UBound(recordGuids); Ptr++)
                        {
                            recordGuid = recordGuids[Ptr];
                            if (recordGuid != "")
                            {
                                using (CPCSBaseClass CS2 = cp.CSNew()) {
                                    CS2.Open("Shared Styles", "ccguid=" + cp.Db.EncodeSQLText(recordGuid));
                                    if (CS2.OK())
                                    {
                                        collectionXml += System.Environment.NewLine + "\t" + "<SharedStyle"
                                                         + " Name=\"" + System.Net.WebUtility.HtmlEncode(CS2.GetText("name")) + "\""
                                                         + " guid=\"" + recordGuid + "\""
                                                         + " alwaysInclude=\"" + CS2.GetBoolean("alwaysInclude") + "\""
                                                         + " prefix=\"" + System.Net.WebUtility.HtmlEncode(CS2.GetText("prefix")) + "\""
                                                         + " suffix=\"" + System.Net.WebUtility.HtmlEncode(CS2.GetText("suffix")) + "\""
                                                         + " sortOrder=\"" + System.Net.WebUtility.HtmlEncode(CS2.GetText("sortOrder")) + "\""
                                                         + ">"
                                                         + EncodeCData(CS2.GetText("styleFilename").Trim())
                                                         + "</SharedStyle>";
                                    }
                                    CS2.Close();
                                }
                            }
                        }
                    }
                    //
                    // Import Collections
                    {
                        string Node = "";
                        using (CPCSBaseClass CS3 = cp.CSNew()) {
                            if (CS3.Open("Add-on Collection Parent Rules", "parentid=" + collection.id))
                            {
                                do
                                {
                                    using (CPCSBaseClass CS2 = cp.CSNew()) {
                                        if (CS2.OpenRecord("Add-on Collections", CS3.GetInteger("childid")))
                                        {
                                            string Guid = CS2.GetText("ccGuid");
                                            if (Guid == "")
                                            {
                                                Guid = cp.Utils.CreateGuid();
                                                CS2.SetField("ccGuid", Guid);
                                            }

                                            Node = Node + System.Environment.NewLine + "\t" + "<ImportCollection name=\"" + System.Net.WebUtility.HtmlEncode(CS2.GetText("name")) + "\">" + Guid + "</ImportCollection>";
                                        }

                                        CS2.Close();
                                    }

                                    CS3.GoNext();
                                }while (CS3.OK());
                            }
                            CS3.Close();
                        }
                        collectionXml += Node;
                    }
                    //
                    // wwwFileList
                    if (wwwFileList != "")
                    {
                        string[] Files = Strings.Split(wwwFileList, System.Environment.NewLine);
                        for (int Ptr = 0; Ptr <= Information.UBound(Files); Ptr++)
                        {
                            string pathFilename = Files[Ptr];
                            if (pathFilename != "")
                            {
                                pathFilename = Strings.Replace(pathFilename, @"\", "/");
                                string path     = "";
                                string filename = pathFilename;
                                int    Pos      = Strings.InStrRev(pathFilename, "/");
                                if (Pos > 0)
                                {
                                    filename = Strings.Mid(pathFilename, Pos + 1);
                                    path     = Strings.Mid(pathFilename, 1, Pos - 1);
                                }
                                string fileExtension = System.IO.Path.GetExtension(filename);
                                pathFilename = Strings.Replace(pathFilename, "/", @"\");
                                if (tempPathFileList.Contains(tempExportPath + filename))
                                {
                                    //
                                    // -- the path already has a file with this name
                                    cp.UserError.Add("There was an error exporting this collection because there were multiple files with the same filename [" + filename + "]");
                                }
                                else if (fileExtension.ToUpperInvariant().Equals(".ZIP"))
                                {
                                    //
                                    // -- zip files come from the collection folder
                                    CoreController core           = ((CPClass)cp).core;
                                    string         addonPath      = AddonController.getPrivateFilesAddonPath();
                                    string         collectionPath = CollectionFolderController.getCollectionConfigFolderPath(core, collection.ccguid);
                                    if (!cp.PrivateFiles.FileExists(addonPath + collectionPath + filename))
                                    {
                                        //
                                        // - not there
                                        cp.UserError.Add("There was an error exporting this collection because the zip file [" + pathFilename + "] was not found in the collection path [" + collectionPath + "].");
                                    }
                                    else
                                    {
                                        //
                                        // -- copy file from here
                                        cp.PrivateFiles.Copy(addonPath + collectionPath + filename, tempExportPath + filename, cp.TempFiles);
                                        tempPathFileList.Add(tempExportPath + filename);
                                        collectionXml += System.Environment.NewLine + "\t" + "<Resource name=\"" + System.Net.WebUtility.HtmlEncode(filename) + "\" type=\"www\" path=\"" + System.Net.WebUtility.HtmlEncode(path) + "\" />";
                                    }
                                }
                                else if ((!cp.WwwFiles.FileExists(pathFilename)))
                                {
                                    cp.UserError.Add("There was an error exporting this collection because the www file [" + pathFilename + "] was not found.");
                                }
                                else
                                {
                                    cp.WwwFiles.Copy(pathFilename, tempExportPath + filename, cp.TempFiles);
                                    tempPathFileList.Add(tempExportPath + filename);
                                    collectionXml += System.Environment.NewLine + "\t" + "<Resource name=\"" + System.Net.WebUtility.HtmlEncode(filename) + "\" type=\"www\" path=\"" + System.Net.WebUtility.HtmlEncode(path) + "\" />";
                                }
                            }
                        }
                    }
                    //
                    // ContentFileList
                    //
                    if (true)
                    {
                        if (ContentFileList != "")
                        {
                            string[] Files = Strings.Split(ContentFileList, System.Environment.NewLine);
                            for (var Ptr = 0; Ptr <= Information.UBound(Files); Ptr++)
                            {
                                string PathFilename = Files[Ptr];
                                if (PathFilename != "")
                                {
                                    PathFilename = Strings.Replace(PathFilename, @"\", "/");
                                    string Path     = "";
                                    string Filename = PathFilename;
                                    int    Pos      = Strings.InStrRev(PathFilename, "/");
                                    if (Pos > 0)
                                    {
                                        Filename = Strings.Mid(PathFilename, Pos + 1);
                                        Path     = Strings.Mid(PathFilename, 1, Pos - 1);
                                    }
                                    if (tempPathFileList.Contains(tempExportPath + Filename))
                                    {
                                        cp.UserError.Add("There was an error exporting this collection because there were multiple files with the same filename [" + Filename + "]");
                                    }
                                    else if ((!cp.CdnFiles.FileExists(PathFilename)))
                                    {
                                        cp.UserError.Add("There was an error exporting this collection because the cdn file [" + PathFilename + "] was not found.");
                                    }
                                    else
                                    {
                                        cp.CdnFiles.Copy(PathFilename, tempExportPath + Filename, cp.TempFiles);
                                        tempPathFileList.Add(tempExportPath + Filename);
                                        collectionXml += System.Environment.NewLine + "\t" + "<Resource name=\"" + System.Net.WebUtility.HtmlEncode(Filename) + "\" type=\"content\" path=\"" + System.Net.WebUtility.HtmlEncode(Path) + "\" />";
                                    }
                                }
                            }
                        }
                    }
                    //
                    // ExecFileListNode
                    //
                    collectionXml += execResourceNodeList;
                    //
                    // Other XML
                    //
                    string OtherXML;
                    OtherXML = CS.GetText("otherxml");
                    if (Strings.Trim(OtherXML) != "")
                    {
                        collectionXml += System.Environment.NewLine + OtherXML;
                    }
                    collectionXml += System.Environment.NewLine + "</Collection>";
                    CS.Close();
                    string tempExportXml_Filename = encodeFilename(cp, CollectionName + ".xml");
                    //
                    // Save the installation file and add it to the archive
                    //
                    cp.TempFiles.Save(tempExportPath + tempExportXml_Filename, collectionXml);
                    if (!tempPathFileList.Contains(tempExportPath + tempExportXml_Filename))
                    {
                        tempPathFileList.Add(tempExportPath + tempExportXml_Filename);
                    }
                    string tempExportZip_Filename = encodeFilename(cp, CollectionName + ".zip");
                    //
                    // -- zip up the folder to make the collection zip file in temp filesystem
                    zipTempCdnFile(cp, tempExportPath + tempExportZip_Filename, tempPathFileList);
                    //
                    // -- copy the collection zip file to the cdn filesystem as the download link
                    cp.TempFiles.Copy(tempExportPath + tempExportZip_Filename, cdnExportZip_Filename, cp.CdnFiles);
                    //
                    // -- delete the temp folder
                    cp.TempFiles.DeleteFolder(tempExportPath);
                }
            } catch (Exception ex) {
                cp.Site.ErrorReport(ex);
            }
            return(cdnExportZip_Filename);
        }
        //
        //====================================================================================================
        /// <summary>
        /// Builds collection folders for a collectionZip file
        /// unzip a folder and if the collection is not in the collections installed or the collectionsToInstall, save the collection to the appropriate collection folder and add it to the collectionsToInstall
        /// </summary>
        /// <param name="core"></param>
        /// <param name="sourceTempFolderPathFilename"></param>
        /// <param name="CollectionLastChangeDate"></param>
        /// <param name="collectionGuid"></param>
        /// <param name="return_ErrorMessage"></param>
        /// <param name="collectionsDownloaded">collection guids that have been saved to the collection folder and need to be saved to the database druing this install.</param>
        /// <param name="collectionsInstalledList">collection guids that have been saved to the database during this install.</param>
        /// <param name="collectionsBuildingFolder">folder building is recursive. These are the collection guids whose folders are currently being built.</param>
        /// <returns></returns>
        public static bool buildCollectionFolderFromCollectionZip(CoreController core, Stack <string> contextLog, string sourceTempFolderPathFilename, DateTime CollectionLastChangeDate, ref string return_ErrorMessage, ref List <string> collectionsDownloaded, ref List <string> collectionsInstalledList, ref List <string> collectionsBuildingFolder)
        {
            try {
                //
                contextLog.Push(MethodInfo.GetCurrentMethod().Name + ", [" + sourceTempFolderPathFilename + "]");
                traceContextLog(core, contextLog);
                //
                string collectionPath     = "";
                string collectionFilename = "";
                core.tempFiles.splitDosPathFilename(sourceTempFolderPathFilename, ref collectionPath, ref collectionFilename);
                string CollectionVersionFolderName = "";
                if (!core.tempFiles.pathExists(collectionPath))
                {
                    //
                    // return false, The working folder is not there
                    return_ErrorMessage = "<p>There was a problem with the installation. The installation folder is not valid.</p>";
                    LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, CheckFileFolder was false for the temp folder [" + collectionPath + "]");
                    return(false);
                }
                //
                LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, processing files in temp folder [" + collectionPath + "]");
                //
                // --move collection file to a temp directory
                // -- use try-finally to delete temp folder
                string tmpInstallPath = "tmpInstallCollection" + GenericController.getGUIDNaked() + "\\";
                try {
                    core.tempFiles.copyFile(sourceTempFolderPathFilename, tmpInstallPath + collectionFilename);
                    if (collectionFilename.ToLowerInvariant().Substring(collectionFilename.Length - 4) == ".zip")
                    {
                        core.tempFiles.unzipFile(tmpInstallPath + collectionFilename);
                        core.tempFiles.deleteFile(tmpInstallPath + collectionFilename);
                    }
                    //
                    // -- find xml file in temp folder and process it
                    bool CollectionXmlFileFound = false;
                    foreach (FileDetail file in core.tempFiles.getFileList(tmpInstallPath))
                    {
                        if (file.Name.Substring(file.Name.Length - 4).ToLower(CultureInfo.InvariantCulture) == ".xml")
                        {
                            //
                            LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", build collection folder for Collection file [" + file.Name + "]");
                            //
                            XmlDocument CollectionFile = new XmlDocument();
                            try {
                                CollectionFile.LoadXml(core.tempFiles.readFileText(tmpInstallPath + file.Name));
                            } catch (Exception ex) {
                                //
                                // -- There was a parse error in this xml file. Set the return message and the flag
                                // -- If another xml files shows up, and process OK it will cover this error
                                return_ErrorMessage = "There was a problem installing the Collection File [" + tmpInstallPath + file.Name + "]. The error reported was [" + ex.Message + "].";
                                LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, error reading collection [" + sourceTempFolderPathFilename + "]");
                                continue;
                            }
                            string CollectionFileBaseName = GenericController.toLCase(CollectionFile.DocumentElement.Name);
                            if ((CollectionFileBaseName != "contensivecdef") && (CollectionFileBaseName != CollectionFileRootNode) && (CollectionFileBaseName != GenericController.toLCase(CollectionFileRootNodeOld)))
                            {
                                //
                                // -- Not a problem, this is just not a collection file
                                LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, xml base name wrong [" + CollectionFileBaseName + "]");
                                continue;
                            }
                            bool IsFound = false;
                            //
                            // Collection File
                            //
                            string Collectionname = XmlController.getXMLAttribute(core, ref IsFound, CollectionFile.DocumentElement, "name", "");
                            string collectionGuid = XmlController.getXMLAttribute(core, ref IsFound, CollectionFile.DocumentElement, "guid", Collectionname);
                            if ((!collectionsInstalledList.Contains(collectionGuid.ToLower(CultureInfo.InvariantCulture))) && (!collectionsDownloaded.Contains(collectionGuid.ToLower(CultureInfo.InvariantCulture))))
                            {
                                if (string.IsNullOrEmpty(Collectionname))
                                {
                                    //
                                    // ----- Error condition -- it must have a collection name
                                    //
                                    return_ErrorMessage = "<p>There was a problem with this Collection. The collection file does not have a collection name.</p>";
                                    LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, collection has no name");
                                    continue;
                                }
                                //
                                //------------------------------------------------------------------
                                // Build Collection folder structure in /Add-ons folder
                                //------------------------------------------------------------------
                                //
                                collectionsDownloaded.Add(collectionGuid.ToLower(CultureInfo.InvariantCulture));
                                CollectionXmlFileFound = true;
                                if (string.IsNullOrEmpty(collectionGuid))
                                {
                                    //
                                    // must have a guid
                                    collectionGuid = Collectionname;
                                }
                                //
                                //
                                CollectionVersionFolderName = verifyCollectionVersionFolderName(core, collectionGuid, Collectionname);
                                string CollectionVersionFolder = AddonController.getPrivateFilesAddonPath() + CollectionVersionFolderName;
                                //
                                core.tempFiles.copyPath(tmpInstallPath, CollectionVersionFolder, core.privateFiles);
                                //
                                // -- iterate through all nodes of this collection xml file and install all dependencies
                                foreach (XmlNode metaDataSection in CollectionFile.DocumentElement.ChildNodes)
                                {
                                    string ChildCollectionGUID = null;
                                    string ChildCollectionName = null;
                                    bool   Found = false;
                                    switch (GenericController.toLCase(metaDataSection.Name))
                                    {
                                    case "resource":
                                        break;

                                    case "getcollection":
                                    case "importcollection":
                                        //
                                        // -- Download Collection file into install folder
                                        ChildCollectionName = XmlController.getXMLAttribute(core, ref Found, metaDataSection, "name", "");
                                        ChildCollectionGUID = XmlController.getXMLAttribute(core, ref Found, metaDataSection, "guid", metaDataSection.InnerText);
                                        if (string.IsNullOrEmpty(ChildCollectionGUID))
                                        {
                                            ChildCollectionGUID = metaDataSection.InnerText;
                                        }
                                        ChildCollectionGUID = GenericController.normalizeGuid(ChildCollectionGUID);
                                        string statusMsg = "Installing collection [" + ChildCollectionName + ", " + ChildCollectionGUID + "] referenced from collection [" + Collectionname + "]";
                                        LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, getCollection or importcollection, childCollectionName [" + ChildCollectionName + "], childCollectionGuid [" + ChildCollectionGUID + "]");
                                        if (GenericController.strInstr(1, CollectionVersionFolder, ChildCollectionGUID, 1) == 0)
                                        {
                                            if (string.IsNullOrEmpty(ChildCollectionGUID))
                                            {
                                                //
                                                // -- Needs a GUID to install
                                                return_ErrorMessage = statusMsg + ". The installation can not continue because an imported collection could not be downloaded because it does not include a valid GUID.";
                                                LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, return message [" + return_ErrorMessage + "]");
                                            }
                                            else
                                            {
                                                if ((!collectionsBuildingFolder.Contains(ChildCollectionGUID)) && (!collectionsDownloaded.Contains(ChildCollectionGUID)) && (!collectionsInstalledList.Contains(ChildCollectionGUID)))
                                                {
                                                    //
                                                    // -- add to the list of building folders to block recursive loop
                                                    collectionsBuildingFolder.Add(ChildCollectionGUID);
                                                    LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, [" + ChildCollectionGUID + "], not found so needs to be installed");
                                                    //
                                                    // If it is not already installed, download and install it also
                                                    //
                                                    string   workingTempPath = GenericController.getGUIDNaked() + "\\";
                                                    DateTime libraryCollectionLastModifiedDate = default(DateTime);
                                                    try {
                                                        //
                                                        // try-finally to delete the working folder
                                                        if (!CollectionLibraryController.downloadCollectionFromLibrary(core, workingTempPath, ChildCollectionGUID, ref libraryCollectionLastModifiedDate, ref return_ErrorMessage))
                                                        {
                                                            //
                                                            // -- did not download correctly
                                                            LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, [" + statusMsg + "], downloadCollectionFiles returned error state, message [" + return_ErrorMessage + "]");
                                                            if (string.IsNullOrEmpty(return_ErrorMessage))
                                                            {
                                                                return_ErrorMessage = statusMsg + ". The installation can not continue because there was an unknown error while downloading the necessary collection file, [" + ChildCollectionGUID + "].";
                                                            }
                                                            else
                                                            {
                                                                return_ErrorMessage = statusMsg + ". The installation can not continue because there was an error while downloading the necessary collection file, guid [" + ChildCollectionGUID + "]. The error was [" + return_ErrorMessage + "]";
                                                            }
                                                        }
                                                        else
                                                        {
                                                            LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, libraryCollectionLastChangeDate [" + libraryCollectionLastModifiedDate.ToString() + "].");
                                                            bool installDependentCollection = true;
                                                            var  localCollectionConfig      = CollectionFolderModel.getCollectionFolderConfig(core, ChildCollectionGUID);
                                                            if (localCollectionConfig == null)
                                                            {
                                                                //
                                                                // -- collection not installed, ok to install
                                                                LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, collection");
                                                            }
                                                            else
                                                            {
                                                                LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, localCollectionConfig.lastChangeDate [" + localCollectionConfig.lastChangeDate.ToString() + "].");
                                                                if (localCollectionConfig.lastChangeDate < libraryCollectionLastModifiedDate)
                                                                {
                                                                    //
                                                                    // -- downloaded collection is newer than installed collection, reinstall
                                                                    LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, **** local version is older than library, needs to reinstall.");
                                                                }
                                                                else
                                                                {
                                                                    //
                                                                    // -- download is older than installed, skip the rest of the xml file processing
                                                                    installDependentCollection = false;
                                                                    LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, **** local version is newer or the same as library, can skip install.");
                                                                    break;
                                                                }
                                                            }
                                                            if (installDependentCollection)
                                                            {
                                                                //
                                                                // -- install the downloaded file
                                                                LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, collection missing or needs to be updated.");
                                                                if (!buildCollectionFoldersFromCollectionZips(core, contextLog, workingTempPath, libraryCollectionLastModifiedDate, ref collectionsDownloaded, ref return_ErrorMessage, ref collectionsInstalledList, ref collectionsBuildingFolder))
                                                                {
                                                                    LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, [" + statusMsg + "], BuildLocalCollectionFolder returned error state, message [" + return_ErrorMessage + "]");
                                                                    if (string.IsNullOrEmpty(return_ErrorMessage))
                                                                    {
                                                                        return_ErrorMessage = statusMsg + ". The installation can not continue because there was an unknown error installing the included collection file, guid [" + ChildCollectionGUID + "].";
                                                                    }
                                                                    else
                                                                    {
                                                                        return_ErrorMessage = statusMsg + ". The installation can not continue because there was an unknown error installing the included collection file, guid [" + ChildCollectionGUID + "]. The error was [" + return_ErrorMessage + "]";
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    } catch (Exception) {
                                                        //
                                                        // -- exception in try-finally for folder handling, just rethrow to the catch for hte method
                                                        throw;
                                                    } finally {
                                                        //
                                                        // -- remove child installation working folder
                                                        core.tempFiles.deleteFolder(workingTempPath);
                                                        //
                                                        // -- no longer building this folder
                                                        collectionsBuildingFolder.Remove(ChildCollectionGUID);
                                                    }
                                                }
                                            }
                                        }
                                        break;
                                    }
                                    if (!string.IsNullOrEmpty(return_ErrorMessage))
                                    {
                                        //
                                        // -- if error during xml processing, skip the rest of the xml nodes and go to the next file.
                                        break;
                                    }
                                }
                            }
                            if (!string.IsNullOrEmpty(return_ErrorMessage))
                            {
                                //
                                // -- stop processing xml nodes if error
                                break;
                            }
                            //
                            // If the collection parsed correctly, update the Collections.xml file and exit loop
                            updateCollectionFolderConfig(core, Collectionname, collectionGuid, CollectionLastChangeDate, CollectionVersionFolderName);
                            break;
                        }
                        if (!string.IsNullOrEmpty(return_ErrorMessage))
                        {
                            //
                            // -- stop files if error
                            break;
                        }
                    }
                    //
                    // -- all files finished
                    if (string.IsNullOrEmpty(return_ErrorMessage) && !CollectionXmlFileFound)
                    {
                        //
                        // no errors, but xml file not found. Make an error
                        return_ErrorMessage = "<p>There was a problem with the installation. The collection zip was not downloaded successfully.</p>";
                    }
                } catch (Exception) {
                    throw;
                } finally {
                    //
                    // delete the tmp working folder
                    core.tempFiles.deleteFolder(tmpInstallPath);
                }
                //
                LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, Exiting with ErrorMessage [" + return_ErrorMessage + "]");
                //
                return(string.IsNullOrEmpty(return_ErrorMessage));
            } catch (Exception ex) {
                LogController.logError(core, ex);
                throw;
            } finally {
                contextLog.Pop();
            }
        }
        //
        //======================================================================================================
        /// <summary>
        /// determine or create a collection version path (/private/addons/collectionFolder/collectionVersion)
        /// </summary>
        /// <param name="core"></param>
        /// <param name="collectionGuid"></param>
        /// <param name="CollectionName"></param>
        /// <returns></returns>
        public static string verifyCollectionVersionFolderName(CoreController core, string collectionGuid, string CollectionName)
        {
            collectionGuid = GenericController.normalizeGuid(collectionGuid);
            string CollectionVersionFolderName = getCollectionConfigFolderPath(core, collectionGuid);
            string CollectionFolderName        = "";

            if (!string.IsNullOrEmpty(CollectionVersionFolderName))
            {
                //
                // This is an upgrade
                //
                int Pos = GenericController.strInstr(1, CollectionVersionFolderName, "\\");
                if (Pos > 0)
                {
                    CollectionFolderName = CollectionVersionFolderName.left(Pos - 1);
                }
            }
            else
            {
                //
                // This is an install
                //
                CollectionFolderName = collectionGuid;
                CollectionFolderName = GenericController.strReplace(CollectionFolderName, "{", "");
                CollectionFolderName = GenericController.strReplace(CollectionFolderName, "}", "");
                CollectionFolderName = GenericController.strReplace(CollectionFolderName, "-", "");
                CollectionFolderName = GenericController.strReplace(CollectionFolderName, " ", "");
                CollectionFolderName = CollectionName + "_" + CollectionFolderName;
                CollectionFolderName = CollectionFolderName.ToLowerInvariant();
            }
            string CollectionFolder = AddonController.getPrivateFilesAddonPath() + CollectionFolderName + "\\";

            core.privateFiles.verifyPath(CollectionFolder);
            //
            // create a collection 'version' folder for these new files
            string   TimeStamp = "";
            DateTime NowTime   = default(DateTime);

            NowTime = core.dateTimeNowMockable;
            int NowPart = NowTime.Year;

            TimeStamp += NowPart.ToString();
            NowPart    = NowTime.Month;
            if (NowPart < 10)
            {
                TimeStamp += "0";
            }
            TimeStamp += NowPart.ToString();
            NowPart    = NowTime.Day;
            if (NowPart < 10)
            {
                TimeStamp += "0";
            }
            TimeStamp += NowPart.ToString();
            NowPart    = NowTime.Hour;
            if (NowPart < 10)
            {
                TimeStamp += "0";
            }
            TimeStamp += NowPart.ToString();
            NowPart    = NowTime.Minute;
            if (NowPart < 10)
            {
                TimeStamp += "0";
            }
            TimeStamp += NowPart.ToString();
            NowPart    = NowTime.Second;
            if (NowPart < 10)
            {
                TimeStamp += "0";
            }
            TimeStamp += NowPart.ToString();
            CollectionVersionFolderName = CollectionFolderName + "\\" + TimeStamp;
            string CollectionVersionFolder = AddonController.getPrivateFilesAddonPath() + CollectionVersionFolderName;
            string CollectionVersionPath   = CollectionVersionFolder + "\\";

            core.privateFiles.createPath(CollectionVersionPath);
            return(CollectionVersionFolderName);
        }
        //
        //====================================================================================================
        //
        public static void updateCollectionFolderConfig(CoreController core, string collectionname, string collectionGuid, DateTime collectionUpdatedDate, string collectionVersionFolderName)
        {
            try {
                XmlDocument Doc = new XmlDocument();
                try {
                    Doc.LoadXml(CollectionFolderModel.getCollectionFolderConfigXml(core));
                } catch (Exception ex) {
                    //
                    // -- exit, error loading file
                    LogController.logError(core, MethodInfo.GetCurrentMethod().Name + ", UpdateConfig, Error loading Collections.xml file." + ex);
                    return;
                }
                if (!Doc.DocumentElement.Name.ToLower(CultureInfo.InvariantCulture).Equals("collectionlist"))
                {
                    //
                    // -- exit, top node invalid
                    LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", UpdateConfig, The Collections.xml file has an invalid root node, [" + Doc.DocumentElement.Name + "] was received and [" + CollectionListRootNode + "] was expected.");
                    return;
                }
                bool collectionFound = false;
                foreach (XmlNode localListNode in Doc.DocumentElement.ChildNodes)
                {
                    if (localListNode.Name.ToLower(CultureInfo.InvariantCulture).Equals("collection"))
                    {
                        //
                        // -- collection node
                        string localGuid = "";
                        foreach (XmlNode CollectionNode in localListNode.ChildNodes)
                        {
                            if (CollectionNode.Name.ToLower(CultureInfo.InvariantCulture).Equals("guid"))
                            {
                                localGuid = CollectionNode.InnerText.ToLower(CultureInfo.InvariantCulture);
                                break;
                            }
                        }
                        if (localGuid.Equals(collectionGuid.ToLower(CultureInfo.InvariantCulture)))
                        {
                            collectionFound = true;
                            foreach (XmlNode collectionNode in localListNode.ChildNodes)
                            {
                                switch (GenericController.toLCase(collectionNode.Name))
                                {
                                case "name":
                                    collectionNode.InnerText = collectionname;
                                    break;

                                case "lastchangedate":
                                    collectionNode.InnerText = collectionUpdatedDate.ToString();
                                    break;

                                case "path":
                                    collectionNode.InnerText = collectionVersionFolderName;
                                    break;
                                }
                            }
                            break;
                        }
                    }
                }
                if (!collectionFound)
                {
                    XmlNode NewCollectionNode = Doc.CreateNode(XmlNodeType.Element, "collection", "");
                    //
                    XmlNode NewAttrNode = Doc.CreateNode(XmlNodeType.Element, "name", "");
                    NewAttrNode.InnerText = collectionname;
                    NewCollectionNode.AppendChild(NewAttrNode);
                    //
                    NewAttrNode           = Doc.CreateNode(XmlNodeType.Element, "lastchangedate", "");
                    NewAttrNode.InnerText = collectionUpdatedDate.ToString();
                    NewCollectionNode.AppendChild(NewAttrNode);
                    //
                    NewAttrNode           = Doc.CreateNode(XmlNodeType.Element, "guid", "");
                    NewAttrNode.InnerText = collectionGuid;
                    NewCollectionNode.AppendChild(NewAttrNode);
                    //
                    NewAttrNode           = Doc.CreateNode(XmlNodeType.Element, "path", "");
                    NewAttrNode.InnerText = collectionVersionFolderName;
                    NewCollectionNode.AppendChild(NewAttrNode);
                    //
                    Doc.DocumentElement.AppendChild(NewCollectionNode);
                }
                //
                //
                // -- Save the result
                string LocalFilename = AddonController.getPrivateFilesAddonPath() + "Collections.xml";
                core.privateFiles.saveFile(LocalFilename, Doc.OuterXml);
            } catch (Exception ex) {
                LogController.logError(core, ex);
                throw;
            }
        }