// //==================================================================================================== /// <summary> /// Build collection folders for all collection files in a tempFiles folder /// - enumerate zip files in a folder and call buildCollectionFolderFromCollectionZip /// </summary> /// <param name="core"></param> /// <param name="sourceTempFolderPath"></param> /// <param name="CollectionLastChangeDate"></param> /// <param name="collectionsToInstall">A list of collection guids that need to be installed in the database. Any collection folders built are added to he collectionsToInstall list.</param> /// <param name="return_ErrorMessage"></param> /// <param name="collectionsInstalledList"></param> /// <param name="collectionsBuildingFolder">list of collection guids in the process of folder building. use to block recursive loop.</param> /// <returns></returns> public static bool buildCollectionFoldersFromCollectionZips(CoreController core, Stack <string> contextLog, string sourceTempFolderPath, DateTime CollectionLastChangeDate, ref List <string> collectionsToInstall, ref string return_ErrorMessage, ref List <string> collectionsInstalledList, ref List <string> collectionsBuildingFolder) { bool success = false; try { // contextLog.Push(MethodInfo.GetCurrentMethod().Name + ", [" + sourceTempFolderPath + "]"); traceContextLog(core, contextLog); // if (core.tempFiles.pathExists(sourceTempFolderPath)) { LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", BuildLocalCollectionFolder, processing files in private folder [" + sourceTempFolderPath + "]"); List <CPFileSystemClass.FileDetail> SrcFileNamelist = core.tempFiles.getFileList(sourceTempFolderPath); foreach (CPFileSystemClass.FileDetail file in SrcFileNamelist) { if ((file.Extension == ".zip") || (file.Extension == ".xml")) { success = buildCollectionFolderFromCollectionZip(core, contextLog, sourceTempFolderPath + file.Name, CollectionLastChangeDate, ref return_ErrorMessage, ref collectionsToInstall, ref collectionsInstalledList, ref collectionsBuildingFolder); } } } } catch (Exception ex) { LogController.logError(core, ex); throw; } finally { contextLog.Pop(); } return(success); }
// //==================================================================================================== /// <summary> /// when breaking changes are required for data, update them here /// </summary> /// <param name="core"></param> /// <param name="DataBuildVersion"></param> public static void migrateData(CoreController core, string DataBuildVersion, string logPrefix) { try { CPClass cp = core.cpParent; // // -- Roll the style sheet cache if it is setup core.siteProperties.setProperty("StylesheetSerialNumber", (-1).ToString()); // // -- verify ID is primary key on all tables with an id foreach (TableModel table in DbBaseModel.createList <TableModel>(cp)) { if (!string.IsNullOrWhiteSpace(table.name)) { bool tableHasId = false; { // // -- verify table as an id field string sql = "SELECT name FROM sys.columns WHERE Name = N'ID' AND Object_ID = Object_ID(N'ccmembers')"; DataTable dt = cp.Db.ExecuteQuery(sql); if (dt != null) { tableHasId = !dt.Rows.Equals(0); } } if (tableHasId) { // // -- table has id field, make sure it is primary key string sql = "" + " select Col.Column_Name" + " from INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab, INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col" + " where (Col.Constraint_Name = Tab.Constraint_Name) AND (Col.Table_Name = Tab.Table_Name) AND (Constraint_Type = 'PRIMARY KEY') AND (Col.Table_Name = '" + table.name + "')"; bool idPrimaryKeyFound = false; foreach (DataRow dr in core.db.executeQuery(sql).Rows) { if (GenericController.encodeText(dr["Column_Name"]).ToLower().Equals("id")) { idPrimaryKeyFound = true; break; } } if (!idPrimaryKeyFound) { try { core.db.executeNonQuery("alter table " + table.name + " add primary key (ID)"); } catch (Exception ex) { LogController.logError(core, ex, "Content Table [" + table.name + "] does not include column ID. Exception happened while adding column and setting it primarykey."); } } } } } // // -- continue only if a previous build exists if (!string.IsNullOrEmpty(DataBuildVersion)) { // // -- 4.1 to 5 conversions if (GenericController.versionIsOlder(DataBuildVersion, "4.1")) { // // -- create Data Migration Assets collection var migrationCollection = DbBaseModel.createByUniqueName <AddonCollectionModel>(cp, "Data Migration Assets"); if (migrationCollection == null) { migrationCollection = DbBaseModel.addDefault <AddonCollectionModel>(cp); migrationCollection.name = "Data Migration Assets"; } // // -- remove all addon content fieldtype rules Contensive.Models.Db.DbBaseModel.deleteRows <Contensive.Models.Db.AddonContentFieldTypeRulesModel>(cp, "(1=1)"); // // -- delete /admin www subfolder core.wwwFiles.deleteFolder("admin"); // // -- delete .asp and .php files foreach (BaseClasses.CPFileSystemBaseClass.FileDetail file in core.wwwFiles.getFileList("")) { if (file == null) { continue; } if (string.IsNullOrWhiteSpace(file.Name)) { continue; } if (file.Name.Length < 4) { continue; } string extension = System.IO.Path.GetExtension(file.Name).ToLower(CultureInfo.InvariantCulture); if ((extension == ".php") || (extension == ".asp")) { core.wwwFiles.deleteFile(file.Name); } } // // -- create www /cclib folder and copy in legacy resources core.programFiles.copyFile("cclib.zip", "cclib.zip", core.wwwFiles); core.wwwFiles.unzipFile("cclib.zip"); // // -- remove all the old menu entries and leave the navigation entries var navContent = DbBaseModel.createByUniqueName <ContentModel>(cp, Contensive.Models.Db.NavigatorEntryModel.tableMetadata.contentName); if (navContent != null) { core.db.executeNonQuery("delete from ccMenuEntries where ((contentcontrolid<>0)and(contentcontrolid<>" + navContent.id + ")and(contentcontrolid is not null))"); } // // -- reinstall newest font-awesome collection string returnErrorMessage = ""; var context = new Stack <string>(); var nonCritialErrorList = new List <string>(); var collectionsInstalledList = new List <string>(); CollectionLibraryController.installCollectionFromLibrary(core, false, context, Constants.fontAwesomeCollectionGuid, ref returnErrorMessage, false, true, ref nonCritialErrorList, logPrefix, ref collectionsInstalledList); // // -- reinstall newest redactor collection returnErrorMessage = ""; context = new Stack <string>(); nonCritialErrorList = new List <string>(); collectionsInstalledList = new List <string>(); CollectionLibraryController.installCollectionFromLibrary(core, false, context, Constants.redactorCollectionGuid, ref returnErrorMessage, false, true, ref nonCritialErrorList, logPrefix, ref collectionsInstalledList); // // -- addons with active-x -- remove programid and add script code that logs error string newCode = "" + "function m" + " ' + CHAR(13)+CHAR(10) + ' \ncp.Site.ErrorReport(\"deprecated active-X add-on executed [#\" & cp.addon.id & \", \" & cp.addon.name & \"]\")" + " ' + CHAR(13)+CHAR(10) + ' \nend function" + ""; string sql = "update ccaggregatefunctions set help='Legacy activeX: ' + objectprogramId, objectprogramId=null, ScriptingCode='" + newCode + "' where (ObjectProgramID is not null)"; LogController.logInfo(core, "MigrateData, removing activex addons, adding exception logging, sql [" + sql + "]"); core.db.executeNonQuery(sql); // // -- create page menus from section menus using (var cs = new CsModel(core)) { sql = "select m.name as menuName, m.id as menuId, p.name as pageName, p.id as pageId, s.name as sectionName, m.*" + " from ccDynamicMenus m" + " left join ccDynamicMenuSectionRules r on r.DynamicMenuId = m.id" + " left join ccSections s on s.id = r.SectionID" + " left join ccPageContent p on p.id = s.RootPageID" + " where (p.id is not null)and(s.active>0)" + " order by m.id, s.sortorder,s.id"; if (cs.openSql(sql)) { int sortOrder = 0; do { string menuName = cs.getText("menuName"); if (!string.IsNullOrWhiteSpace(menuName)) { var menu = DbBaseModel.createByUniqueName <MenuModel>(cp, menuName); if (menu == null) { menu = DbBaseModel.addEmpty <MenuModel>(cp); menu.name = menuName; try { menu.classItemActive = cs.getText("classItemActive"); menu.classItemFirst = cs.getText("classItemFirst"); menu.classItemHover = cs.getText("classItemHover"); menu.classItemLast = cs.getText("classItemLast"); menu.classTierAnchor = cs.getText("classTierItem"); menu.classTierItem = cs.getText("classTierItem"); menu.classTierList = cs.getText("classTierList"); menu.classTopAnchor = cs.getText("classTopItem"); menu.classTopItem = cs.getText("classTopItem"); menu.classTopList = cs.getText("classTopList"); menu.classTopWrapper = cs.getText("classTopWrapper"); } catch (Exception ex) { LogController.logError(core, ex, "migrateData error populating menu from dynamic menu."); } menu.save(cp); } // // -- set the root page's menuHeadline to the section name var page = DbBaseModel.create <PageContentModel>(cp, cs.getInteger("pageId")); if (page != null) { page.menuHeadline = cs.getText("sectionName"); page.save(cp); // // -- create a menu-page rule to attach this page to the menu in the current order var menuPageRule = DbBaseModel.addEmpty <MenuPageRuleModel>(cp); if (menuPageRule != null) { menuPageRule.name = "Created from v4.1 menu sections " + core.dateTimeNowMockable.ToString(); menuPageRule.pageId = page.id; menuPageRule.menuId = menu.id; menuPageRule.active = true; menuPageRule.sortOrder = sortOrder.ToString().PadLeft(4, '0'); menuPageRule.save(cp); sortOrder += 10; } } } cs.goNext(); } while (cs.ok()); } } // // -- create a theme addon for each template for styles and meta content using (var csTemplate = cp.CSNew()) { if (csTemplate.Open("page templates")) { do { int templateId = csTemplate.GetInteger("id"); string templateStylePrepend = ""; string templateStyles = csTemplate.GetText("StylesFilename"); // // -- add shared styles to the template stylesheet using (var csStyleRule = cp.CSNew()) { if (csStyleRule.Open("shared styles template rules", "(TemplateID=" + templateId + ")")) { do { int sharedStyleId = csStyleRule.GetInteger("styleid"); using (var csStyle = cp.CSNew()) { if (csStyleRule.Open("shared styles", "(id=" + sharedStyleId + ")")) { // // -- prepend lines beginning with @ t string styles = csStyleRule.GetText("StyleFilename"); if (!string.IsNullOrWhiteSpace(styles)) { // // -- trim off leading spaces, newlines, comments styles = styles.Trim(); while (!string.IsNullOrWhiteSpace(styles) && styles.Substring(0, 1).Equals("@")) { if (styles.IndexOf(Environment.NewLine) >= 0) { templateStylePrepend += styles.Substring(0, styles.IndexOf(Environment.NewLine)); styles = styles.Substring(styles.IndexOf(Environment.NewLine) + 1).Trim(); } else { templateStylePrepend += styles; styles = string.Empty; } } ; templateStyles += Environment.NewLine + styles; } } } csStyleRule.GoNext(); } while (csStyleRule.OK()); } } // // -- create an addon var themeAddon = DbBaseModel.addDefault <AddonModel>(cp); themeAddon.name = "Theme assets for template " + csTemplate.GetText("name"); themeAddon.otherHeadTags = csTemplate.GetText("otherheadtags"); themeAddon.javaScriptBodyEnd = csTemplate.GetText("jsendbody"); themeAddon.stylesFilename.content = templateStylePrepend + Environment.NewLine + templateStyles; themeAddon.collectionId = migrationCollection.id; themeAddon.save(cp); // // -- create an addon template rule to set dependency var rule = DbBaseModel.addEmpty <AddonTemplateRuleModel>(cp); rule.addonId = themeAddon.id; rule.templateId = templateId; rule.save(cp); // csTemplate.GoNext(); } while (csTemplate.OK()); } } // // -- reset the html minify so it is easier to resolve other issues core.siteProperties.setProperty("ALLOW HTML MINIFY", false); // // -- remove contentcategoryid from all edit page cp.Db.ExecuteNonQuery("update ccfields set Authorable=0 where name='contentcategoryid'"); cp.Db.ExecuteNonQuery("update ccfields set Authorable=0 where name='editsourceid'"); cp.Db.ExecuteNonQuery("update ccfields set Authorable=0 where name='editarchive'"); cp.Db.ExecuteNonQuery("update ccfields set Authorable=0 where name='editblank'"); // // -- remove legacy workflow fields UpgradeController.dropLegacyWorkflowField(core, "editsourceid"); cp.Db.ExecuteNonQuery("delete from ccfields where name='editsourceid'"); // UpgradeController.dropLegacyWorkflowField(core, "editblank"); cp.Db.ExecuteNonQuery("delete from ccfields where name='editblank'"); // UpgradeController.dropLegacyWorkflowField(core, "editarchive"); cp.Db.ExecuteNonQuery("delete from ccfields where name='editarchive'"); // UpgradeController.dropLegacyWorkflowField(core, "contentcategoryid"); cp.Db.ExecuteNonQuery("delete from ccfields where name='contentcategoryid'"); // // // -- end of 4.1 to 5 conversion } // // -- 5.19.1223 conversion -- render AddonList no copyFilename if (GenericController.versionIsOlder(DataBuildVersion, "5.19.1223")) { // // -- verify design block installation string returnUserError = ""; if (!cp.Db.IsTable("dbtext")) { if (!cp.Addon.InstallCollectionFromLibrary(Constants.designBlockCollectionGuid, ref returnUserError)) { throw new Exception("Error installing Design Blocks, required for data upgrade. " + returnUserError); } } // // -- add a text block and childPageList to every page without an addonlist foreach (var page in DbBaseModel.createList <PageContentModel>(cp, "(addonList is null)")) { convertPageContentToAddonList(core, page); } core.siteProperties.setProperty("PageController Render Legacy Copy", false); } // // -- 5.2005.9.4 conversion -- collections incorrectly marked not-updateable - mark all except themes (templates) if (GenericController.versionIsOlder(DataBuildVersion, "5.2005.9.4")) { // // -- cp.Db.ExecuteNonQuery("update ccaddoncollections set updatable=1 where name not like '%theme%'"); } // // -- 5.2005.19.1 conversion -- rename site property EmailUrlRootRelativePrefix to LocalFileModeProtocolDomain if (GenericController.versionIsOlder(DataBuildVersion, "5.2005.19.1")) { // // -- if (string.IsNullOrWhiteSpace(cp.Site.GetText("webAddressProtocolDomain"))) { cp.Site.SetProperty("webAddressProtocolDomain", cp.Site.GetText("EmailUrlRootRelativePrefix")); } } // // -- delete legacy corehelp collection. Created with fields that have only field name, legacy install layed collections over the application collection // new install loads fields directly from collection, which coreHelp then marks all fields inactive. core.db.delete("{6e905db1-d3f0-40af-aac4-4bd78e680fae}", "ccaddoncollections"); } // -- Reload core.cache.invalidateAll(); core.clearMetaData(); } catch (Exception ex) { LogController.logError(core, ex); throw; } }
// //==================================================================================================== /// <summary> /// Send email by SMTP. return 'ok' if success, else return a user compatible error message /// </summary> public static bool send(CoreController core, AmazonSimpleEmailServiceClient client, EmailSendDomainModel email, ref string reasonForFail) { string logShortDetail = ", subject [" + email.subject + "], toMemberId [" + email.toMemberId + "], toAddress [" + email.toAddress + "], fromAddress [" + email.fromAddress + "]"; string logLongDetail = logShortDetail + ", BounceAddress [" + email.bounceAddress + "], replyToAddress [" + email.replyToAddress + "]"; reasonForFail = ""; try { if (core.mockEmail) { // // -- for unit tests, mock interface by adding email to core.mockSmptList core.mockEmailList.Add(new MockEmailClass { email = email }); return(true); } // // -- test for email bounce block list using (var cs = core.cpParent.CSNew()) { string sql = "select count(*) as cnt from EmailBounceList where name like" + DbController.encodeSqlTextLike(email.toAddress) + " and transient=0"; if (cs.OpenSQL(sql)) { if (!cs.GetInteger("cnt").Equals(0)) { reasonForFail = "Recipient email address is on the email block list"; return(false); } } } // // -- send email Body messageBody = new Body { }; if (!string.IsNullOrEmpty(email.htmlBody)) { messageBody.Html = new Content { Charset = "UTF-8", Data = email.htmlBody }; } if (!string.IsNullOrEmpty(email.textBody)) { messageBody.Text = new Content { Charset = "UTF-8", Data = email.textBody }; } var sendRequest = new SendEmailRequest { Source = email.fromAddress, Destination = new Destination { ToAddresses = new List <string> { email.toAddress } }, Message = new Message { Subject = new Content(email.subject), Body = messageBody } }; try { LogController.logInfo(core, "Sending SES email" + logShortDetail); var response = client.SendEmail(sendRequest); return(true); } catch (Exception ex) { reasonForFail = "Error sending email [" + ex.Message + "]" + logShortDetail; LogController.logError(core, "Unexpected exception during SES send" + logLongDetail + ", exception [" + ex + "]"); return(false); } } catch (Exception ex) { reasonForFail = "Error sending email [" + ex.Message + "]" + logShortDetail; LogController.logError(core, "Unexpected exception during SES configure" + logLongDetail + ", exception [" + ex + "]"); return(false); } }
// //==================================================================================================== /// <summary> /// Iterate through all apps and execute tasks in processes /// </summary> private void runTasks(CoreController serverCore) { try { Stopwatch swProcess = new Stopwatch(); swProcess.Start(); // foreach (var appKVP in serverCore.serverConfig.apps) { if (appKVP.Value.enabled && appKVP.Value.appStatus.Equals(AppConfigModel.AppStatusEnum.ok)) { // // query tasks that need to be run // using (CPClass cpApp = new CPClass(appKVP.Value.name)) { // LogController.logTrace(cpApp.core, "runTasks, appname=[" + appKVP.Value.name + "]"); // try { int recordsAffected = 0; int sequentialTaskCount = 0; do { // // for now run an sql to get processes, eventually cache in variant cache string sqlCmdRunner = DbController.encodeSQLText(runnerGuid); string sql = "" + Environment.NewLine + " BEGIN TRANSACTION" + Environment.NewLine + " update cctasks set cmdRunner=" + sqlCmdRunner + " where id in (select top 1 id from cctasks where (cmdRunner is null)and(datestarted is null) order by id)" + Environment.NewLine + " COMMIT TRANSACTION"; cpApp.core.db.executeNonQuery(sql, ref recordsAffected); if (recordsAffected == 0) { // // -- no tasks found LogController.logTrace(cpApp.core, "runTasks, appname=[" + appKVP.Value.name + "], no tasks"); } else { // // -- select task to get timeout List <TaskModel> taskList = DbBaseModel.createList <TaskModel>(cpApp, "(cmdRunner=" + sqlCmdRunner + ")"); if (taskList.Count > 0) { TaskModel task = taskList.First(); Stopwatch swTask = new Stopwatch(); swTask.Start(); // // -- track multiple executions if (sequentialTaskCount > 0) { LogController.logTrace(cpApp.core, "runTasks, appname=[" + appKVP.Value.name + "], multiple tasks run in a single cycle, sequentialTaskCount [" + sequentialTaskCount + "]"); } // // -- two execution methods, 1) run task here, 2) start process and wait (so bad addon code does not memory link) bool runInServiceProcess = cpApp.Site.GetBoolean("Run tasks in service process"); string cliPathFilename = cpApp.core.programFiles.localAbsRootPath + "cc.exe"; if (!runInServiceProcess && !System.IO.File.Exists(cliPathFilename)) { runInServiceProcess = true; LogController.logError(cpApp.core, "TaskRunner cannot run out of process because command line program cc.exe not found in program files folder [" + cpApp.core.programFiles.localAbsRootPath + "]"); } if (runInServiceProcess) { // // -- execute here executeRunnerTasks(cpApp.Site.Name, runnerGuid); } else { // // -- execute in new process string filename = "cc.exe"; string workingDirectory = cpApp.core.programFiles.localAbsRootPath; string arguments = "-a \"" + appKVP.Value.name + "\" --runTask \"" + runnerGuid + "\""; LogController.logInfo(cpApp.core, "TaskRunner starting process to execute task for filename [" + filename + "], workingDirectory [" + workingDirectory + "], arguments [" + arguments + "]"); // // todo manage multiple executing processes using (Process process = new Process()) { process.StartInfo.CreateNoWindow = true; process.StartInfo.FileName = filename; process.StartInfo.WorkingDirectory = workingDirectory; process.StartInfo.Arguments = arguments; process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; process.Start(); // // -- determine how long to wait int timeoutMsec = 0; if ((int.MaxValue / 1000) >= task.timeout) { // minus 1 because maxvalue causes wait for ever timeoutMsec = int.MaxValue - 1; } else { timeoutMsec = task.timeout * 1000; } if (timeoutMsec == 0) { // // --no timeout, just run the task process.WaitForExit(); } else { process.WaitForExit(timeoutMsec); } if (!process.HasExited) { LogController.logError(cpApp.core, "TaskRunner Killing process, process timed out, app [" + appKVP.Value.name + "]."); process.Kill(); process.WaitForExit(); } process.Close(); } } LogController.logTrace(cpApp.core, "runTasks, app [" + appKVP.Value.name + "], task complete (" + swTask.ElapsedMilliseconds + "ms)"); } } sequentialTaskCount++; } while (recordsAffected > 0); } catch (Exception ex) { LogController.logError(cpApp.core, ex); } } } } // // -- trace log without core } catch (Exception ex) { LogController.logError(serverCore, ex); } }
// //==================================================================================================== /// <summary> /// download a collectionZip from the collection library to a privateFilesPath /// </summary> /// <param name="core"></param> /// <param name="tempFilesDownloadPath"></param> /// <param name="collectionGuid"></param> /// <param name="return_CollectionLastModifiedDate"></param> /// <param name="return_ErrorMessage"></param> /// <returns></returns> internal static bool downloadCollectionFromLibrary(CoreController core, string tempFilesDownloadPath, string collectionGuid, ref DateTime return_CollectionLastModifiedDate, ref string return_ErrorMessage) { bool result = false; try { // LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", downloading collection [" + collectionGuid + "]"); // // Request the Download file for this collection XmlDocument Doc = new XmlDocument(); string URL = "http://support.contensive.com/GetCollection?iv=" + CoreController.codeVersion() + "&guid=" + collectionGuid; string errorPrefix = "DownloadCollectionFiles, Error reading the collection library status file from the server for Collection [" + collectionGuid + "], download URL [" + URL + "]. "; int downloadRetry = 0; int downloadDelay = 2000; const int downloadRetryMax = 3; do { try { result = true; return_ErrorMessage = ""; // // -- pause for a second between fetches to pace the server (<10 hits in 10 seconds) Thread.Sleep(downloadDelay); // // -- download file System.Net.WebRequest rq = System.Net.WebRequest.Create(URL); rq.Timeout = 60000; System.Net.WebResponse response = rq.GetResponse(); Stream responseStream = response.GetResponseStream(); XmlTextReader reader = new XmlTextReader(responseStream); Doc.Load(reader); break; } catch (Exception ex) { // // this error could be data related, and may not be critical. log issue and continue downloadDelay += 2000; return_ErrorMessage = "There was an error while requesting the download details for collection [" + collectionGuid + "]"; result = false; LogController.logInfo(core, errorPrefix + "There was a parse error reading the response [" + ex + "]"); } downloadRetry += 1; } while (downloadRetry < downloadRetryMax); if (string.IsNullOrEmpty(return_ErrorMessage)) { // // continue if no errors if (Doc.DocumentElement.Name.ToLowerInvariant() != GenericController.toLCase(DownloadFileRootNode)) { return_ErrorMessage = "The collection file from the server was not valid for collection [" + collectionGuid + "]"; result = false; LogController.logInfo(core, errorPrefix + "The response has a basename [" + Doc.DocumentElement.Name + "] but [" + DownloadFileRootNode + "] was expected."); } else { // // Parse the Download File and download each file into the working folder if (Doc.DocumentElement.ChildNodes.Count == 0) { return_ErrorMessage = "The collection library status file from the server has a valid basename, but no childnodes."; LogController.logInfo(core, errorPrefix + "The collection library status file from the server has a valid basename, but no childnodes. The collection was probably Not found"); result = false; } else { // int CollectionFileCnt = 0; foreach (XmlNode metaDataSection in Doc.DocumentElement.ChildNodes) { string ResourceFilename = null; string ResourceLink = null; string CollectionVersion = null; string CollectionFileLink = null; string Collectionname = null; switch (GenericController.toLCase(metaDataSection.Name)) { case "collection": // // Read in the interfaces and save to Add-ons ResourceFilename = ""; ResourceLink = ""; Collectionname = ""; collectionGuid = ""; CollectionVersion = ""; CollectionFileLink = ""; foreach (XmlNode metaDataInterfaces in metaDataSection.ChildNodes) { int Pos = 0; string UserError = null; switch (GenericController.toLCase(metaDataInterfaces.Name)) { case "name": Collectionname = metaDataInterfaces.InnerText; break; case "help": if (!string.IsNullOrWhiteSpace(metaDataInterfaces.InnerText)) { core.tempFiles.saveFile(tempFilesDownloadPath + "Collection.hlp", metaDataInterfaces.InnerText); } break; case "guid": collectionGuid = metaDataInterfaces.InnerText; break; case "lastmodifieddate": return_CollectionLastModifiedDate = GenericController.encodeDate(metaDataInterfaces.InnerText); break; case "version": CollectionVersion = metaDataInterfaces.InnerText; break; case "collectionfilelink": CollectionFileLink = metaDataInterfaces.InnerText; CollectionFileCnt = CollectionFileCnt + 1; if (!string.IsNullOrEmpty(CollectionFileLink)) { Pos = CollectionFileLink.LastIndexOf("/") + 1; if ((Pos <= 0) && (Pos < CollectionFileLink.Length)) { // // Skip this file because the collecion file link has no slash (no file) LogController.logInfo(core, errorPrefix + "Collection [" + Collectionname + "] was not installed because the Collection File Link does not point to a valid file [" + CollectionFileLink + "]"); } else { string CollectionFilePath = tempFilesDownloadPath + CollectionFileLink.Substring(Pos); core.tempFiles.saveHttpRequestToFile(CollectionFileLink, CollectionFilePath); } } break; case "activexdll": case "resourcelink": // // save the filenames and download them only if OKtoinstall ResourceFilename = ""; ResourceLink = ""; foreach (XmlNode ActiveXNode in metaDataInterfaces.ChildNodes) { switch (GenericController.toLCase(ActiveXNode.Name)) { case "filename": ResourceFilename = ActiveXNode.InnerText; break; case "link": ResourceLink = ActiveXNode.InnerText; break; } } if (string.IsNullOrEmpty(ResourceLink)) { UserError = "There was an error processing a collection in the download file [" + Collectionname + "]. An ActiveXDll node with filename [" + ResourceFilename + "] contained no 'Link' attribute."; LogController.logInfo(core, errorPrefix + UserError); } else { if (string.IsNullOrEmpty(ResourceFilename)) { // // Take Filename from Link Pos = ResourceLink.LastIndexOf("/") + 1; if (Pos != 0) { ResourceFilename = ResourceLink.Substring(Pos); } } if (string.IsNullOrEmpty(ResourceFilename)) { UserError = "There was an error processing a collection in the download file [" + Collectionname + "]. The ActiveX filename attribute was empty, and the filename could not be read from the link [" + ResourceLink + "]."; LogController.logInfo(core, errorPrefix + UserError); } else { core.tempFiles.saveHttpRequestToFile(ResourceLink, tempFilesDownloadPath + ResourceFilename); } } break; } } break; } } if (CollectionFileCnt == 0) { LogController.logInfo(core, errorPrefix + "The collection was requested and downloaded, but was not installed because the download file did not have a collection root node."); } } } // // -- invalidate cache core.cache.invalidateAll(); } } catch (Exception ex) { LogController.logError(core, ex); throw; } return(result); }
// //==================================================================================================== /// <summary> /// Send email by SMTP. return 'ok' if success, else return a user compatible error message /// </summary> public static bool send(CoreController core, EmailSendDomainModel email, ref string returnErrorMessage) { bool status = false; returnErrorMessage = ""; try { string smtpServer = core.siteProperties.getText("SMTPServer", "127.0.0.1"); SmtpClient client = new SmtpClient(smtpServer); MailMessage mailMessage = new MailMessage(); MailAddress fromAddresses = new MailAddress(email.fromAddress.Trim()); ContentType mimeType = null; AlternateView alternate = null; // mailMessage.From = fromAddresses; mailMessage.To.Add(new MailAddress(email.toAddress.Trim())); mailMessage.Subject = email.subject; client.EnableSsl = false; client.UseDefaultCredentials = false; // if ((string.IsNullOrEmpty(email.textBody)) && (!string.IsNullOrEmpty(email.htmlBody))) { // // html only mailMessage.Body = email.htmlBody; mailMessage.IsBodyHtml = true; } else if ((!string.IsNullOrEmpty(email.textBody)) && (string.IsNullOrEmpty(email.htmlBody))) { // // text body only mailMessage.Body = email.textBody; mailMessage.IsBodyHtml = false; } else { // // both html and text mailMessage.Body = email.textBody; mailMessage.IsBodyHtml = false; mimeType = new System.Net.Mime.ContentType("text/html"); alternate = AlternateView.CreateAlternateViewFromString(email.htmlBody, mimeType); mailMessage.AlternateViews.Add(alternate); } if (core.mockEmail) { // // -- for unit tests, mock interface by adding email to core.mockSmptList core.mockEmailList.Add(new MockEmailClass { email = email }); status = true; } else { // // -- send email try { LogController.logInfo(core, "sendSmtp, to [" + email.toAddress + "], from [" + email.fromAddress + "], subject [" + email.subject + "], BounceAddress [" + email.bounceAddress + "], replyTo [" + email.replyToAddress + "]"); client.Send(mailMessage); status = true; } catch (Exception ex) { returnErrorMessage = "There was an error sending email [" + ex + "]"; LogController.logError(core, returnErrorMessage); } } } catch (Exception ex) { LogController.logError(core, "There was an error configuring smtp server ex [" + ex + "]"); throw; } return(status); }
// //==================================================================================================== /// <summary> /// Iterate through all apps, find addosn that need to run and add them to the task queue /// </summary> private void scheduleTasks(CoreController core) { try { // // -- run tasks for each app foreach (var appKvp in core.serverConfig.apps) { if (appKvp.Value.enabled && appKvp.Value.appStatus.Equals(AppConfigModel.AppStatusEnum.ok)) { LogController.logTrace(core, "scheduleTasks, app=[" + appKvp.Value.name + "]"); using (CPClass cpApp = new CPClass(appKvp.Value.name)) { // // Execute Processes try { string sqlAddonsCriteria = "" + "(active<>0)" + " and(name<>'')" + " and(" + " ((ProcessRunOnce is not null)and(ProcessRunOnce<>0))" + " or((ProcessInterval is not null)and(ProcessInterval<>0)and(ProcessNextRun is null))" + " or(ProcessNextRun<" + DbController.encodeSQLDate(core.dateTimeNowMockable) + ")" + " )"; var addonList = DbBaseModel.createList <AddonModel>(cpApp, sqlAddonsCriteria); foreach (var addon in addonList) { // int addonProcessInterval = encodeInteger(addon.processInterval); if (addon.processRunOnce) { // // -- run once checked addon.processNextRun = core.dateTimeNowMockable; addon.processRunOnce = false; } else if ((addon.processNextRun == null) && (addonProcessInterval > 0)) { // // -- processInterval set but everything else blank ) addon.processNextRun = core.dateTimeNowMockable.AddMinutes(addonProcessInterval); } if (addon.processNextRun <= core.dateTimeNowMockable) { // LogController.logInfo(cpApp.core, "scheduleTasks, addon [" + addon.name + "], add task, addonProcessRunOnce [" + addon.processRunOnce + "], addonProcessNextRun [" + addon.processNextRun + "]"); // // -- add task to queue for runner addTaskToQueue(cpApp.core, new TaskModel.CmdDetailClass { addonId = addon.id, addonName = addon.name, args = GenericController.convertAddonArgumentstoDocPropertiesList(cpApp.core, addon.argumentList) }, true); if (addonProcessInterval > 0) { // // -- interval set, update the next run addon.processNextRun = core.dateTimeNowMockable.AddMinutes(addonProcessInterval); } else { // // -- no interval, no next run addon.processNextRun = null; } } addon.save(cpApp); } } catch (Exception ex) { LogController.logTrace(cpApp.core, "scheduleTasks, exception [" + ex + "]"); LogController.logError(cpApp.core, ex); } } } } } catch (Exception ex) { LogController.logTrace(core, "scheduleTasks, exeception [" + ex + "]"); LogController.logError(core, ex); } }
// //====================================================================================================== // public static void installNode(CoreController core, XmlNode AddonNode, string AddonGuidFieldName, int CollectionID, ref bool return_UpgradeOK, ref string return_ErrorMessage, ref bool collectionIncludesDiagnosticAddons) { // todo - return bool return_ErrorMessage = ""; return_UpgradeOK = true; try { string Basename = GenericController.toLCase(AddonNode.Name); if ((Basename == "page") || (Basename == "process") || (Basename == "addon") || (Basename == "add-on")) { bool IsFound = false; string addonName = XmlController.getXMLAttribute(core, ref IsFound, AddonNode, "name", "No Name"); if (string.IsNullOrEmpty(addonName)) { addonName = "No Name"; } string addonGuid = XmlController.getXMLAttribute(core, ref IsFound, AddonNode, "guid", addonName); if (string.IsNullOrEmpty(addonGuid)) { addonGuid = addonName; } string navTypeName = XmlController.getXMLAttribute(core, ref IsFound, AddonNode, "type", ""); int navTypeId = getListIndex(navTypeName, navTypeIDList); if (navTypeId == 0) { navTypeId = NavTypeIDAddon; } using (var cs = new CsModel(core)) { string Criteria = "(" + AddonGuidFieldName + "=" + DbController.encodeSQLText(addonGuid) + ")"; cs.open(AddonModel.tableMetadata.contentName, Criteria, "", false); if (cs.ok()) { // // Update the Addon // LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", UpgradeAppFromLocalCollection, GUID match with existing Add-on, Updating Add-on [" + addonName + "], Guid [" + addonGuid + "]"); } else { // // not found by GUID - search name against name to update legacy Add-ons // cs.close(); Criteria = "(name=" + DbController.encodeSQLText(addonName) + ")and(" + AddonGuidFieldName + " is null)"; cs.open(AddonModel.tableMetadata.contentName, Criteria, "", false); if (cs.ok()) { LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", UpgradeAppFromLocalCollection, Add-on name matched an existing Add-on that has no GUID, Updating legacy Aggregate Function to Add-on [" + addonName + "], Guid [" + addonGuid + "]"); } } if (!cs.ok()) { // // not found by GUID or by name, Insert a new addon // cs.close(); cs.insert(AddonModel.tableMetadata.contentName); if (cs.ok()) { LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", UpgradeAppFromLocalCollection, Creating new Add-on [" + addonName + "], Guid [" + addonGuid + "]"); } } if (!cs.ok()) { // // Could not create new Add-on // LogController.logInfo(core, MethodInfo.GetCurrentMethod().Name + ", UpgradeAppFromLocalCollection, Add-on could not be created, skipping Add-on [" + addonName + "], Guid [" + addonGuid + "]"); } else { int addonId = cs.getInteger("ID"); MetadataController.deleteContentRecords(core, "Add-on Include Rules", "addonid=" + addonId); MetadataController.deleteContentRecords(core, "Add-on Content Trigger Rules", "addonid=" + addonId); // cs.set("collectionid", CollectionID); cs.set(AddonGuidFieldName, addonGuid); cs.set("name", addonName); cs.set("navTypeId", navTypeId); var ArgumentList = new StringBuilder(); var StyleSheet = new StringBuilder(); if (AddonNode.ChildNodes.Count > 0) { foreach (XmlNode Addonfield in AddonNode.ChildNodes) { if (!(Addonfield is XmlComment)) { XmlNode PageInterface = Addonfield; string fieldName = null; string FieldValue = ""; switch (GenericController.toLCase(Addonfield.Name)) { case "activexdll": { // // This is handled in BuildLocalCollectionFolder // break; } case "editors": { // // list of editors // foreach (XmlNode TriggerNode in Addonfield.ChildNodes) { // int fieldTypeId = 0; string fieldType = null; switch (GenericController.toLCase(TriggerNode.Name)) { case "type": { fieldType = TriggerNode.InnerText; fieldTypeId = MetadataController.getRecordIdByUniqueName(core, "Content Field Types", fieldType); if (fieldTypeId > 0) { using (var CS2 = new CsModel(core)) { Criteria = "(addonid=" + addonId + ")and(contentfieldTypeID=" + fieldTypeId + ")"; CS2.open("Add-on Content Field Type Rules", Criteria); if (!CS2.ok()) { CS2.insert("Add-on Content Field Type Rules"); } if (CS2.ok()) { CS2.set("addonid", addonId); CS2.set("contentfieldTypeID", fieldTypeId); } } } break; } default: { // do nothing break; } } } break; } case "processtriggers": { // // list of events that trigger a process run for this addon // foreach (XmlNode TriggerNode in Addonfield.ChildNodes) { switch (GenericController.toLCase(TriggerNode.Name)) { case "contentchange": { int TriggerContentId = 0; string ContentNameorGuid = TriggerNode.InnerText; if (string.IsNullOrEmpty(ContentNameorGuid)) { ContentNameorGuid = XmlController.getXMLAttribute(core, ref IsFound, TriggerNode, "guid", ""); if (string.IsNullOrEmpty(ContentNameorGuid)) { ContentNameorGuid = XmlController.getXMLAttribute(core, ref IsFound, TriggerNode, "name", ""); } } using (var CS2 = new CsModel(core)) { Criteria = "(ccguid=" + DbController.encodeSQLText(ContentNameorGuid) + ")"; CS2.open("Content", Criteria); if (!CS2.ok()) { Criteria = "(ccguid is null)and(name=" + DbController.encodeSQLText(ContentNameorGuid) + ")"; CS2.open("content", Criteria); } if (CS2.ok()) { TriggerContentId = CS2.getInteger("ID"); } } if (TriggerContentId != 0) { using (var CS2 = new CsModel(core)) { Criteria = "(addonid=" + addonId + ")and(contentid=" + TriggerContentId + ")"; CS2.open("Add-on Content Trigger Rules", Criteria); if (!CS2.ok()) { CS2.insert("Add-on Content Trigger Rules"); if (CS2.ok()) { CS2.set("addonid", addonId); CS2.set("contentid", TriggerContentId); } } CS2.close(); } } break; } default: { // do nothing break; } } } break; } case "scripting": { // // include add-ons - NOTE - import collections must be run before interfaces // when importing a collectin that will be used for an include int scriptinglanguageid = (int)AddonController.ScriptLanguages.VBScript; string ScriptingLanguage = XmlController.getXMLAttribute(core, ref IsFound, Addonfield, "language", "").ToLowerInvariant(); if (ScriptingLanguage.Equals("javascript") || ScriptingLanguage.Equals("jscript")) { scriptinglanguageid = (int)AddonController.ScriptLanguages.Javascript; } cs.set("scriptinglanguageid", scriptinglanguageid); string ScriptingEntryPoint = XmlController.getXMLAttribute(core, ref IsFound, Addonfield, "entrypoint", ""); cs.set("ScriptingEntryPoint", ScriptingEntryPoint); int ScriptingTimeout = GenericController.encodeInteger(XmlController.getXMLAttribute(core, ref IsFound, Addonfield, "timeout", "5000")); cs.set("ScriptingTimeout", ScriptingTimeout); string ScriptingCode = ""; foreach (XmlNode ScriptingNode in Addonfield.ChildNodes) { switch (GenericController.toLCase(ScriptingNode.Name)) { case "code": { ScriptingCode += ScriptingNode.InnerText; break; } default: { // do nothing break; } } } cs.set("ScriptingCode", ScriptingCode); break; } case "activexprogramid": { // // save program id // FieldValue = Addonfield.InnerText; cs.set("ObjectProgramID", FieldValue); break; } case "navigator": { // // create a navigator entry with a parent set to this // cs.save(); string menuNameSpace = XmlController.getXMLAttribute(core, ref IsFound, Addonfield, "NameSpace", ""); if (!string.IsNullOrEmpty(menuNameSpace)) { string NavIconTypeString = XmlController.getXMLAttribute(core, ref IsFound, Addonfield, "type", ""); if (string.IsNullOrEmpty(NavIconTypeString)) { NavIconTypeString = "Addon"; } BuildController.verifyNavigatorEntry(core, new MetadataMiniCollectionModel.MiniCollectionMenuModel { menuNameSpace = menuNameSpace, name = addonName, adminOnly = false, developerOnly = false, newWindow = false, active = true, addonName = addonName, navIconType = NavIconTypeString, navIconTitle = addonName }, CollectionID); } break; } case "argument": case "argumentlist": { // // multiple argumentlist elements are concatinated with crlf ArgumentList.Append(Addonfield.InnerText.Trim(' ') + Environment.NewLine); break; } case "style": { // // import exclusive style // string NodeName = XmlController.getXMLAttribute(core, ref IsFound, Addonfield, "name", ""); string NewValue = encodeText(Addonfield.InnerText).Trim(' '); if (NewValue.left(1) != "{") { NewValue = "{" + NewValue; } if (NewValue.Substring(NewValue.Length - 1) != "}") { NewValue += "}"; } StyleSheet.Append(NodeName + " " + NewValue + Environment.NewLine); break; } case "stylesheet": case "styles": { // // import exclusive stylesheet if more then whitespace // string test = Addonfield.InnerText; test = strReplace(test, " ", ""); test = strReplace(test, "\r", ""); test = strReplace(test, "\n", ""); test = strReplace(test, "\t", ""); if (!string.IsNullOrEmpty(test)) { StyleSheet.Append(Addonfield.InnerText + Environment.NewLine); } break; } case "template": case "content": case "admin": { // // these add-ons will be "non-developer only" in navigation // fieldName = Addonfield.Name; FieldValue = Addonfield.InnerText; if (!cs.isFieldSupported(fieldName)) { // // Bad field name - need to report it somehow // } else { cs.set(fieldName, FieldValue); if (GenericController.encodeBoolean(Addonfield.InnerText)) { // // if template, admin or content - let non-developers have navigator entry // } } break; } case "icon": { // // icon // FieldValue = XmlController.getXMLAttribute(core, ref IsFound, Addonfield, "link", ""); if (!string.IsNullOrEmpty(FieldValue)) { // // Icons can be either in the root of the website or in content files // FieldValue = GenericController.strReplace(FieldValue, "\\", "/"); // make it a link, not a file if (GenericController.strInstr(1, FieldValue, "://") != 0) { // // the link is an absolute URL, leave it link this // } else { if (FieldValue.left(1) != "/") { // // make sure it starts with a slash to be consistance // FieldValue = "/" + FieldValue; } if (FieldValue.left(17) == "/contensivefiles/") { // // in content files, start link without the slash // FieldValue = FieldValue.Substring(17); } } cs.set("IconFilename", FieldValue); { cs.set("IconWidth", GenericController.encodeInteger(XmlController.getXMLAttribute(core, ref IsFound, Addonfield, "width", "0"))); cs.set("IconHeight", GenericController.encodeInteger(XmlController.getXMLAttribute(core, ref IsFound, Addonfield, "height", "0"))); cs.set("IconSprites", GenericController.encodeInteger(XmlController.getXMLAttribute(core, ref IsFound, Addonfield, "sprites", "0"))); } } break; } case "includeaddon": case "includeadd-on": case "include addon": case "include add-on": { // // processed in phase2 of this routine, after all the add-ons are installed // break; } case "form": { // // The value of this node is the xml instructions to create a form. Take then // entire node, children and all, and save them in the formxml field. // this replaces the settings add-on type, and soo to be report add-on types as well. // this removes the ccsettingpages and settingcollectionrules, etc. // { cs.set("formxml", Addonfield.InnerXml); } break; } case "javascript": case "javascriptinhead": { // // these all translate to JSFilename // fieldName = "jsfilename"; cs.set(fieldName, Addonfield.InnerText); break; } case "iniframe": { // // typo - field is inframe // fieldName = "inframe"; cs.set(fieldName, Addonfield.InnerText); break; } case "diagnostic": { bool fieldValue = encodeBoolean(Addonfield.InnerText); cs.set("diagnostic", fieldValue); collectionIncludesDiagnosticAddons = collectionIncludesDiagnosticAddons || fieldValue; break; } case "category": { if (!string.IsNullOrWhiteSpace(Addonfield.InnerText)) { AddonCategoryModel category = DbBaseModel.createByUniqueName <AddonCategoryModel>(core.cpParent, Addonfield.InnerText); if (category == null) { category = DbBaseModel.addDefault <AddonCategoryModel>(core.cpParent); category.name = Addonfield.InnerText; category.save(core.cpParent); } cs.set("addonCategoryId", category.id); } break; } case "instancesettingprimarycontentid": { int lookupContentId = 0; if (!string.IsNullOrWhiteSpace(Addonfield.InnerText)) { ContentModel lookupContent = DbBaseModel.createByUniqueName <ContentModel>(core.cpParent, Addonfield.InnerText); if (lookupContent != null) { lookupContentId = lookupContent.id; } } cs.set("instancesettingprimarycontentid", lookupContentId); break; } default: { // // All the other fields should match the Db fields // fieldName = Addonfield.Name; FieldValue = Addonfield.InnerText; if (!cs.isFieldSupported(fieldName)) { // // Bad field name - need to report it somehow // LogController.logError(core, new ApplicationException("bad field found [" + fieldName + "], in addon node [" + addonName + "], of collection [" + MetadataController.getRecordName(core, "add-on collections", CollectionID) + "]")); } else { cs.set(fieldName, FieldValue); } break; } } } } } cs.set("ArgumentList", ArgumentList.ToString()); cs.set("StylesFilename", StyleSheet.ToString()); } cs.close(); } } } catch (Exception ex) { LogController.logError(core, ex); throw; } }
// //==================================================================================================== /// <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(); } }
// //==================================================================================================== // 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; } }