/* The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is comprised of the ADF directory The Initial Developer of the Original Code is PaperThin, Inc. Copyright (c) 2009-2022. All Rights Reserved. By downloading, modifying, distributing, using and/or accessing any files in this directory, you agree to the terms and conditions of the applicable end user license agreement. */ /* *************************************************************** */ /* Author: PaperThin, Inc. Name: resourceService_1_0.cfc Summary: Resource Service functions for the ADF Library Version: 1.0 History: 2016-05-12 - GAC - Created 2020-10-08 - GAC - Added methods to parse and return the resources data from the allScripts.cfm to use for registering resources 2020-11-06 - GAC - Updated getAllScriptsData() method to take a version parameter 2022-09-23 - GAC - Update getAllScripts() method to take a scriptsDataVersion parameter 2022-10-18 - GAC - Updated buildResourceKey() to replace groups of non-alphanumeric characters with only one underscore 2022-10-24 - GAC - Added the getAllScriptsMetadata() and getAllScriptsFileInfo() functions */ component displayname="resourceService_1_0" extends="ADF.lib.libraryBase" hint="Scripts functions for the ADF Library" output="no" { variables.resourceBackupDir = '_cs_apps/resources/backups'; // no trailing slash variables.resourceBackupFilePrefix = 'registered-resources-'; variables.getResourceBackupFileExt = 'bak'; public string function getResourceBackupDir() { return variables.resourceBackupDir; } public string function getResourceBackupFilePrefix() { return variables.resourceBackupFilePrefix; } public string function getResourceBackupFileExt() { return variables.getResourceBackupFileExt; } public string function getResourceBackupSiteDirPath() { return request.site.dir & variables.resourceBackupDir; } public struct function getAllScriptsMetadata(string version="1.0", string fileName="") { var rData = { error_msg: '', dir: '', data: [] }; var fileData = getAllScriptsFileInfo(version=arguments.version, fileName=arguments.fileName); rData.dir = fileData.dir; rData.error_msg = fileData.error_msg; if ( StructKeyExists(fileData,'failedFile') ) rData.failedFile = fileData.failedFile; rData.data = getAllScriptsData(version=arguments.version, fileName=arguments.fileName); return rData; } public struct function getAllScriptsFileInfo(string version="1.0", string fileName="") { var rData = { error_msg: '', path: '', dir: '', ext: '', version: arguments.version, fileName: arguments.fileName }; var dataFileVersion = arguments.version; var cfmDataFileName = "allScripts.cfm"; var jsonDataFileName = ListFirst(cfmDataFileName,'.') & '.json'; var scriptsPath = 'scripts/data'; var filterList = "../,./"; var filterStr = ''; var adfFilePath = '/ADF/lib/#scriptsPath#/'; var siteOverrideFilePath = '#request.site.csAppsURL##scriptsPath#/'; // siteOverrideFilePath is not versioned var failedFileName = ''; var fileMap = { site: {}, adf: {} }; // Hold over from early version where dataFileVersion was a file path for ( var i=1; i <= ListLen(filterList,','); i++ ) { filterStr = ListGetAt(filterList, i, ','); if (Find(filterStr, dataFileVersion)) dataFileVersion = Replace(dataFileVersion, filterStr, '', "ALL"); } // Build the versioned ADF data FilePath adfFilePath = adfFilePath & '#dataFileVersion#/'; // Build the FileMap for ADF level files fileMap.adf.cfmPath = "#adfFilePath##cfmDataFileName#"; fileMap.adf.jsonPath = "#adfFilePath##jsonDataFileName#"; fileMap.adf.cfmDir = ExpandPath("#fileMap.adf.cfmPath#"); fileMap.adf.jsonDir = ExpandPath("#fileMap.adf.jsonPath#"); // Set the Override custom fileName (for site level filename override) if ( LEN(TRIM(arguments.fileName)) ) { rData.version = ''; rData.ext = ListLast(arguments.fileName,'.'); if ( rData.ext EQ 'json' ) jsonDataFileName = arguments.fileName; else if ( rData.ext EQ 'cfm' ) cfmDataFileName = arguments.fileName; StructDelete(fileMap,'adf'); } // Build the FileMap for Site Level files fileMap.site.cfmPath = "#siteOverrideFilePath##cfmDataFileName#"; fileMap.site.jsonPath = "#siteOverrideFilePath##jsonDataFileName#"; fileMap.site.cfmDir = ExpandPath("#fileMap.site.cfmPath#"); fileMap.site.jsonDir = ExpandPath("#fileMap.site.jsonPath#"); // Get the allScripts data from a local override file in _cs_apps/scripts/data folder or from the ADF versioned data folder // - Check for Site-Level JSON file if ( FileExists(fileMap.site.jsonDir) ) { rData.ext = 'json'; rData.path = fileMap.site.jsonPath; rData.dir = fileMap.site.jsonDir; rData.fileName = jsonDataFileName; } // - Check for Site-Level CFM file else if ( FileExists(fileMap.site.cfmDir) ) { rData.ext = 'cfm'; rData.path = fileMap.site.cfmPath; rData.dir = fileMap.site.cfmDir; rData.fileName = cfmDataFileName; } // - Check for ADF level JSON file else if ( StructKeyExists(fileMap,'adf') AND FileExists(fileMap.adf.jsonDir) ) { rData.ext = 'json'; rData.path = fileMap.adf.jsonPath; rData.dir = fileMap.adf.jsonDir; rData.fileName = jsonDataFileName; } // - Use the ADF level CFM file else if ( StructKeyExists(fileMap,'adf') AND FileExists(fileMap.adf.cfmDir) ) { rData.ext = 'cfm'; rData.path = fileMap.adf.cfmPath; rData.dir = fileMap.adf.cfmDir; rData.fileName = cfmDataFileName; } // - Use the base ADF CFM file else { failedFileName = arguments.fileName; cfmDataFileName = "allScripts.cfm"; dataFileVersion = '1.0'; adfilePath = '/ADF/lib/#scriptsPath#/' & '#dataFileVersion#/'; rData.error_msg = 'Requested site-level scripts data file #failedFileName# was not found. Using ADF default #cfmDataFileName# version #dataFileVersion# file instead.'; rData.failedfile = failedFileName; rData.ext = ListLast(cfmDataFileName,'.'); rData.path = "#adfilePath##cfmDataFileName#"; rData.dir = ExpandPath(rData.path); rData.fileName = cfmDataFileName; rData.version = dataFileVersion; } return rData; } public array function getAllScriptsData(string version="1.0", string fileName="") { var rData = []; var fileData = getAllScriptsFileInfo(version=arguments.version, fileName=arguments.fileName); if ( fileData.ext EQ 'json' AND ListLast(fileData.dir,'.') EQ 'json' ) { jsonData = FileRead(fileData.dir); if ( IsJson(jsonData) ) rData = deserializeJson(jsonData); } else { // - Include the base ADF allScript.CFM file which contains 'rData' array include "#fileData.path#"; } return rData; } public array function getAllScripts(string source="local", scriptsDataVersion="1.0", scriptsDataFilename="") { var retArr = []; var rData = getAllScriptsData(version=arguments.scriptsDataVersion, fileName=arguments.scriptsDataFilename); var i = 1; var rItem = {}; var srcOptions = "local,external"; if ( ListFindNoCase(srcOptions,arguments.source) EQ 0 ) arguments.source = "local"; for ( i=1; i <= ArrayLen(rData); i++ ) { rItem = rData[i]; rItem.cssSourceArray = _buildSourceArr(resouceItem=rItem,source=arguments.source,sourceType="css"); rItem.jsSourceArray = _buildSourceArr(resouceItem=rItem,source=arguments.source,sourceType="js"); // If either js or css Array is empty if ( ArrayLen(rItem.cssSourceArray) EQ 0 OR ArrayLen(rItem.jsSourceArray) EQ 0 ) { // if none of the requested 'external' data exists, get the 'local' versions if ( arguments.source EQ "external" ) { if ( ArrayLen(rItem.cssSourceArray) EQ 0 ) rItem.cssSourceArray = _buildSourceArr(resouceItem=rItem,source="local",sourceType="css"); if ( ArrayLen(rItem.jsSourceArray) EQ 0 ) rItem.jsSourceArray = _buildSourceArr(resouceItem=rItem,source="local",sourceType="js"); } // if none of the requested 'local' data exists, get the 'external' versions else if ( arguments.source EQ "local" ) { if ( ArrayLen(rItem.cssSourceArray) EQ 0 ) rItem.cssSourceArray = _buildSourceArr(resouceItem=rItem,source="external",sourceType="css"); if ( ArrayLen(rItem.jsSourceArray) EQ 0 ) rItem.jsSourceArray = _buildSourceArr(resouceItem=rItem,source="external",sourceType="js"); } } // Set the Source Location rItem.sourceLocation = arguments.source; if ( NOT StructKeyExists(rItem,"archive") OR rItem.archive NEQ 1 ) arrayAppend(retArr,rItem); } return retArr; } public struct function getAllScriptsKeyMap(string source="local") { var retData = {}; var data = getAllScripts(source=arguments.source); var i = 1; var rItem = {}; var keyArr = []; var aliasArr = []; var a = 1; var aKey = ""; for ( i=1; i <= ArrayLen(data); i++ ) { rItem = data[i]; // Add the name to the KeyArr if ( StructKeyExists(rItem,"name") AND LEN(TRIM(rItem.name)) ) ArrayAppend(keyArr,rItem.name); // Add all of the Aliases to the KeyArr if ( StructKeyExists(rItem,"ALIASLIST") AND LEN(TRIM(rItem.ALIASLIST)) ) { aliasArr = ListToArray(rItem.ALIASLIST); arrayAppend(keyArr,aliasArr,true); } // Add the generated key to the KeyArr if ( StructKeyExists(rItem,"key") ) arrayAppend(keyArr,rItem.key); // Loop over the keyArr and create a struct for one (with no dups) for ( a=1; a <= ArrayLen(keyArr); a++ ) { aKey = keyArr[a]; if (NOT StructKeyExists(retData, aKey)) retData[aKey] = rItem; } } return retData; } /* _buildSourceArr() LoadTagType: 1 (CSS) 2 (JS) // CS 10.7+ 3 (CSS Third Party) 4 (JS Third Party) */ private array function _buildSourceArr(required struct resouceItem,string source="local",string sourceType="js") { var retArr = []; var data = arguments.resouceItem; var srcData = {}; var srcItm = {}; var tempArr = []; var tempData = {}; var srcOptions = "local,external"; var srcTypeOptions = "css,js"; var csVersion = server.ADF.csVersion; var isCS107plus = application.ADF.utils.minimumVersionCheck(version=csVersion,minimumVersionsList="10.7"); var isThirdParty = false; if ( ListFindNoCase(srcOptions,arguments.source) EQ 0 ) arguments.source = "local"; if ( ListFindNoCase(srcTypeOptions,arguments.sourceType) EQ 0 ) arguments.sourceType = "js"; if ( StructKeyExists(data,"source") ) { srcData = data.source; if ( StructKeyExists(srcData,arguments.source) ) { srcItm = srcData[arguments.source]; if ( StructKeyExists(srcItm,arguments.sourceType) ) { tempArr = srcItm[arguments.sourceType]; for ( i=1; i <= ArrayLen(tempArr); i++ ) { tempData = tempArr[i]; // Check if we need to use the new CS10.7 "Third Party" resouces types (with integrity and crossorigin) isThirdParty = false; if ( ( StructKeyExists(tempData,"Integrity") AND LEN(TRIM(tempData.Integrity)) ) OR ( StructKeyExists(tempData,"Crossorigin") AND LEN(TRIM(tempData.Crossorigin)) ) ) isThirdParty = true; if ( arguments.sourceType EQ "JS" ) { tempData.LoadTagType = 2; if ( isCS107plus AND isThirdParty ) tempData.LoadTagType = 4; } else if ( arguments.sourceType EQ "CSS" ) { tempData.LoadTagType = 1; if ( isCS107plus AND isThirdParty ) tempData.LoadTagType = 3; } // Make sure each tempData Set has an Integrity and a Crossorigin if ( isCS107plus ) { if ( !StructKeyExists(tempData,"Integrity") ) tempData.Integrity = ""; if ( !StructKeyExists(tempData,"Crossorigin") ) tempData.Crossorigin = ""; } ArrayAppend(retArr,tempData); } } } } return retArr; } public struct function getScriptByKey(required string key,string source="local") { var retData = {}; var data = getAllScriptsKeyMap(source=arguments.source); if ( StructKeyExists(data,arguments.key) ) retData = data[arguments.key]; return retData; } public array function getScriptsByGroupList(required string groupList,string source="local") { var retArr = []; var data = getAllScripts(source=arguments.source); var i = 1; var rItem = {}; var grpArr = []; var grpFilter = ""; var g = 1; var rscMap = {}; for ( i=1; i <= ArrayLen(data); i++ ) { rItem = data[i]; grpFilter = ''; grpArr = []; // get key for duplicate tracking if ( StructKeyExists(rItem,"key") ) key = rItem.key; if ( StructKeyExists(rItem,"groups") ) { grpArr = rItem.groups; if ( NOT IsArray(grpArr) ) grpArr = ListToArray(grpArr); } for ( g=1; g <= ListLen(arguments.groupList); g++ ) { grpFilter = ListGetAt(arguments.groupList,g); if ( ArrayFindNoCase(grpArr, grpFilter) AND !StructKeyExists(rscMap,key) ) { arrayAppend(retArr,rItem); rscMap[key] = grpFilter; } } } //WriteDUmp(rscMap); return retArr; } public array function getScriptsByAliasList(required string aliasList,string source="local") { var retArr = []; var data = getAllScripts(source=arguments.source); var i = 1; var rItem = {}; var name = ""; var aliasArr = []; var aliasFilter = ""; var a = 1; var rscMap = {}; for ( i=1; i <= ArrayLen(data); i++ ) { rItem = data[i]; aliasFilter = ''; aliasArr = []; // get key for duplicate tracking if ( StructKeyExists(rItem,"key") ) key = rItem.key; if ( StructKeyExists(rItem,"name") ) name = rItem.name; if ( StructKeyExists(rItem,"aliaslist") ) { aliasArr = rItem.aliaslist; if ( NOT IsArray(aliasArr) ) aliasArr = ListToArray(aliasArr); } // Added the Resource Name to the Alias List arrayAppend(aliasArr,name); for ( a=1; a <= ListLen(arguments.aliasList); a++ ) { aliasFilter = ListGetAt(arguments.aliasList,a); if ( ArrayFindNoCase(aliasArr, aliasFilter) AND !StructKeyExists(rscMap,key) ) { arrayAppend(retArr,rItem); rscMap[key] = aliasFilter; } } } //WriteDUmp(rscMap); return retArr; } public struct function backupRegisteredResources() { var retData = {}; var jsStr = ''; var resourceAPI = Server.CommonSpot.ObjectFactory.getObject("Resource"); var resQry = resourceAPI.getList(); var resArr = []; var resCols = "Name,Description,Category,InstallInstructions,Redistributable,earlyLoadSourceArray,lateLoadSourceArray,aliasList"; var resItem = {}; var q = 1; var backupSiteDirPath = getResourceBackupSiteDirPath(); var backupExt = variables.getResourceBackupFileExt; var backupFilename = variables.resourceBackupFilePrefix & DateTimeFormat(Now(),"yyyymmdd-HHnnss") & '.' & backupExt; var backupPath = backupSiteDirPath & "/" & backupFilename; var bStatus = false; retData.status = false; for( q=1; q <= resQry.RecordCount; q++ ) { resItem = application.ADF.data.queryRowToStruct(query=resQry,rowNum=q,colsList=resCols,LCaseNames=true); arrayAppend(resArr,resItem); } // Convert to a JSON string jsStr = serializeJson(resArr); // Create Registered Resources Backup file if ( Len(Trim(jsStr)) AND IsJSON(jsStr) ) { bStatus = application.ADF.utils.writeDataFile(filePath=backupPath,dataString=jsStr,overwrite=0,append=false); retData.status = bStatus; retData.file = backupPath; } return retData; } /* Name: buildResourceKey History: 2022-10-18 - Updated to replace groups with only one underscore */ public string function buildResourceKey(string str="") { return TRIM(REReplace(arguments.str,"[^0-9A-Za-z]+","_","all")); } }