diff --git a/.gitignore b/.gitignore index 8b29193..842398a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -coldbox \ No newline at end of file +/coldbox +/modules + diff --git a/README.md b/README.md index 3b36519..f10ee32 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,136 @@ -CodeChecker -============ +``` + ______ __ ________ __ ___ + / ____/___ ____/ /__ / ____/ /_ ___ _____/ /_____ _____ / | ____ ____ + / / / __ \/ __ / _ \/ / / __ \/ _ \/ ___/ //_/ _ \/ ___/ / /| | / __ \/ __ \ +/ /___/ /_/ / /_/ / __/ /___/ / / / __/ /__/ ,< / __/ / / ___ |/ /_/ / /_/ / +\____/\____/\__,_/\___/\____/_/ /_/\___/\___/_/|_|\___/_/ /_/ |_/ .___/ .___/ + /_/ /_/ +``` -See the [Wiki](https://github.com/wellercs/CodeChecker/wiki) -for instructions, documentation, credits, and release notes. +# CodeChecker App + +Welcome to the CodeChecker. A code quality tool. This repo contains a standalone app you can run against your code. +This app bundles the [CodeChecker core libraries](https://github.com/coldbox-modules/codechecker-core) for use in a web server. + +## INSTRUCTIONS + +Deploy this application to any web-accessible directory and start up a server. + +```bash +git clone git@github.com:Ortus-Solutions/CodeChecker.git +box install +box server start +``` + +Rules may be added or modified in the app/services/Rules.cfc file. + +Third party plugins are packaged in app/services/. + +Visit /CodeChecker/app/index.cfm to begin via the UI. + +To specify directories and/or files to review/check, use the check files form (frm_codechecker.cfm) and separate entries by a carriage return. + +Alternatively, only the services directory is required for running the application outside of the browser. + +To run CodeChecker outside of the browser, call the following: +* Component: /services/CodeChecker +* Function: startCodeReview +* Parameters: +- filepath (required string): the directory or file path for which to review +- recurse (optional boolean): flag for whether or not to review recursively + +Call getResults() to return an array of structs of the code check results. + +## DOCUMENTATION + +- APPLICATION STRUCTURE + +This application uses a basic MVC structure. + +The heart of the application resides in the "services" directory. This is where the code checker and rules engines can be found. Third party plugins also reside in services. + +Resources such as css, javascript, images, etc. reside in the "assets" directory. + +The "model" directory contains files "action" files for the view layer. + +The "view" directory contains the UI for the results table and check files form (frm_codechecker.cfm). + +If you only want to run CodeChecker without a web UI, you only need the services directory. + +- SERVICES LAYER + +CodeChecker.cfc is the object that checks and enforces the defined rules. The default check function uses REFindNoCase(). + +Rules.cfc is the object defining the code check rules. + +Initial categories of rules are: +* Security +* Performance +* Standards +* Maintenance + +Initial metadata for rules include: +* bulkcheck - boolean value of whether to check the entire file in one pass (true) or line-by-line (false) +* category - string value corresponding to one of the categories listed above or your own custom category +* componentname - string value of the check component name to call in the dynamic cfinvoke +* customcode - currently does not do anything but considering using this as an option to run custom code instead of always using the regular expression pattern +* extensions - comma-delimited list of file extensions of files to check +* functionname - string value of the check function name to call in the dynamic cfinvoke +* message - string value of the explanation of the rule +* name - string value of the title of the rule +* passonmatch - boolean value of whether to pass or fail if a match is found +* pattern - string value of the regular expression of the rule +* severity - value of the severity level of the broken rule (default values are 1-5). 5 is most severe. +* tagname - pipe delimited list of ColdFusion tags that directs the checker to run the rule only if the line contains one of the specified tags + +Third party plugins are supported for additional rules. + +Currently integrated third party plugins include: + +* QueryParamScanner by Peter Boughton +* VarScoper by Mike Schierberl + +These plugins are automatically ran by CodeChecker. + +- VIEW LAYER + +To specify directories and/or files to review/check, use the check files form (frm_codechecker.cfm) and separate entries by a carriage return. + +The results of the code check are returned as an array of structs and will be displayed in a table (dsp_codechecker.cfm). The results page will show exceptions to the defined rules as well as display any failed files/directories that were not checked (i.e., missing files). + +Results display the following exception data: +* Directory +* File +* Rule +* Message +* Line Number +* Category +* Severity + +- TESTS + +The "tests" directory contains test files containing intentionally broken rules. + +MXUnit tests will be written in the future. + +- CUSTOMIZATION + +Any of the default rules can be modified or deleted. + +To add a new rule, simply copy one of the "temprulestruct" blocks of code and paste it below another block. +Be sure to set temprulestruct to an empty structure to clear out the data for any previously defined rules. +Also ensure that the bottom of your block appends temprulestruct to the "rules" array. + +## CREDITS + +Steve Bryant for inspiring this project with his CodeCop application. +http://codecop.riaforge.org/ + +Peter Boughton for the QueryParamScanner cfc. +http://qpscanner.riaforge.org/ + +Mike Schierberl for the VarScoper cfc. +http://varscoper.riaforge.org/ + +Chris Wellers for creating the first version of the CodeChecker +https://github.com/wellercs/CodeChecker diff --git a/box.json b/box.json index 46436f6..9c43417 100644 --- a/box.json +++ b/box.json @@ -1,105 +1,57 @@ -{ - "name":"CodeChecker", - "version":"2.0.0", - "author":"Chris Weller ", - "location":"USA", - "directory":"CodeChecker", - "createPackageDirectory":true, - "packageDirectory":"CodeChecker", - "homepage":"https://github.com/wellercs/CodeChecker", - "documentation":"https://github.com/wellercs/CodeChecker/wiki", - "repository":{ - "type":"git", - "url":"https://github.com/wellercs/CodeChecker" - }, - "bugs":"https://github.com/wellercs/CodeChecker/issues", - "slug":"CodeChecker", - "shortDescription":"A package for checking code quality.", - "description":"This package uses rules to evaluate code on the local system and report back possible issues based on maintenance, performance, security, and standards.", - "instructions":"https://github.com/wellercs/CodeChecker/wiki", - "changelog":"https://github.com/wellercs/CodeChecker/releases", - "type":"projects", - "keywords":[ - "code", - "check", - "checker", - "review", - "reviewer", - "quality", - "qa", - "test", - "maintenance", - "performance", - "security", - "standards" - ], - "private":false, - "engines":[ - { - "type":"railo", - "version":">=4.1.x" - }, - { - "type":"adobe", - "version":">=9.0.0" - }, - { - "type":"lucee", - "version":">4.5" - } - ], - "projectURL":"https://github.com/wellercs/CodeChecker", - "license":[ - { - "type":"Apache2", - "url":"http://www.apache.org/licenses/LICENSE-2.0.html" - } - ], - "contributors":[ - "Chris Weller ", - "Gavin Pickin ", - "Luis Majano ", + "homepage":"https://github.com/Ortus-Solutions/CodeChecker", + "documentation":"https://github.com/Ortus-Solutions/CodeChecker/wiki", + "createPackageDirectory":false, + "repository":{ + "type":"git", + "url":"https://github.com/Ortus-Solutions/CodeChecker" + }, + "slug":"CodeChecker", + "shortDescription":"A package for checking code quality.", + "description":"This package uses rules to evaluate code on the local system and report back possible issues based on maintenance, performance, security, and standards.", + "type":"projects", + "keywords":[ + "code", + "check", + "checker", + "review", + "reviewer", + "quality", + "qa", + "test", + "maintenance", + "performance", + "security", + "standards" + ], + "private":false, + "projectURL":"https://github.com/Ortus-Solutions/CodeChecker", + "license":[ + { + "type":"Apache2", + "url":"http://www.apache.org/licenses/LICENSE-2.0.html" + } + ], + "contributors":[ + "Chris Weller ", + "Gavin Pickin ", + "Luis Majano - // Allow unique URL or combination of URLs, we recommend both enabled - setUniqueURLS(false); - // Auto reload configuration, true in dev makes sense to reload the routes on every request - //setAutoReload(false); - // Sets automatic route extension detection and places the extension in the rc.format variable - // setExtensionDetection(true); - // The valid extensions this interceptor will detect - // setValidExtensions('xml,json,jsont,rss,html,htm'); - // If enabled, the interceptor will throw a 406 exception that an invalid format was detected or just ignore it - // setThrowOnInvalidExtension(true); - - // Base URL - if( len(getSetting('AppMapping') ) lte 1){ - setBaseURL("http://#cgi.HTTP_HOST#/index.cfm"); - } - else{ - setBaseURL("http://#cgi.HTTP_HOST#/#getSetting('AppMapping')#/index.cfm"); - } - - // Your Application Routes - addRoute(pattern=":handler/:action?"); - - - /** Developers can modify the CGI.PATH_INFO value in advance of the SES - interceptor to do all sorts of manipulations in advance of route - detection. If provided, this function will be called by the SES - interceptor instead of referencing the value CGI.PATH_INFO. - - This is a great place to perform custom manipulations to fix systemic - URL issues your Web site may have or simplify routes for i18n sites. - - @Event The ColdBox RequestContext Object - **/ - function PathInfoProvider(Event){ - /* Example: - var URI = CGI.PATH_INFO; - if (URI eq "api/foo/bar") - { - Event.setProxyRequest(true); - return "some/other/value/for/your/routes"; - } - */ - return CGI.PATH_INFO; - } - \ No newline at end of file diff --git a/config/WireBox.cfc b/config/WireBox.cfc index 9a4998c..43388bb 100644 --- a/config/WireBox.cfc +++ b/config/WireBox.cfc @@ -1,47 +1,7 @@ component extends="coldbox.system.ioc.config.Binder"{ - /** - * Configure WireBox, that's it! - */ function configure(){ - // The WireBox configuration structure DSL - wireBox = { - // Scope registration, automatically register a wirebox injector instance on any CF scope - // By default it registeres itself on application scope - scopeRegistration = { - enabled = true, - scope = "application", // server, cluster, session, application - key = "wireBox" - }, - - // DSL Namespace registrations - customDSL = { - // namespace = "mapping name" - }, - - // Custom Storage Scopes - customScopes = { - // annotationName = "mapping name" - }, - - // Package scan locations - scanLocations = ["model"], - - // Stop Recursions - stopRecursions = [], - - // Parent Injector to assign to the configured injector, this must be an object reference - parentInjector = "", - - // Register all event listeners here, they are created in the specified order - listeners = [ - // { class="", name="", properties={} } - ] - }; - - // Map Models Automatically with aliases - mapDirectory( packagePath="codechecker.models" ); } } \ No newline at end of file diff --git a/config/rules/bp.casesensitivity.rules.json b/config/rules/bp.casesensitivity.rules.json deleted file mode 100644 index 127c668..0000000 --- a/config/rules/bp.casesensitivity.rules.json +++ /dev/null @@ -1,171 +0,0 @@ -[ - { - "pattern": "arrayContains\\(", - "message": "arrayContains() is Case Sensitive - try arrayContainsNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "arrayContains()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "arrayFindAll\\(", - "message": "arrayFindAll() is Case Sensitive - try arrayFindAllNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "arrayFindAll()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "arrayFind\\(", - "message": "arrayFind() is Case Sensitive - try arrayFindNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "arrayFind()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "compare\\(", - "message": "compare() is Case Sensitive - try compareNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "compare()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "find\\(", - "message": "find() is Case Sensitive - try findNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "find()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "listContains\\(", - "message": "listContains() is Case Sensitive - try listContainsNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "listContains()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "listFind\\(", - "message": "listFind() is Case Sensitive - try listFindNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "listFind()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "listValueCount\\(", - "message": "listValueCount() is Case Sensitive - try listValueCountNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "listValueCount()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "REFind\\(", - "message": "REFind() is Case Sensitive - try REFindNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "REFind()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "REMatch\\(", - "message": "REMatch() is Case Sensitive - try REMatchNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "REMatch()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "replace\\(", - "message": "replace() is Case Sensitive - try replaceNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "replace()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": "REReplace\\(", - "message": "REReplace() is Case Sensitive - try REReplaceNoCase() instead", - "componentname": "CodeChecker", - "category": "Case Sensitive Functions - Best Practices", - "name": "REReplace()", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "5", - "customcode": "", - "bulkcheck": false, - "tagname": "", - "functionname": "checkCode" - } - -] \ No newline at end of file diff --git a/config/rules/bp.securityrisks.rules.json b/config/rules/bp.securityrisks.rules.json deleted file mode 100644 index 1e8e1db..0000000 --- a/config/rules/bp.securityrisks.rules.json +++ /dev/null @@ -1,283 +0,0 @@ -[ - { - "pattern": "|\\W+", - "message": "Catch blocks should not be empty.", - "componentname": "CodeChecker", - "category": "Standards", - "name": "Empty catch block", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "3", - "customcode": "", - "bulkcheck": true, - "tagname": "", - "functionname": "checkCode" - }, - { - "pattern": ".*output=\\042\\s*true\\s*\\042|.*output=\\s*true\\s*", - "message": "Output attribute of components and functions should be set to false.", - "componentname": "CodeChecker", - "category": "Standards", - "name": "Avoid using output=true in cfcomponent and cffunction", - "passonmatch": false, - "extensions": "cfm,cfc", - "severity": "3", - "customcode": "", - "bulkcheck": false, - "tagname": "cfcomponent|cffunction", - "functionname": "checkCode" - }, - { - "pattern": "function init\\(| \ No newline at end of file diff --git a/includes/i18n/i18n_goes_here.txt b/includes/i18n/i18n_goes_here.txt deleted file mode 100644 index e69de29..0000000 diff --git a/layouts/Main.cfm b/layouts/Main.cfm index 08871c2..c091bd8 100644 --- a/layouts/Main.cfm +++ b/layouts/Main.cfm @@ -1 +1 @@ - #html.doctype()# #prc.pageTitle#
#renderView()#
\ No newline at end of file + #html.doctype()# #prc.pageTitle#
#renderView()#
\ No newline at end of file diff --git a/lib/drop_jars_here.txt b/lib/drop_jars_here.txt deleted file mode 100644 index e69de29..0000000 diff --git a/models/CodeCheckerService.cfc b/models/CodeCheckerService.cfc deleted file mode 100644 index bf8c0a9..0000000 --- a/models/CodeCheckerService.cfc +++ /dev/null @@ -1,229 +0,0 @@ -/** -* I provide functions for checking code quality. -*/ -component accessors="true"{ - - // properties - property name="categories" type="string"; - property name="results" type="array"; - property name="rules" type="array"; - - /** - * I initialize the component. - * @rulesService I am the Rules service object. - * @utilService I am the Utility service object. - * @wirebox Instance of WireBox - * @categories I am a comma separated list of categories, _ALL for all categories. - */ - CodeCheckerService function init( - required any rulesService inject="RulesService", - required any utilService inject="UtilService", - required any wireBox inject="wirebox", - string categories = "" - ){ - // init properties - variables.results = []; - // Init DI - variables.rulesService = arguments.rulesService; - variables.wirebox = arguments.wirebox; - variables.utilService = arguments.utilService; - variables.categories = arguments.categories; - variables.rules = arguments.rulesService.getRules(); - - return this; - } - - /** - * I return whether the code check passed or failed. - * @line I am the line of code for which to check. - * @passonmatch I determine whether to pass or fail if the pattern is matched. - * @pattern I am the pattern of code for which to check. - */ - public boolean function checkCode( required string line, required boolean passonmatch, required string pattern ) { - if ( ( REFindNoCase( arguments.pattern, arguments.line ) AND NOT arguments.passonmatch ) OR ( NOT REFindNoCase( arguments.pattern, arguments.line ) AND arguments.passonmatch ) ) { - return false; - } - return true; - } - - /** - * I start the code review. - * @filepath I am the directory or file path for which to review. - * @recurse I determine whether or not to review recursively. - */ - public array function startCodeReview( required string filepath, boolean recurse = true ) { - if ( DirectoryExists(arguments.filepath) ) { - // path, recurse, listInfo, filter, sort - // TODO: DirectoryList() should filter on type=file - local.qryFiles = DirectoryList(arguments.filepath, arguments.recurse, "query"); - for ( local.row = 1; local.row LTE local.qryFiles.recordcount; local.row++ ) { - if ( local.qryFiles.type[local.row] IS "File" ) { - local.filePath = "#local.qryFiles.directory[local.row]#/#local.qryFiles.name[local.row]#"; - readFile(filepath=local.filePath); - if ( variables.categories IS "_ALL" OR ListFind( variables.categories, 'QueryParamScanner') ) { - runQueryParamScanner(filepath=local.filePath); - } - if ( variables.categories IS "_ALL" OR ListFind( variables.categories, 'VarScoper') ) { - runVarScoper(filepath=local.filePath) - } - } - } - } - else if ( FileExists(arguments.filepath) ) { - local.filePath = arguments.filepath; - readFile(filepath=local.filePath); - if ( variables.categories IS "_ALL" OR ListFind( variables.categories, 'QueryParamScanner') ) { - runQueryParamScanner(filepath=local.filePath); - } - if ( variables.categories IS "_ALL" OR ListFind( variables.categories, 'VarScoper') ) { - runVarScoper(filepath=local.filePath) - } - } - return variables.results; - } - - /** - * I read the file and run the rules against the file. - * @filepath I am the file path for which to review. - */ - public void function readFile( required string filepath ) { - local.dataFile = fileOpen( arguments.filepath, "read" ); - local.lineNumber = 0; - while ( !fileIsEOF( local.dataFile ) ) { - local.lineNumber++; - local.line = fileReadLine( local.dataFile ); - // run rules on each line - runRules(filepath=arguments.filepath, line=local.line, linenumber=local.lineNumber, categories=variables.categories); - if ( fileIsEOF( local.dataFile ) ) { - // run rules on whole file. useful for rules where you are just testing the existence of something. - runRules(filepath=arguments.filepath); - } - } - fileClose( local.dataFile ); - } - - /** - * I run the code review rules for the line of code. - * @filepath I am the file path for which to review. - * @line I am the line of code for which to review. - * @linenumber I am the line number of the code for which to review. - * @categories I am a comma separated list of categories, _ALL for all categories. - */ - public void function runRules( required string filepath, string line, numeric linenumber, string categories = "" ) { - local.standardizedfilepath = Replace(arguments.filepath, "\", "/", "all"); - local.file = ListLast(local.standardizedfilepath, "/"); - local.directory = Replace(local.standardizedfilepath, local.file, ""); - local.fileextension = ListLast(local.file, "."); - for ( local.ruleitem in variables.rules ) { - // backwards compat support for v1 - if ( local.ruleitem.componentname IS "CodeChecker" ) { - local.ruleitem.componentname = "CodeCheckerService"; - } - if ( arguments.categories IS "_ALL" OR ListFind( arguments.categories, local.ruleitem["category"] ) ) { - if ( NOT ListFindNoCase(local.ruleitem.extensions, local.fileextension, ",") ) { - continue; - } - if ( StructKeyExists(arguments,"line") AND NOT local.ruleitem.bulkcheck AND NOT ListLen(local.ruleitem.tagname,"|") ) { - local.codeCheckerReturn = variables.utilService._invoke( - obj = local.ruleitem.componentname, - fn = local.ruleitem.functionname, - args = { - line = arguments.line, - passonmatch = local.ruleitem.passonmatch, - pattern = local.ruleitem.pattern - } - ); - if ( NOT local.codeCheckerReturn ) { - recordResult(directory=local.directory, file=local.file, rule=local.ruleitem.name, message=local.ruleitem.message, linenumber=arguments.linenumber, category=local.ruleitem.category, severity=local.ruleitem.severity); - } - } - else if ( StructKeyExists(arguments,"line") AND NOT local.ruleitem.bulkcheck AND ListLen(local.ruleitem.tagname,"|") ) { - if ( REFindNoCase("<#Replace(local.ruleitem.tagname,'|','|<')#", arguments.line) ) { - local.codeCheckerReturn = variables.utilService._invoke( - obj = local.ruleitem.componentname, - fn = local.ruleitem.functionname, - args = { - line = arguments.line, - passonmatch = local.ruleitem.passonmatch, - pattern = local.ruleitem.pattern - } - ); - if ( NOT local.codeCheckerReturn ) { - recordResult(directory=local.directory, file=local.file, rule=local.ruleitem.name, message=local.ruleitem.message, linenumber=arguments.linenumber, category=local.ruleitem.category, severity=local.ruleitem.severity); - } - } - } - else if ( NOT StructKeyExists(arguments,"line") AND local.ruleitem.bulkcheck ) { - local.objJREUtils = wirebox.getInstance( "jre-utils" ); - local.dataFile = FileRead( arguments.filepath ); - local.matches = local.objJREUtils.get( local.dataFile , local.ruleitem.pattern ); - if ( ( local.ruleitem.passonmatch AND NOT ArrayLen(local.matches) ) OR ( ArrayLen(local.matches) AND NOT local.ruleitem.passonmatch ) ) { - // TODO: report actual line number - recordResult(directory=local.directory, file=local.file, rule=local.ruleitem.name, message=local.ruleitem.message, linenumber=-1, category=local.ruleitem.category, severity=local.ruleitem.severity); - } - } - else { - continue; - } - } - } - } - - /** - * I run the qpscanner component. - * @filepath I am the file path for which to review. - */ - public void function runQueryParamScanner( required string filepath ) { - local.standardizedfilepath = Replace(arguments.filepath, "\", "/", "all"); - local.file = ListLast(local.standardizedfilepath, "/"); - local.directory = Replace(local.standardizedfilepath, local.file, ""); - local.fileextension = ListLast(local.file, "."); - if ( ListFindNoCase("cfm,cfc",local.fileextension) ) { - - local.objJREUtils = wirebox.getInstance( "jre-utils" ).init(); - - local.objQueryParamScanner = wirebox.getInstance( - name = "qpscanner", - initArguments = { - jre = local.objJREUtils, - StartingDir = arguments.filepath, - OutputFormat = "wddx", - RequestTimeout = -1 - } - ); - local.qpScannerResult = local.objQueryParamScanner.go(); - for ( local.row = 1; local.row LTE local.qpScannerResult.data.recordcount; local.row++ ) { - recordResult(directory=local.directory, file=local.file, rule="Missing cfqueryparam", message="All query variables should utilize cfqueryparam. This helps prevent sql injection. It also increases query performance by caching the execution plan.", linenumber=local.qpScannerResult.data.querystartline[local.row], category="QueryParamScanner", severity="5"); - } - } - } - - /** - * I run the varScoper component. - * @filepath I am the file path for which to review. - */ - public void function runVarScoper( required string filepath ) { - local.standardizedfilepath = Replace(arguments.filepath, "\", "/", "all"); - local.file = ListLast(local.standardizedfilepath, "/"); - local.directory = Replace(local.standardizedfilepath, local.file, ""); - local.fileextension = ListLast(local.file, "."); - if ( local.fileextension IS "cfc" ) { - local.objVarScoper = wirebox.getInstance( name="varScoper", initArguments={ fileParseText=FileRead( arguments.filepath ) } ); - local.objVarScoper.runVarscoper(); - local.varScoperResult = local.objVarScoper.getResultsArray(); - for ( local.resultitem in local.varScoperResult ) { - for ( local.unscopedstruct in local.resultitem.unscopedarray ) { - recordResult(directory=local.directory, file=local.file, rule="Unscoped CFC variable", message="All CFC variables should be scoped in order to prevent memory leaks.", linenumber=local.unscopedstruct.linenumber, category="VarScoper", severity="5"); - } - } - } - } - - /** - * I record the result of the code review. - */ - public void function recordResult() { - ArrayAppend(variables.results, arguments); - } - -} diff --git a/models/QueryParamScanner/jre-utils.cfc b/models/QueryParamScanner/jre-utils.cfc deleted file mode 100644 index 0fbfb76..0000000 --- a/models/QueryParamScanner/jre-utils.cfc +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/models/QueryParamScanner/qpscanner.cfc b/models/QueryParamScanner/qpscanner.cfc deleted file mode 100644 index d3f4db0..0000000 --- a/models/QueryParamScanner/qpscanner.cfc +++ /dev/null @@ -1,310 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - findQueries |(?si)(<#cf#query[^p]).*?(?=) - findQueryTag |(?si)(<#cf#query[^p][^>]{0,300}>) - isQueryOfQuery |(?si)dbtype\s*=\s*["']query["'] - killParams |(?si)<#cf#queryparam[^>]+> - killCfTag |(?si)<#cf#[a-z]{2,}[^>]*> - killOrderBy |(?si)\bORDER BY\b.*?$ - killBuiltIn |(?si)##(#ListChangeDelims(This.BuiltInFunctions,'|')#)\([^)]*\)## - findScopes |(?si)(?<=##([a-z]{1,20}\()?)[^\(##<]+?(?=\.[^##<]+?##) - findName |(?si)(?<=(<#cf#query[^>]{0,300}\bname=")).*?(?="[^>]{0,300}>) - findClientScopes |(?i)\b(#ListChangeDelims(This.ClientScopes,'|')#)\b - isCfmlFile |(?i)\.cf(c|ml?)$ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SELECT * FROM Arguments.QueryOne - UNION SELECT * FROM Arguments.QueryTwo - - - - - - - - \ No newline at end of file diff --git a/models/QueryParamScanner/readme.txt b/models/QueryParamScanner/readme.txt deleted file mode 100644 index 9b6a040..0000000 --- a/models/QueryParamScanner/readme.txt +++ /dev/null @@ -1,115 +0,0 @@ -------------------------------------------------------------------------------- -qpScanner v0.7 - - - -INSTALLATION -============ - -Extract all files to a directory in your webroot, then access in a browser. - -Everything required is contained within the zip file, and no mappings nor -datasources need to be setup. - - - -ECLIPSE PLUGIN INSTALLATION -=========================== - -There is an Eclipse plugin available for QueryParam Scanner. - -To install the plugin, please add the update site to Eclipse: - - http://eclipse.hybridchill.com/ - -Please consult the documentation that comes with the Plugin for further -details on the Plugin and how to use it. - - - -USAGE -===== - -After launching QueryParam Scanner, you should see a Quick Start form: - - Select Config - This allows you to choose between "default" or "paranoid" configs. - The default config should be fine for most people. - - Starting Directory - Where you put the location of the project(s) you wish to scan. - This can be either an absolute path or a mapping. - - Recursive - Indicates if you want qpScanner to look inside directories, or remain - at the current directory level. - - -Once these are set as appropriate, press Scan and qpScanner will get to work. - -As it finds queries with CF variables (ie: #values_in_hashes#) that are not -inside a tag, it will list that file. The positions of the -queries are displayed when clicking on a file, and clicking on each of those -reveals the actual contents of the query. - -When complete, it will list how many were found out of how many total queries. - - - -NOTE: QueryParam Scanner should be used *only* in your development environment, -not on a live/public box. In addition to the security risks, it might have an -adverse affect on performance. - - - -KNOWN ISSUES -============ - -This is a development release of QueryParam Scanner, and this list of issues -may not be a complete one. Always ensure you have a recent backup of your code. - -There is one known issue with this version of qpScanner: - -1. Incorrect Line Numbers With Identical Queries -If you have a file with multiple identical queries (same name/attributes/SQL), -QueryParam Scanner will report line numbers correctly for only the first of -the queries. - - - -SUPPORT -======= - -For help or support, please see the project page at Hybridchill: -http://www.hybridchill.com/projects/qpscanner.html - - - - -CREDITS -======= - -QueryParam Scanner is a project created and maintained by Peter Boughton. - -It makes use of three other open-source projects: -- Java Regex Utilities http://www.hybridchill.com/projects/jre-utils.html -- jQuery JavaScript library http://www.jquery.com -- Fusebox Framework http://www.fuseboxframework.org - - - - -LICENSING & VERSIONS -==================== - -GPL license (see included gpl-license.txt for details) -- qpScanner v0.7.0 -- jre-utils v0.6.0 -- jQuery v1.2.6 - -Apache 2 license (see fusebox5/LICENSE.txt for details) -- Fusebox v5.5.1 - - - -------------------------------------------------------------------------------- \ No newline at end of file diff --git a/models/QueryParamScanner/settings.cfc b/models/QueryParamScanner/settings.cfc deleted file mode 100644 index 05129e5..0000000 --- a/models/QueryParamScanner/settings.cfc +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/models/RulesService.cfc b/models/RulesService.cfc deleted file mode 100644 index d7e1c5d..0000000 --- a/models/RulesService.cfc +++ /dev/null @@ -1,54 +0,0 @@ -/** -* I set the rules for the code checker. -*/ -component accessors="true" singleton{ - - property name="categories" type="array"; - property name="rules" type="array"; - - /** - * @hint I initialize the component. - * @rulesDirPath I am the directory path containing the rules. - */ - RulesService function init( string rulesDirPath = expandPath( '/codechecker/config/rules' ) ){ - - variables.categories = []; - variables.rules = []; - - //TODO: support cfscript patterns - //TODO: support multiline - //TODO: unscoped variables in cfm pages - //TODO: unnecessary use of pound signs - //TODO: reserved words/functions - //TODO: deprecated functions - //TODO: require return statement for return types other than void - - // path, recurse, listInfo, filter, sort - local.rulesFilePaths = directoryList( - arguments.rulesDirPath, - true, - "path", - "*.json", - "asc" - ); - - for ( local.ruleFile in local.rulesFilePaths ) { - // merge array of config data - if ( findNoCase( 'disabled',local.ruleFile ) == 0 ) { - variables.rules.addAll( deserializeJSON( fileRead( local.ruleFile ) ) ); - } - - } - - for( local.rule in variables.rules ) { - if ( findNoCase( 'disabled',local.ruleFile ) == 0 ) { - if ( NOT arrayFind( variables.categories, local.rule.category ) ) { - arrayAppend( variables.categories, local.rule.category); - } - } - } - - return this; - } - -} diff --git a/models/SpreadSheet/Spreadsheet.cfc b/models/SpreadSheet/Spreadsheet.cfc deleted file mode 100644 index 40a7787..0000000 --- a/models/SpreadSheet/Spreadsheet.cfc +++ /dev/null @@ -1,1159 +0,0 @@ -component{ - - variables.version = "0.4.8"; - variables.poiLoaderName = "_poiLoader-" & Hash( GetCurrentTemplatePath() ); - - variables.dateFormats = { - DATE = "yyyy-mm-dd" - ,DATETIME = "yyyy-mm-dd HH:nn:ss" - ,TIME = "hh:mm:ss" - ,TIMESTAMP = "yyyy-mm-dd hh:mm:ss" - }; - variables.exceptionType = "cfsimplicity.lucee.spreadsheet"; - - include "tools.cfm"; - include "formatting.cfm"; - - function init( struct dateFormats ){ - if( arguments.KeyExists( "dateFormats" ) ) - this.overrideDefaultDateFormats( arguments.dateFormats ); - return this; - } - - private void function overrideDefaultDateFormats( required struct formats ){ - for( var format in formats ){ - if( !variables.dateFormats.KeyExists( format ) ) - throw( type=exceptionType,message="Invalid date format key",detail="'#format#' is not a valid dateformat key. Valid keys are DATE, DATETIME, TIME and TIMESTAMP" ); - variables.dateFormats[ format ]=formats[ format ]; - } - } - - void function flushPoiLoader(){ - lock scope="server" timeout="10"{ - StructDelete( server,poiLoaderName ); - }; - } - - /* META INFO */ - public struct function getDateFormats(){ - return dateFormats; - } - - /* CUSTOM METHODS */ - - any function workbookFromQuery( required query data,boolean addHeaderRow=true,boldHeaderRow=true,xmlFormat=false ){ - var workbook = this.new( xmlFormat=xmlFormat ); - if( addHeaderRow ){ - var columns = QueryColumnArray( data ); - this.addRow( workbook,columns.ToList() ); - if( boldHeaderRow ) - this.formatRow( workbook,{ bold=true },1 ); - this.addRows( workbook,data,2,1 ); - } else { - this.addRows( workbook,data ); - } - return workbook; - } - - binary function binaryFromQuery( required query data,boolean addHeaderRow=true,boldHeaderRow=true,xmlFormat=false ){ - /* Pass in a query and get a spreadsheet binary file ready to stream to the browser */ - var workbook = this.workbookFromQuery( argumentCollection=arguments ); - return this.readBinary( workbook ); - } - - void function downloadFileFromQuery( - required query data - ,required string filename - ,boolean addHeaderRow=true - ,boolean boldHeaderRow=true - ,boolean xmlFormat=false - ,string contentType - ){ - var safeFilename = this.filenameSafe( filename ); - var filenameWithoutExtension = safeFilename.REReplace( "\.xlsx?$","" ); - var binary = this.binaryFromQuery( data,addHeaderRow,boldHeaderRow,xmlFormat ); - if( !arguments.KeyExists( "contentType" ) ) - arguments.contentType = xmlFormat? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "application/msexcel"; - var extension = xmlFormat? "xlsx": "xls"; - header name="Content-Disposition" value="attachment; filename=#Chr(34)##filenameWithoutExtension#.#extension##Chr(34)#"; - content type=contentType variable="#binary#" reset="true"; - } - - void function downloadCsvFromFile( - required string src - ,required string filename - ,string contentType="text/csv" - ,string columns - ,string columnNames - ,numeric headerRow - ,string rows - ,string sheetName - ,numeric sheetNumber // 1-based - ,boolean includeHeaderRow=false - ,boolean includeBlankRows=false - ,boolean fillMergedCellsWithVisibleValue=false - ){ - arguments.format="csv"; - var csv=this.read( argumentCollection=arguments ); - var binary=ToBinary( ToBase64( csv.Trim() ) ); - var safeFilename = this.filenameSafe( filename ); - var filenameWithoutExtension = safeFilename.REReplace( "\.csv$","" ); - header name="Content-Disposition" value="attachment; filename=#Chr(34)##filenameWithoutExtension#.csv#Chr(34)#"; - content type=contentType variable="#binary#" reset="true"; - } - - void function writeFileFromQuery( - required query data - ,required string filepath - ,boolean overwrite=false - ,boolean addHeaderRow=true - ,boldHeaderRow=true - ,xmlFormat=false - ){ - if( !xmlFormat AND ( ListLast( filepath,"." ) IS "xlsx" ) ) - arguments.xmlFormat=true; - var workbook = this.workbookFromQuery( data,addHeaderRow,boldHeaderRow,xmlFormat ); - if( xmlFormat AND ( ListLast( filepath,"." ) IS "xls" ) ) - arguments.filePath &="x";// force to .xlsx - this.write( workbook=workbook,filepath=filepath,overwrite=overwrite ); - } - - /* MAIN API */ - - void function addColumn( - required workbook - ,required string data /* Delimited list of cell values */ - ,numeric startRow - ,numeric startColumn - ,boolean insert=true - ,string delimiter="," - ,boolean autoSize=false - ){ - var row = 0; - var cell = 0; - var oldCell = 0; - var rowNum = ( arguments.KeyExists( "startRow" ) AND startRow )? startRow-1: 0; - var cellNum = 0; - var lastCellNum = 0; - var cellValue = 0; - if( arguments.KeyExists( "startColumn" ) ){ - cellNum = startColumn-1; - } else { - row = this.getActiveSheet( workbook ).getRow( rowNum ); - /* if this row exists, find the next empty cell number. note: getLastCellNum() returns the cell index PLUS ONE or -1 if not found */ - if( !IsNull( row ) AND row.getLastCellNum() GT 0 ) - cellNum = row.getLastCellNum(); - else - cellNum = 0; - } - var columnNumber = cellNum+1; - var columnData = ListToArray( data,delimiter ); - for( var cellValue in columnData ){ - /* if rowNum is greater than the last row of the sheet, need to create a new row */ - if( rowNum GT this.getActiveSheet( workbook ).getLastRowNum() OR IsNull( this.getActiveSheet( workbook ).getRow( rowNum ) ) ) - row = this.createRow( workbook,rowNum ); - else - row = this.getActiveSheet( workbook ).getRow( rowNum ); - /* POI doesn't have any 'shift column' functionality akin to shiftRows() so inserts get interesting */ - /* ** Note: row.getLastCellNum() returns the cell index PLUS ONE or -1 if not found */ - if( insert AND ( cellNum LT row.getLastCellNum() ) ){ - /* need to get the last populated column number in the row, figure out which cells are impacted, and shift the impacted cells to the right to make room for the new data */ - lastCellNum = row.getLastCellNum(); - for( var i=lastCellNum; i EQ cellNum; i-- ){ - oldCell = row.getCell( JavaCast( "int",i-1 ) ); - if( !IsNull( oldCell ) ){ - cell = this.createCell( row,i ); - cell.setCellStyle( oldCell.getCellStyle() ); - var cellValue = this.getCellValueAsType( workbook,oldCell ); - this.setCellValueAsType( workbook,oldCell,cellValue ); - cell.setCellComment( oldCell.getCellComment() ); - } - } - } - cell = this.createCell( row,cellNum ); - this.setCellValueAsType( workbook,cell,cellValue ); - rowNum++; - } - if( autoSize ) - this.autoSizeColumn( workbook,columnNumber ); - } - - void function addFreezePane( - required workbook - ,required numeric freezeColumn - ,required numeric freezeRow - ,numeric leftmostColumn //left column visible in right pane - ,numeric topRow //top row visible in bottom pane - ){ - if( arguments.KeyExists( "leftmostColumn" ) AND !arguments.KeyExists( "topRow" ) ) - arguments.topRow = freezeRow; - if( arguments.KeyExists( "topRow" ) AND !arguments.KeyExists( "leftmostColumn" ) ) - arguments.leftmostColumn = freezeColumn; - /* createFreezePane() operates on the logical row/column numbers as opposed to physical, so no need for n-1 stuff here */ - if( !arguments.KeyExists( "leftmostColumn" ) ){ - this.getActiveSheet( workbook ).createFreezePane( JavaCast( "int",freezeColumn ),JavaCast( "int",freezeRow ) ); - return; - } - // POI lets you specify an active pane if you use createSplitPane() here - this.getActiveSheet( workbook ).createFreezePane( - JavaCast( "int",freezeColumn ) - ,JavaCast( "int",freezeRow ) - ,JavaCast( "int",leftmostColumn ) - ,JavaCast( "int",topRow ) - ); - } - - void function addImage( - required workbook - ,string filepath - ,imageData - ,string imageType - ,required string anchor - ){ - /* - TODO: Should we allow for passing in of a boolean indicating whether or not an image resize should happen (only works on jpg and png)? Currently does not resize. If resize is performed, it does mess up passing in x/y coordinates for image positioning. - */ - if( !arguments.KeyExists( "filepath" ) AND !arguments.KeyExists( "imageData" ) ) - throw( type=exceptionType,message="Invalid argument combination",detail="You must provide either a file path or an image object" ); - if( arguments.KeyExists( "imageData" ) AND !arguments.KeyExists( "imageType" ) ) - throw( type=exceptionType,message="Invalid argument combination",detail="If you specify an image object, you must also provide the imageType argument" ); - var numberOfAnchorElements = ListLen( anchor ); - if( ( numberOfAnchorElements NEQ 4 ) AND ( numberOfAnchorElements NEQ 8 ) ) - throw( type=exceptionType,message="Invalid anchor argument",detail="The anchor argument must be a comma-delimited list of integers with either 4 or 8 elements" ); - //we'll need the image type int in all cases - if( arguments.KeyExists( "filepath" ) ){ - if( !FileExists( filepath ) ) - throw( type=exceptionType,message="Non-existent file",detail="The specified file does not exist." ); - try{ - arguments.imageType = ListLast( FileGetMimeType( filepath ),"/" ); - } - catch( any exception ){ - throw( type=exceptionType,message="Could Not Determine Image Type",detail="An image type could not be determined from the filepath provided" ); - } - } else if( !arguments.KeyExists( "imageType" ) ){ - throw( type=exceptionType,message="Could Not Determine Image Type",detail="An image type could not be determined from the filepath or imagetype provided" ); - } - arguments.imageType = imageType.UCase(); - switch( imageType ){ - case "DIB": case "EMF": case "JPEG": case "PICT": case "PNG": case "WMF": - var imageTypeIndex = workbook[ "PICTURE_TYPE_" & imageType ]; - break; - case "JPG": - var imageTypeIndex = workbook.PICTURE_TYPE_JPEG; - break; - default: - throw( type=exceptionType,message="Invalid Image Type",detail="Valid image types are DIB, EMF, JPG, JPEG, PICT, PNG, and WMF" ); - } - if( arguments.KeyExists( "filepath" ) ){ - try{ - var inputStream = CreateObject( "java","java.io.FileInputStream" ).init( JavaCast("string",filepath ) ); - var ioUtils = this.loadPoi( "org.apache.poi.util.IOUtils" ); - var bytes = ioUtils.toByteArray( inputStream ); - } - finally{ - inputStream.close(); - } - } else { - var bytes = ToBinary( imageData ); - } - var imageIndex = workbook.addPicture( bytes,JavaCast( "int",imageTypeIndex ) ); - var theAnchor = this.loadPoi( "org.apache.poi.hssf.usermodel.HSSFClientAnchor" ).init(); - if( numberOfAnchorElements EQ 4 ){ - theAnchor.setRow1( JavaCast( "int",ListFirst( anchor )-1 ) ); - theAnchor.setCol1( JavaCast( "int",ListGetAt( anchor, 2 )-1 ) ); - theAnchor.setRow2( JavaCast( "int",ListGetAt( anchor, 3 )-1 ) ); - theAnchor.setCol2( JavaCast( "int",ListLast( anchor )-1 ) ); - } else if( numberOfAnchorElements EQ 8 ){ - theAnchor.setDx1( JavaCast( "int",ListFirst( anchor ) ) ); - theAnchor.setDy1( JavaCast( "int",ListGetAt( anchor,2 ) ) ); - theAnchor.setDx2( JavaCast( "int",ListGetAt( anchor,3 ) ) ); - theAnchor.setDy2( JavaCast( "int",ListGetAt( anchor,4 ) ) ); - theAnchor.setRow1( JavaCast( "int",ListGetAt( anchor,5 )-1 ) ); - theAnchor.setCol1( JavaCast( "int",ListGetAt( anchor,6 )-1 ) ); - theAnchor.setRow2( JavaCast( "int",ListGetAt( anchor,7 )-1 ) ); - theAnchor.setCol2( JavaCast( "int",ListLast( anchor )-1 ) ); - } - /* TODO: need to look into createDrawingPatriarch() vs. getDrawingPatriarch() since create will kill any existing images. getDrawingPatriarch() throws a null pointer exception when an attempt is made to add a second image to the spreadsheet */ - var drawingPatriarch = getActiveSheet( workbook ).createDrawingPatriarch(); - var picture = drawingPatriarch.createPicture( theAnchor,imageIndex ); - /* Disabling this for now--maybe let people pass in a boolean indicating whether or not they want the image resized? - if this is a png or jpg, resize the picture to its original size (this doesn't work for formats other than jpg and png) - - - - */ - } - - void function addInfo( required workbook,required struct info ){ - /* Valid struct keys are author, category, lastauthor, comments, keywords, manager, company, subject, title */ - if( this.isBinaryFormat( workbook ) ) - this.addInfoBinary( workbook,info ); - else - this.addInfoXml( workbook,info ); - } - - void function addRow( - required workbook - ,required string data /* Delimited list of data */ - ,numeric row - ,numeric column=1 - ,boolean insert=true - ,string delimiter="," - ,boolean handleEmbeddedCommas=true /* When true, values enclosed in single quotes are treated as a single element like in ACF. Only applies when the delimiter is a comma. */ - ,boolean autoSizeColumns=false - ){ - if( arguments.KeyExists( "row" ) AND ( row LTE 0 ) ) - throw( type=exceptionType,message="Invalid row value",detail="The value for row must be greater than or equal to 1." ); - if( arguments.KeyExists( "column" ) AND ( column LTE 0 ) ) - throw( type=exceptionType,message="Invalid column value",detail="The value for column must be greater than or equal to 1." ); - if( !insert AND !arguments.KeyExists( "row") ) - throw( type=exceptionType,message="Missing row value",detail="To replace a row using 'insert', please specify the row to replace." ); - var lastRow = this.getNextEmptyRow( workbook ); - //If the requested row already exists... - if( arguments.KeyExists( "row" ) AND ( row LTE lastRow ) ){ - if( arguments.insert ) - shiftRows( workbook,row,lastRow,1 );//shift the existing rows down (by one row) - else - deleteRow( workbook,row );//otherwise, clear the entire row - } - var theRow = arguments.KeyExists( "row" )? this.createRow( workbook,arguments.row-1 ): this.createRow( workbook ); - var rowValues = this.parseRowData( data,delimiter,handleEmbeddedCommas ); - var cellIndex = column-1; - for( var cellValue in rowValues ){ - var cell = this.createCell( theRow,cellIndex ); - this.setCellValueAsType( workbook,cell,cellValue.Trim() ) - if( autoSizeColumns ) - this.autoSizeColumn( workbook,column ); - cellIndex++; - } - } - - void function addRows( - required workbook - ,required query data - ,numeric row - ,numeric column=1 - ,boolean insert=true - ,boolean autoSizeColumns=false - ){ - var lastRow = this.getNextEmptyRow( workbook ); - if( arguments.KeyExists( "row" ) AND ( row LTE lastRow ) AND insert ) - shiftRows( workbook,row,lastRow,data.recordCount ); - var rowNum = arguments.keyExists( "row" )? row-1: this.getNextEmptyRow( workbook ); - var queryColumns = this.getQueryColumnFormats( workbook,data ); - var dateUtil = this.getDateUtil(); - for( var dataRow in data ){ - var newRow = this.createRow( workbook,rowNum,false ); - var cellIndex = ( column-1 ); - /* Note: To properly apply date/number formatting: - - cell type must be CELL_TYPE_NUMERIC - - cell value must be applied as a java.util.Date or java.lang.Double (NOT as a string) - - cell style must have a dataFormat (datetime values only) - */ - /* populate all columns in the row */ - for( var queryColumn in queryColumns ){ - var cell = this.createCell( newRow, cellIndex, false ); - var value = dataRow[ queryColumn.name ]; - var forceDefaultStyle = false; - queryColumn.index = cellIndex; - /* Cast the values to the correct type, so data formatting is properly applied */ - if( queryColumn.cellDataType IS "DOUBLE" AND IsNumeric( value ) ){ - cell.setCellValue( JavaCast( "double",Val( value ) ) ); - } else if( queryColumn.cellDataType IS "TIME" AND IsDate( value ) ){ - value = TimeFormat( ParseDateTime( value ),"HH:MM:SS"); - cell.setCellValue( dateUtil.convertTime( value ) ); - forceDefaultStyle = true; - } else if( queryColumn.cellDataType EQ "DATE" AND IsDate( value ) ){ - /* If the cell is NOT already formatted for dates, apply the default format brand new cells have a styleIndex == 0 */ - var styleIndex = cell.getCellStyle().getDataFormat(); - var styleFormat = cell.getCellStyle().getDataFormatString(); - if( styleIndex EQ 0 OR NOT dateUtil.isADateFormat( styleIndex,styleFormat ) ) - forceDefaultStyle = true; - cell.setCellValue( ParseDateTime( value ) ); - } else if( queryColumn.cellDataType EQ "BOOLEAN" AND IsBoolean( value ) ){ - cell.setCellValue( JavaCast( "boolean",value ) ); - } else if( IsSimpleValue( value ) AND !Len( value ) ){ //NB don't use member function: won't work if numeric - cell.setCellType( cell.CELL_TYPE_BLANK ); - } else { - cell.setCellValue( JavaCast( "string",value ) ); - } - /* Replace the existing styles with custom formatting */ - if( queryColumn.KeyExists( "customCellStyle" ) ){ - cell.setCellStyle( queryColumn.customCellStyle ); - /* Replace the existing styles with default formatting (for readability). The reason we cannot just update the cell's style is because they are shared. So modifying it may impact more than just this one cell. */ - } else if( queryColumn.KeyExists( "defaultCellStyle" ) AND forceDefaultStyle ){ - cell.setCellStyle( queryColumn.defaultCellStyle ); - } - cellIndex++; - } - rowNum++; - } - if( autoSizeColumns ){ - var numberOfColumns = queryColumns.Len(); - var thisColumn = column; - for( var i=thisColumn; i LTE numberOfColumns; i++ ){ - this.autoSizeColumn( workbook,thisColumn ); - thisColumn++; - } - } - } - - void function addSplitPane( - required workbook - ,required numeric xSplitPosition - ,required numeric ySplitPosition - ,required numeric leftmostColumn - ,required numeric topRow - ,string activePane="UPPER_LEFT" //Valid values are LOWER_LEFT, LOWER_RIGHT, UPPER_LEFT, and UPPER_RIGHT - ){ - var activeSheet = this.getActiveSheet( workbook ); - arguments.activePane = activeSheet[ "PANE_#activePane#" ]; - activeSheet.createSplitPane( - JavaCast( "int",xSplitPosition ) - ,JavaCast( "int",ySplitPosition ) - ,JavaCast( "int",leftmostColumn ) - ,JavaCast( "int",topRow ) - ,JavaCast( "int",activePane ) - ); - } - - void function autoSizeColumn( required workbook,required numeric column,boolean useMergedCells=false ){ - if( column LTE 0 ) - throw( type=exceptionType,message="Invalid column value",detail="The value for column must be greater than or equal to 1." ); - /* Adjusts the width of the specified column to fit the contents. For performance reasons, this should normally be called only once per column. */ - var columnIndex = column-1; - this.getActiveSheet( workbook ).autoSizeColumn( columnIndex,useMergedCells ); - } - - void function clearCell( required workbook,required numeric row,required numeric column ){ - /* Clears the specified cell of all styles and values */ - var defaultStyle = workbook.getCellStyleAt( JavaCast( "short",0 ) ); - var rowIndex = row-1; - var rowObject = this.getActiveSheet( workbook ).getRow( JavaCast( "int",rowIndex ) ); - if( IsNull( rowObject ) ) - return; - var columnIndex = column-1; - var cell = rowObject.getCell( JavaCast( "int",columnIndex ) ); - if( IsNull( cell ) ) - return; - cell.setCellStyle( defaultStyle ); - cell.setCellType( cell.CELL_TYPE_BLANK ); - } - - void function clearCellRange( - required workbook - ,required numeric startRow - ,required numeric startColumn - ,required numeric endRow - ,required numeric endColumn - ){ - /* Clears the specified cell range of all styles and values */ - for( var rowNumber=startRow; rowNumber LTE endRow; rowNumber++ ){ - for( var columnNumber=startColumn; columnNumber LTE endColumn; columnNumber++ ){ - clearCell( workbook,rowNumber,columnNumber ); - } - } - } - - void function createSheet( required workbook,string sheetName,overwrite=false ){ - if( arguments.KeyExists( "sheetName" ) ) - this.validateSheetName( sheetName ); - else - arguments.sheetName = this.generateUniqueSheetName( workbook ); - if( !this.sheetExists( workbook=workbook,sheetName=sheetName ) ){ - workbook.createSheet( JavaCast( "String",sheetName ) ); - return; - } - /* sheet already exists with that name */ - if( !overwrite ) - throw( type=exceptionType,message="Sheet name already exists",detail="A sheet with the name '#sheetName#' already exists in this workbook" ); - /* OK to replace the existing */ - var sheetIndexToReplace = workbook.getSheetIndex( JavaCast( "string",sheetName) ); - this.deleteSheetAtIndex( workbook,sheetIndexToReplace ); - var newSheet = workbook.createSheet( JavaCast( "String",sheetName ) ); - var moveToIndex = sheetIndexToReplace; - this.moveSheet( workbook,sheetName,moveToIndex ); - } - - void function deleteColumn( required workbook,required numeric column ){ - if( column LTE 0 ) - throw( type=exceptionType,message="Invalid column value",detail="The value for column must be greater than or equal to 1." ); - /* POI doesn't have remove column functionality, so iterate over all the rows and remove the column indicated */ - var rowIterator = this.getActiveSheet( workbook ).rowIterator(); - while( rowIterator.hasNext() ){ - var row = rowIterator.next(); - var cell = row.getCell( JavaCast( "int",column-1 ) ); - if( IsNull( cell ) ) - continue; - row.removeCell( cell ); - } - } - - void function deleteColumns( required workbook,required string range ){ - /* Validate and extract the ranges. Range is a comma-delimited list of ranges, and each value can be either a single number or a range of numbers with a hyphen. */ - var allRanges = this.extractRanges( range ); - for( var thisRange in allRanges ){ - if( thisRange.startAt EQ thisRange.endAt ){ - /* Just one row */ - this.deleteColumn( workbook,thisRange.startAt ); - continue; - } - for( var columnNumber=thisRange.startAt; columnNumber LTE thisRange.endAt; columnNumber++ ){ - this.deleteColumn( workbook,columnNumber ); - } - } - } - - void function deleteRow( required workbook,required numeric row ){ - /* Deletes the data from a row. Does not physically delete the row. */ - if( row LTE 0 ) - throw( type=exceptionType,message="Invalid row value",detail="The value for row must be greater than or equal to 1." ); - var rowToDelete = row-1; - if( rowToDelete GTE this.getFirstRowNum( workbook ) AND rowToDelete LTE this.getLastRowNum( workbook ) ) //If this is a valid row, remove it - this.getActiveSheet( workbook ).removeRow( this.getActiveSheet( workbook ).getRow( JavaCast( "int",rowToDelete ) ) ); - } - - void function deleteRows( required workbook,required string range ){ - /* Validate and extract the ranges. Range is a comma-delimited list of ranges, and each value can be either a single number or a range of numbers with a hyphen. */ - var allRanges = this.extractRanges( range ); - for( var thisRange in allRanges ){ - if( thisRange.startAt EQ thisRange.endAt ){ - /* Just one row */ - this.deleteRow( workbook,thisRange.startAt ); - continue; - } - for( var rowNumber=thisRange.startAt; rowNumber LTE thisRange.endAt; rowNumber++ ){ - this.deleteRow( workbook,rowNumber ); - } - } - } - - void function formatCell( required workbook,required struct format,required numeric row,required numeric column,any cellStyle ){ - var cell = this.initializeCell( workbook,row,column ); - if( arguments.KeyExists( "cellStyle" ) ) - cell.setCellStyle( cellStyle );// reuse an existing style - else - cell.setCellStyle( this.buildCellStyle( workbook,format ) ); - } - - void function formatCellRange( - required workbook - ,required struct format - ,required numeric startRow - ,required numeric endRow - ,required numeric startColumn - ,required numeric endColumn - ){ - var style = this.buildCellStyle( workbook,format ); - for( var rowNumber=startRow; rowNumber LTE endRow; rowNumber++ ){ - for( var columnNumber=startColumn; columnNumber LTE endColumn; columnNumber++ ){ - this.formatCell( workbook,format,rowNumber,columnNumber,style ); - } - } - } - - void function formatColumn( required workbook,required struct format,required numeric column ){ - if( column LT 1 ) - throw( type=exceptionType,message="Invalid column value",detail="The column value must be greater than 0" ); - var rowIterator = this.getActiveSheet( workbook ).rowIterator(); - var columnNumber = column; - while( rowIterator.hasNext() ){ - var rowNumber = rowIterator.next().getRowNum() + 1; - this.formatCell( workbook,format,rowNumber,columnNumber ); - } - } - - void function formatColumns( required workbook,required struct format,required string range ){ - /* Validate and extract the ranges. Range is a comma-delimited list of ranges, and each value can be either a single number or a range of numbers with a hyphen. */ - var allRanges = this.extractRanges( range ); - for( var thisRange in allRanges ){ - if( thisRange.startAt EQ thisRange.endAt ){ - /* Just one column */ - this.formatColumn( workbook,format,thisRange.startAt ); - continue; - } - for( var columnNumber=thisRange.startAt; columnNumber LTE thisRange.endAt; columnNumber++ ){ - this.formatColumn( workbook,format,columnNumber ); - } - } - } - - void function formatRow( required workbook,required struct format,required numeric row ){ - var rowIndex = row-1; - var theRow = this.getActiveSheet( workbook ).getRow( rowIndex ); - if( IsNull( theRow ) ) - return; - var cellIterator = theRow.cellIterator(); - while( cellIterator.hasNext() ){ - formatCell( workbook,format,row,cellIterator.next().getColumnIndex()+1 ); - } - } - - void function formatRows( required workbook,required struct format,required string range ){ - /* Validate and extract the ranges. Range is a comma-delimited list of ranges, and each value can be either a single number or a range of numbers with a hyphen. */ - var allRanges = this.extractRanges( range ); - for( var thisRange in allRanges ){ - if( thisRange.startAt EQ thisRange.endAt ){ - /* Just one row */ - this.formatRow( workbook,format,thisRange.startAt ); - continue; - } - for( var rowNumber=thisRange.startAt; rowNumber LTE thisRange.endAt; rowNumber++ ){ - this.formatRow( workbook,format,rowNumber ); - } - } - } - - function getCellComment( required workbook,numeric row,numeric column ){ - if( arguments.keyExists( "row" ) AND !arguments.KeyExists( "column" ) ) - throw( type=exceptionType,message="Invalid argument combination",detail="If you specify the row you must also specify the column" ); - if( arguments.keyExists( "column" ) AND !arguments.KeyExists( "row" ) ) - throw( type=exceptionType,message="Invalid argument combination",detail="If you specify the column you must also specify the row" ); - if( arguments.KeyExists( "row" ) ){ - var cell = this.getCellAt( workbook,row,column ); - var commentObject = cell.getCellComment(); - if( !IsNull( commentObject ) ){ - return { - author = commentObject.getAuthor() - ,comment = commentObject.getString().getString() - ,column = column - ,row = row - } - } - return {}; - } - /* TODO: Look into checking all sheets in the workbook */ - /* row and column weren't provided so loop over the whole sheet and return all the comments as an array of structs */ - var result = []; - var rowIterator = this.getActiveSheet( workbook ).rowIterator(); - while( rowIterator.hasNext() ){ - var cellIterator = rowIterator.next().cellIterator(); - while( cellIterator.hasNext() ){ - var commentObject = cellIterator.next().getCellComment(); - if( !IsNull( commentObject ) ){ - var comment = { - author = commentObject.getAuthor() - ,comment = commentObject.getString().getString() - ,column = column - ,row = row - } - comments.Append( comment ); - } - } - } - return comments; - } - - function getCellFormula( required workbook,numeric row,numeric column ){ - if( arguments.KeyExists( "row" ) AND arguments.KeyExists( "column" ) ){ - if( cellExists( workbook,row,column ) ){ - var cell = getCellAt( workbook,row,column ); - if( cell.getCellType() IS cell.CELL_TYPE_FORMULA ) - return cell.getCellFormula(); - return ""; - } - } - //no row and column provided so return an array of structs containing formulas for the entire sheet - var rowIterator = getActiveSheet( workbook ).rowIterator(); - var formulas = []; - while( rowIterator.hasNext() ){ - var cellIterator = rowIterator.next().cellIterator(); - while( cellIterator.hasNext() ){ - var cell = cellIterator.next(); - var formulaStruct = { - row = ( cell.getRowIndex() + 1 ) - ,column = ( cell.getColumnIndex() + 1 ) - }; - try{ - formulaStruct.formula = cell.getCellFormula(); - } - catch( any exception ){ - formulaStruct.formula = ""; - } - if( formulaStruct.formula.Len() ) - formulas.Append( formulaStruct ); - } - } - return formulas; - } - - function getCellValue( required workbook,required numeric row,required numeric column ){ - if( !this.cellExists( workbook,row,column ) ) - return ""; - var rowIndex = row-1; - var columnIndex = column-1; - var rowObject = this.getActiveSheet( workbook ).getRow( JavaCast( "int",rowIndex ) ); - var cell = rowObject.getCell( JavaCast( "int",columnIndex ) ); - var formatter = this.getFormatter(); - if( cell.getCellType() EQ cell.CELL_TYPE_FORMULA ){ - var formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); - return formatter.formatCellValue( cell,formulaEvaluator ); - } - return formatter.formatCellValue( cell ); - } - - struct function info( required workbook ){ - /* - workbook properties returned in the struct are: - * AUTHOR - * CATEGORY - * COMMENTS - * CREATIONDATE - * LASTEDITED - * LASTAUTHOR - * LASTSAVED - * KEYWORDS - * MANAGER - * COMPANY - * SUBJECT - * TITLE - * SHEETS - * SHEETNAMES - * SPREADSHEETTYPE - */ - //format specific metadata - var info = this.isBinaryFormat( workbook )? this.binaryInfo( workbook ): this.xmlInfo( workbook ); - //common properties - info.sheets = workbook.getNumberOfSheets(); - var sheetnames = []; - if( IsNumeric( info.sheets ) ){ - for( var i=1; i LTE info.sheets; i++ ){ - sheetnames.Append( workbook.getSheetName( JavaCast( "int",i-1 ) ) ); - } - info.sheetnames = sheetnames.ToList(); - } - info.spreadSheetType = this.isXmlFormat( workbook )? "Excel (2007)": "Excel"; - return info; - } - - boolean function isBinaryFormat( required workbook ){ - return workbook.getClass().getCanonicalName() IS "org.apache.poi.hssf.usermodel.HSSFWorkbook"; - } - - boolean function isXmlFormat( required workbook ){ - return workbook.getClass().getCanonicalName() IS "org.apache.poi.xssf.usermodel.XSSFWorkbook"; - } - - void function mergeCells( - required workbook - ,required numeric startRow - ,required numeric endRow - ,required numeric startColumn - ,required numeric endColumn - ,boolean emptyInvisibleCells=false - ){ - if( startRow LT 1 OR startRow GT endRow ) - throw( type=exceptionType,message="Invalid startRow or endRow",detail="Row values must be greater than 0 and the startRow cannot be greater than the endRow." ); - if( startColumn LT 1 OR startColumn GT endColumn ) - throw( type=exceptionType,message="Invalid startColumn or endColumn",detail="Column values must be greater than 0 and the startColumn cannot be greater than the endColumn." ); - var cellRangeAddress = loadPoi( "org.apache.poi.ss.util.CellRangeAddress" ).init( - JavaCast( "int",startRow - 1 ) - ,JavaCast( "int",endRow - 1 ) - ,JavaCast( "int",startColumn - 1 ) - ,JavaCast( "int",endColumn - 1 ) - ); - this.getActiveSheet( workbook ).addMergedRegion( cellRangeAddress ); - if( !emptyInvisibleCells ) - return; - // stash the value to retain - var visibleValue = getCellValue( workbook,startRow,startColumn ); - //empty all cells in the merged region - setCellRangeValue( workbook,"",startRow,endRow,startColumn,endColumn ); - //restore the stashed value - setCellValue( workbook,visibleValue,startRow,startColumn ); - } - - function new( string sheetName="Sheet1",boolean xmlformat=false ){ - var workbook = this.createWorkBook( sheetName,xmlFormat ); - this.createSheet( workbook,sheetName,xmlformat ); - setActiveSheet( workbook,sheetName ); - return workbook; - } - - function read( - required string src - ,string format - ,string columns - ,string columnNames - ,numeric headerRow - ,string rows - ,string sheetName - ,numeric sheetNumber // 1-based - ,boolean includeHeaderRow=false - ,boolean includeBlankRows=false - ,boolean fillMergedCellsWithVisibleValue=false - ){ - if( arguments.KeyExists( "query" ) ) - throw( type=exceptionType,message="Invalid argument 'query'.",details="Just use format='query' to return a query object" ); - if( arguments.KeyExists( "format" ) AND !ListFindNoCase( "query,html,csv",format ) ) - throw( type=exceptionType,message="Invalid format",detail="Supported formats are: 'query', 'html' and 'csv'" ); - if( arguments.KeyExists( "sheetName" ) AND arguments.KeyExists( "sheetNumber" ) ) - throw( type=exceptionType,message="Cannot provide both sheetNumber and sheetName arguments",detail="Only one of either 'sheetNumber' or 'sheetName' arguments may be provided." ); - if( !FileExists( src ) ) - throw( type=exceptionType,message="Non-existent file",detail="Cannot find the file #src#." ); - var workbook = this.workbookFromFile( src ); - if( arguments.KeyExists( "sheetName" ) ) - this.setActiveSheet( workbook=workbook,sheetName=sheetName ); - if( !arguments.keyExists( "format" ) ) - return workbook; - var args = { - workbook = workbook - }; - if( arguments.KeyExists( "sheetName" ) ) - args.sheetName = sheetName; - if( arguments.KeyExists( "sheetNumber" ) ) - args.sheetNumber = sheetNumber; - if( arguments.KeyExists( "headerRow" ) ){ - args.headerRow=headerRow; - args.includeHeaderRow = includeHeaderRow; - } - if( arguments.KeyExists( "rows" ) ) - args.rows = rows; - if( arguments.KeyExists( "columns" ) ) - args.columns = columns; - if( arguments.KeyExists( "columnNames" ) ) - args.columnNames = columnNames; - args.includeBlankRows=includeBlankRows; - args.fillMergedCellsWithVisibleValue=fillMergedCellsWithVisibleValue; - var generatedQuery=this.sheetToQuery( argumentCollection=args ); - if( format IS "query" ) - return generatedQuery; - var args={ - query=generatedQuery - }; - if( arguments.KeyExists( "headerRow" ) ){ - args.headerRow=headerRow; - args.includeHeaderRow = includeHeaderRow; - } - switch( format ){ - case "csv": return this.queryToCsv( argumentCollection=args ); - case "html": return this.queryToHtml( argumentCollection=args ); - } - } - - binary function readBinary( required workbook ){ - var baos = CreateObject( "Java","org.apache.commons.io.output.ByteArrayOutputStream" ).init(); - workbook.write( baos ); - baos.flush(); - return baos.toByteArray(); - } - - void function removeSheet( required workbook,required string sheetName ){ - validateSheetName( sheetName ); - validateSheetExistsWithName( workbook,sheetName ); - arguments.sheetNumber = workbook.getSheetIndex( sheetName )+1; - var sheetIndex = sheetNumber-1; - this.deleteSheetAtIndex( workbook,sheetIndex ); - } - - void function removeSheetNumber( required workbook,required numeric sheetNumber ){ - validateSheetNumber( workbook,sheetNumber ); - var sheetIndex = sheetNumber-1; - this.deleteSheetAtIndex( workbook,sheetIndex ); - } - - void function renameSheet( required workbook,required string sheetName,required numeric sheetNumber ){ - this.validateSheetName( sheetName ); - this.validateSheetNumber( workbook,sheetNumber ); - var sheetIndex = sheetNumber-1; - var foundAt = workbook.getSheetIndex( JavaCast( "string",sheetName ) ); - if( ( foundAt GT 0 ) AND ( foundAt NEQ sheetIndex ) ) - throw( type=exceptionType,message="Invalid Sheet Name [#sheetName#]",detail="The workbook already contains a sheet named [#sheetName#]. Sheet names must be unique" ); - workbook.setSheetName( JavaCast( "int",sheetIndex ),JavaCast( "string",sheetName ) ); - } - - void function setActiveSheet( required workbook,string sheetName,numeric sheetNumber ){ - this.validateSheetNameOrNumberWasProvided( argumentCollection=arguments ); - if( arguments.KeyExists( "sheetName" ) ){ - this.validateSheetExistsWithName( workbook,sheetName ); - sheetNumber = workbook.getSheetIndex( JavaCast( "string",sheetName ) ) + 1; - } - this.validateSheetNumber( workbook,sheetNumber ) - workbook.setActiveSheet( JavaCast( "int",sheetNumber - 1 ) ); - } - - void function setActiveSheetNumber( required workbook,numeric sheetNumber ){ - this.setActiveSheet( argumentCollection=arguments ); - } - - void function setCellComment( - required workbook - ,required struct comment - ,required numeric row - ,required numeric column - ){ - /* - The comment struct may contain the following keys: - * anchor - * author - * bold - * color - * comment - * fillcolor - * font - * horizontalalignment - * italic - * linestyle - * linestylecolor - * size - * strikeout - * underline - * verticalalignment - * visible - */ - var drawingPatriarch = this.getActiveSheet( workbook ).createDrawingPatriarch(); - var commentString = this.loadPoi( "org.apache.poi.hssf.usermodel.HSSFRichTextString" ).init( JavaCast( "string",comment.comment ) ); - var javaColorRGB = 0; - if( comment.KeyExists( "anchor" ) ) - var clientAnchor = loadPoi( "org.apache.poi.hssf.usermodel.HSSFClientAnchor" ).init( - JavaCast( "int",0 ) - ,JavaCast( "int",0 ) - ,JavaCast( "int",0 ) - ,JavaCast( "int",0 ) - ,JavaCast( "int",ListGetAt( comment.anchor,1 ) ) - ,JavaCast( "int",ListGetAt( comment.anchor,2 ) ) - ,JavaCast( "int",ListGetAt( comment.anchor,3 ) ) - ,JavaCast( "int",ListGetAt( comment.anchor,4 ) ) - ); - else - var clientAnchor = loadPoi( "org.apache.poi.hssf.usermodel.HSSFClientAnchor" ).init( - JavaCast( "int",0 ) - ,JavaCast( "int",0 ) - ,JavaCast( "int",0 ) - ,JavaCast( "int",0 ) - ,JavaCast( "int",column ) - ,JavaCast( "int",row ) - ,JavaCast( "int",column+2 ) - ,JavaCast( "int",row+2 ) - ); - var commentObject = drawingPatriarch.createComment( clientAnchor ); - if( comment.KeyExists( "author" ) ) - commentObject.setAuthor( JavaCast( "string",comment.author ) ); - /* If we're going to do anything font related, need to create a font. Didn't really want to create it above since it might not be needed. */ - if( comment.KeyExists( "bold" ) - OR comment.KeyExists( "color" ) - OR comment.KeyExists( "font" ) - OR comment.KeyExists( "italic" ) - OR comment.KeyExists( "size" ) - OR comment.KeyExists( "strikeout" ) - OR comment.KeyExists( "underline" ) - ){ - var font = workbook.createFont(); - if( comment.KeyExists( "bold" ) ){ - if( comment.bold ) - font.setBoldWeight( font.BOLDWEIGHT_BOLD ); - else - font.setBoldWeight( font.BOLDWEIGHT_NORMAL ); - } - if( comment.KeyExists( "color" ) ) - font.setColor( JavaCast( "int",getColorIndex( comment.color ) ) ); - if( comment.KeyExists( "font" ) ) - font.setFontName( JavaCast( "string",comment.font ) ); - if( comment.KeyExists( "italic" ) ) - font.setItalic( JavaCast( "string",comment.italic ) ); - if( comment.KeyExists( "size" ) ) - font.setFontHeightInPoints( JavaCast( "int",comment.size ) ); - if( comment.KeyExists( "strikeout" ) ) - font.setStrikeout( JavaCast( "boolean",comment.strikeout ) ); - if( comment.KeyExists( "underline" ) ) - font.setUnderline( JavaCast( "boolean",comment.underline ) ); - commentString.applyFont( font ); - } - if( comment.KeyExists( "fillColor" ) ){ - javaColorRGB = this.getJavaColorRGB( comment.fillColor ); - commentObject.setFillColor( - JavaCast( "int",javaColorRGB.red ) - ,JavaCast( "int",javaColorRGB.green ) - ,JavaCast( "int",javaColorRGB.blue ) - ); - } - /* - Horizontal alignment can be left, center, right, justify, or distributed. Note that the constants on the Java class are slightly different in some cases: - 'center' = CENTERED - 'justify' = JUSTIFIED - */ - if( comment.KeyExists( "horizontalAlignment" ) ){ - if( comment.horizontalAlignment.UCase() IS "CENTER" ) - comment.horizontalAlignment = "CENTERED"; - if( comment.horizontalAlignment.UCase() IS "JUSTIFY" ) - comment.horizontalAlignment = "JUSTIFIED"; - commentObject.setHorizontalAlignment( JavaCast( "int",commentObject[ "HORIZONTAL_ALIGNMENT_" & comment.horizontalalignment.UCase() ] ) ); - } - /* - Valid values for linestyle are: - * solid - * dashsys - * dashdotsys - * dashdotdotsys - * dotgel - * dashgel - * longdashgel - * dashdotgel - * longdashdotgel - * longdashdotdotgel - */ - if( comment.KeyExists( "lineStyle" ) ) - commentObject.setLineStyle( JavaCast( "int",commentObject[ "LINESTYLE_" & comment.lineStyle.UCase() ] ) ); - if( comment.KeyExists( "lineStyleColor" ) ){ - javaColorRGB = this.getJavaColorRGB( comment.lineStyleColor ); - commentObject.setLineStyleColor( - JavaCast( "int",javaColorRGB.red ) - ,JavaCast( "int",javaColorRGB.green ) - ,JavaCast( "int",javaColorRGB.blue ) - ); - } - /* Vertical alignment can be top, center, bottom, justify, and distributed. Note that center and justify are DIFFERENT than the constants for horizontal alignment, which are CENTERED and JUSTIFIED. */ - if( comment.KeyExists( "verticalAlignment" ) ) - commentObject.setVerticalAlignment( JavaCast( "int",commentObject[ "VERTICAL_ALIGNMENT_" & comment.verticalAlignment.UCase() ] ) ); - if( comment.KeyExists( "visible" ) ) - commentObject.setVisible( JavaCast( "boolean",comment.visible ) );//doesn't seem to work - commentObject.setString( commentString ); - var cell = this.initializeCell( workbook,row,column ); - cell.setCellComment( commentObject ); - } - - void function setCellFormula( required workbook,required string formula,required numeric row,required numeric column ){ - //Automatically create the cell if it does not exist, instead of throwing an error - var cell = initializeCell( workbook,row,column ); - cell.setCellFormula( JavaCast( "string",formula ) ); - } - - void function setCellValue( required workbook,required value,required numeric row,required numeric column ){ - //Automatically create the cell if it does not exist, instead of throwing an error - var cell = initializeCell( workbook,row,column ); - this.setCellValueAsType( workbook,cell,value ); - } - - void function setCellRangeValue( - required workbook - ,required value - ,required numeric startRow - ,required numeric endRow - ,required numeric startColumn - ,required numeric endColumn - ){ - /* Sets the same value to a range of cells */ - for( var rowNumber=startRow; rowNumber LTE endRow; rowNumber++ ){ - for( var columnNumber=startColumn; columnNumber LTE endColumn; columnNumber++ ){ - setCellValue( workbook,value,rowNumber,columnNumber ); - } - } - } - - void function setColumnWidth( required workbook,required numeric column,required numeric width ){ - var columnIndex = column-1; - this.getActiveSheet( workbook ).setColumnWidth( JavaCast( "int",columnIndex ),JavaCast( "int",width*256 ) ); - } - - void function setFooter( - required workbook - ,string leftFooter="" - ,string centerFooter="" - ,string rightFooter="" - ){ - if( !centerFooter.isEmpty() ) - this.getActiveSheet( workbook ).getFooter().setCenter( JavaCast( "string",centerFooter ) ); - if( !leftFooter.isEmpty() ) - this.getActiveSheet( workbook ).getFooter().setleft( JavaCast( "string",leftFooter ) ); - if( !rightFooter.isEmpty() ) - this.getActiveSheet( workbook ).getFooter().setright( JavaCast( "string",rightFooter ) ); - } - - void function setHeader( - required workbook - ,string leftHeader="" - ,string centerHeader="" - ,string rightHeader="" - ){ - if( !centerHeader.isEmpty() ) - this.getActiveSheet( workbook ).getHeader().setCenter( JavaCast( "string",centerHeader ) ); - if( !leftHeader.isEmpty() ) - this.getActiveSheet( workbook ).getHeader().setleft( JavaCast( "string",leftHeader ) ); - if( !rightHeader.isEmpty() ) - this.getActiveSheet( workbook ).getHeader().setright( JavaCast( "string",rightHeader ) ); - } - - void function setRowHeight( required workbook,required numeric row,required numeric height ){ - var rowIndex = row-1; - this.getActiveSheet( workbook ).getRow( JavaCast( "int",rowIndex ) ).setHeightInPoints( JavaCast( "int",height ) ); - } - - void function shiftColumns( required workbook,required numeric start,numeric end=start,numeric offset=1 ){ - if( start LTE 0 ) - throw( type=exceptionType,message="Invalid start value",detail="The start value must be greater than or equal to 1" ); - if( arguments.KeyExists( "end" ) AND ( end LTE 0 OR end LT start ) ) - throw( type=exceptionType,message="Invalid end value",detail="The end value must be greater than or equal to the start value" ); - var rowIterator = this.getActiveSheet( workbook ).rowIterator(); - var startIndex = start-1; - var endIndex = arguments.KeyExists( "end" )? end-1: startIndex; - while( rowIterator.hasNext() ){ - var row = rowIterator.next(); - if( offset GT 0 ){ - for( var i=endIndex; i GTE startIndex; i-- ){ - var tempCell = row.getCell( JavaCast( "int",i ) ); - var cell = this.createCell( row,i+offset ); - if( !IsNull( tempCell ) ){ - this.setCellValueAsType( workbook,cell,this.getCellValueAsType( workbook,tempCell ) ); - cell.setCellStyle( tempCell.getCellStyle() ); - } - } - } else { - for( var i=startIndex; i LTE endIndex; i++ ){ - var tempCell = row.getCell( JavaCast( "int",i ) ); - var cell = createCell( row,i+offset ); - if( !IsNull( tempCell ) ){ - this.setCellValueAsType( workbook,cell,this.getCellValueAsType( workbook,tempCell ) ); - cell.setCellStyle( tempCell.getCellStyle() ); - } - } - } - } - // clean up any columns that need to be deleted after the shift - var numberColsShifted = ( endIndex-startIndex )+1; - var numberColsToDelete = Abs( offset ); - if( numberColsToDelete GT numberColsShifted ) - numberColsToDelete = numberColsShifted; - if( offset GT 0 ){ - var stopValue = ( startIndex + numberColsToDelete )-1; - for( var i=startIndex; i LTE stopValue; i++ ){ - this.deleteColumn( workbook,i+1 ); - } - return; - } - var stopValue = ( endIndex - numberColsToDelete )+1; - for( var i=endIndex; i GTE stopValue; i-- ){ - this.deleteColumn( workbook,i+1 ); - } - } - - void function shiftRows( required workbook,required numeric start,numeric end=start,numeric offset=1 ){ - this.getActiveSheet( workbook ).shiftRows( - JavaCast( "int",arguments.start - 1 ) - ,JavaCast( "int",arguments.end - 1 ) - ,JavaCast( "int",arguments.offset ) - ); - } - - void function write( required workbook,required string filepath,boolean overwrite=false,string password ){ - if( !overwrite AND FileExists( filepath ) ) - throw( type=exceptionType,message="File already exists",detail="The file path specified already exists. Use 'overwrite=true' if you wish to overwrite it." ); - // writeProtectWorkbook takes both a user name and a password, but since CF 9 tag only takes a password, just making up a user name - // TODO: workbook.isWriteProtected() returns true but the workbook opens without prompting for a password - if( arguments.KeyExists( "password" ) AND !password.Trim().IsEmpty() ) - workbook.writeProtectWorkbook( JavaCast( "string",password ),JavaCast( "string","user" ) ); - lock name="#filepath#" timeout=5{ - var outputStream = CreateObject( "java","java.io.FileOutputStream" ).init( filepath ); - } - try{ - lock name="#filepath#" timeout=5{ - workbook.write( outputStream ); - } - outputStream.flush(); - } - finally{ - // always close the stream. otherwise file may be left in a locked state if an unexpected error occurs - outputStream.close(); - } - } - -} \ No newline at end of file diff --git a/models/SpreadSheet/formatting.cfm b/models/SpreadSheet/formatting.cfm deleted file mode 100644 index c710109..0000000 --- a/models/SpreadSheet/formatting.cfm +++ /dev/null @@ -1,181 +0,0 @@ - -private any function buildCellStyle( required workbook,required struct format ){ - /* TODO: Reuse styles */ - var cellStyle = workbook.createCellStyle(); - var formatter = workbook.getCreationHelper().createDataFormat(); - var font = 0; - var setting = 0; - var settingValue = 0; - var formatIndex = 0; - /* - Valid values of the format struct are: - * alignment - * bold - * bottomborder - * bottombordercolor - * color - * dataformat - * fgcolor - * fillpattern - * font - * fontsize - * hidden - * indent - * italic - * leftborder - * leftbordercolor - * locked - * rightborder - * rightbordercolor - * rotation - * strikeout - * textwrap - * topborder - * topbordercolor - * underline - * verticalalignment (added in CF9.0.1) - */ - for( var setting in format ){ - settingValue = UCase( format[ setting ] ); - switch( setting ){ - case "alignment": - cellStyle.setAlignment( cellStyle[ "ALIGN_" & settingValue ] ); - break; - case "bold": - font = cloneFont( workbook,workbook.getFontAt( cellStyle.getFontIndex() ) ); - if( format.KeyExists( setting ) ) - font.setBoldweight( font.BOLDWEIGHT_BOLD ); - else - font.setBoldweight( font.BOLDWEIGHT_NORMAL ) - cellStyle.setFont( font ); - break; - case "bottomborder": - cellStyle.setBorderBottom( Evaluate( "cellStyle." & "BORDER_" & UCase( StructFind( format,setting ) ) ) ); - break; - case "bottombordercolor": - cellStyle.setBottomBorderColor( JavaCast( "int",getColorIndex( StructFind( format,setting ) ) ) ); - break; - case "color": - font = cloneFont( workbook,workbook.getFontAt( cellStyle.getFontIndex() ) ); - font.setColor( getColorIndex( StructFind( format,setting ) ) ); - cellStyle.setFont( font ); - break; - /* TODO: this is returning the correct data format index from HSSFDataFormat but doesn't seem to have any effect on the cell. Could be that I'm testing with OpenOffice so I'll have to check things in MS Excel */ - case "dataformat": - cellStyle.setDataFormat( formatter.getFormat( JavaCast( "string",format[ setting ] ) ) ); - break; - case "fgcolor": - cellStyle.setFillForegroundColor( getColorIndex( StructFind( format,setting ) ) ); - /* make sure we always apply a fill pattern or the color will not be visible */ - if( !arguments.KeyExists( "fillpattern" ) ) - cellStyle.setFillPattern( cellStyle.SOLID_FOREGROUND ); - break; - /* TODO: CF 9 docs list "nofill" as opposed to "no_fill"; docs wrong? The rest match POI settings exactly.If it really is nofill instead of no_fill, just change to no_fill before calling setFillPattern */ - case "fillpattern": - cellStyle.setFillPattern( Evaluate( "cellStyle." & UCase( StructFind( format,setting ) ) ) ); - break; - case "font": - font = cloneFont( workbook,workbook.getFontAt( cellStyle.getFontIndex() ) ); - font.setFontName( JavaCast( "string",StructFind( format,setting ) ) ); - cellStyle.setFont( font ); - break; - case "fontsize": - font = cloneFont( workbook,workbook.getFontAt( cellStyle.getFontIndex() ) ); - font.setFontHeightInPoints( JavaCast( "int",StructFind( format,setting ) ) ); - cellStyle.setFont( font ); - break; - /* TODO: I may just not understand what's supposed to be happening here, but this doesn't seem to do anything */ - case "hidden": - cellStyle.setHidden( JavaCast( "boolean",StructFind( format, setting ) ) ); - break; - /* TODO: I may just not understand what's supposed to be happening here, but this doesn't seem to do anything */ - case "indent": - cellStyle.setIndention( JavaCast( "int",StructFind( format, setting ) ) ); - break; - case "italic": - font = cloneFont( workbook,workbook.getFontAt( cellStyle.getFontIndex ( ) ) ); - if( StructFind( format,setting ) ) - font.setItalic( JavaCast( "boolean",true ) ); - else - font.setItalic( JavaCast( "boolean",false ) ); - cellStyle.setFont( font ); - break; - case "leftborder": - cellStyle.setBorderLeft( Evaluate("cellStyle." & "BORDER_" & UCase( StructFind( format,setting ) ) ) ); - break; - case "leftbordercolor": - cellStyle.setLeftBorderColor( getColorIndex( StructFind( format,setting ) ) ); - break; - /* TODO: I may just not understand what's supposed to be happening here, but this doesn't seem to do anything */ - case "locked": - cellStyle.setLocked( JavaCast( "boolean",StructFind( format,setting ) ) ); - break; - case "rightborder": - cellStyle.setBorderRight( Evaluate("cellStyle." & "BORDER_" & UCase( StructFind( format,setting ) ) ) ); - break; - case "rightbordercolor": - cellStyle.setRightBorderColor( getColorIndex( StructFind( format,setting ) ) ); - break; - case "rotation": - cellStyle.setRotation( JavaCast( "int",StructFind( format,setting ) ) ); - break; - case "strikeout": - font = cloneFont( workbook,workbook.getFontAt( cellStyle.getFontIndex() ) ); - if( StructFind( format,setting ) ) - font.setStrikeout( JavaCast( "boolean",true ) ); - else - font.setStrikeout( JavaCast( "boolean",false ) ); - cellStyle.setFont( font ); - break; - case "textwrap": - cellStyle.setWrapText( JavaCast( "boolean",StructFind( format,setting ) ) ); - break; - case "topborder": - cellStyle.setBorderTop( Evaluate( "cellStyle." & "BORDER_" & UCase( StructFind( format,setting ) ) ) ); - break; - case "topbordercolor": - cellStyle.setTopBorderColor( getColorIndex( StructFind( format,setting ) ) ); - break; - case "underline": - font = cloneFont( workbook,workbook.getFontAt( cellStyle.getFontIndex() ) ); - if( StructFind( format,setting ) ) - font.setUnderline( JavaCast( "boolean",true ) ); - else - font.setUnderline( JavaCast( "boolean",false ) ); - cellStyle.setFont( font ); - break; - case "verticalalignment": - cellStyle.setVerticalAlignment( cellStyle[ settingValue ] ); - break; - } - } - return cellStyle; -} - -private any function cloneFont( required workbook,required fontToClone ){ - var newFont = workbook.createFont(); - /* copy the existing cell's font settings to the new font */ - newFont.setBoldweight( fontToClone.getBoldweight() ); - newFont.setCharSet( fontToClone.getCharSet() ); - newFont.setColor( fontToClone.getColor() ); - newFont.setFontHeight( fontToClone.getFontHeight() ); - newFont.setFontName( fontToClone.getFontName() ); - newFont.setItalic( fontToClone.getItalic() ); - newFont.setStrikeout( fontToClone.getStrikeout() ); - newFont.setTypeOffset( fontToClone.getTypeOffset() ); - newFont.setUnderline( fontToClone.getUnderline() ); - return newFont; -} - -private numeric function getColorIndex( required string colorName ){ - try{ - var findColor = colorName.Trim().UCase(); - var IndexedColors = CreateObject( "Java","org.apache.poi.ss.usermodel.IndexedColors" ); - var color = IndexedColors.valueOf( JavaCast( "string",findColor ) ); - return color.getIndex(); - } - catch( any exception ){ - throw( type=exceptionType,message="Invalid Color",detail="The color provided (#colorName#) is not valid." ); - } -} - \ No newline at end of file diff --git a/models/SpreadSheet/lib/poi-3.12-20150511.jar b/models/SpreadSheet/lib/poi-3.12-20150511.jar deleted file mode 100644 index a4f4263..0000000 Binary files a/models/SpreadSheet/lib/poi-3.12-20150511.jar and /dev/null differ diff --git a/models/SpreadSheet/lib/poi-ooxml-3.12-20150511.jar b/models/SpreadSheet/lib/poi-ooxml-3.12-20150511.jar deleted file mode 100644 index a7222d4..0000000 Binary files a/models/SpreadSheet/lib/poi-ooxml-3.12-20150511.jar and /dev/null differ diff --git a/models/SpreadSheet/lib/poi-ooxml-schemas-3.12-20150511.jar b/models/SpreadSheet/lib/poi-ooxml-schemas-3.12-20150511.jar deleted file mode 100644 index 5fcc65a..0000000 Binary files a/models/SpreadSheet/lib/poi-ooxml-schemas-3.12-20150511.jar and /dev/null differ diff --git a/models/SpreadSheet/lib/xmlbeans-2.6.0.jar b/models/SpreadSheet/lib/xmlbeans-2.6.0.jar deleted file mode 100644 index d1b6627..0000000 Binary files a/models/SpreadSheet/lib/xmlbeans-2.6.0.jar and /dev/null differ diff --git a/models/SpreadSheet/tools.cfm b/models/SpreadSheet/tools.cfm deleted file mode 100644 index 3662664..0000000 --- a/models/SpreadSheet/tools.cfm +++ /dev/null @@ -1,783 +0,0 @@ - -private void function addInfoBinary( required workbook,required struct info ){ - workbook.createInformationProperties(); // creates the following if missing - var documentSummaryInfo = workbook.getDocumentSummaryInformation(); - var summaryInfo = workbook.getSummaryInformation(); - for( var key in info ){ - var value = JavaCast( "string",info[ key ] ); - switch( key ){ - case "author": - summaryInfo.setAuthor( value ); - break; - case "category": - documentSummaryInfo.setCategory( value ); - break; - case "lastauthor": - summaryInfo.setLastAuthor( value ); - break; - case "comments": - summaryInfo.setComments( value ); - break; - case "keywords": - summaryInfo.setKeywords( value ); - break; - case "manager": - documentSummaryInfo.setManager( value ); - break; - case "company": - documentSummaryInfo.setCompany( value ); - break; - case "subject": - summaryInfo.setSubject( value ); - break; - case "title": - summaryInfo.setTitle( value ); - break; - } - } -} - -private void function addInfoXml( required workbook,required struct info ){ - var documentProperties = workbook.getProperties().getExtendedProperties().getUnderlyingProperties(); - var coreProperties = workbook.getProperties().getCoreProperties(); - for( var key in info ){ - var value = JavaCast( "string",info[ key ] ); - switch( key ){ - case "author": - coreProperties.setCreator( value ); - break; - case "category": - coreProperties.setCategory( value ); - break; - case "lastauthor": - coreProperties.getUnderlyingProperties().setLastModifiedByProperty( value ); - break; - case "comments": - coreProperties.setDescription( value ); - break; - case "keywords": - coreProperties.setKeywords( value ); - break; - case "subject": - coreProperties.setSubjectProperty( value ); - break; - case "title": - coreProperties.setTitle( value ); - break; - case "manager": - documentProperties.setManager( value ); - break; - case "company": - documentProperties.setCompany( value ); - break; - } - } -} - -private void function addRowToSheetData( required workbook,required struct sheet,required numeric rowIndex ){ - if( ( rowIndex EQ sheet.headerRowIndex ) AND !sheet.includeHeaderRow ) - return; - var rowData=[]; - var row=sheet.object.GetRow( JavaCast( "int",rowIndex ) ); - if( IsNull( row ) ){ - if( sheet.includeBlankRows ) - sheet.data.Append( rowData ); - return; - } - if( rowIsEmpty( row ) AND !sheet.includeBlankRows ) - return; - rowData=getRowData( workbook,row,sheet.columnRanges ); - sheet.data.Append( rowData ); - if( !sheet.columnRanges.Len() ){ - var rowColumnCount = row.GetLastCellNum(); - sheet.totalColumnCount = Max( sheet.totalColumnCount,rowColumnCount ); - } -} - -private struct function binaryInfo( required workbook ){ - var documentProperties = workbook.getDocumentSummaryInformation(); - var coreProperties = workbook.getSummaryInformation(); - return { - author = coreProperties.getAuthor()?:"" - ,category = documentProperties.getCategory()?:"" - ,comments = coreProperties.getComments()?:"" - ,creationDate = coreProperties.getCreateDateTime()?:"" - ,lastEdited = ( coreProperties.getEditTime() EQ 0 )? "": CreateObject( "java","java.util.Date" ).init( coreProperties.getEditTime() ) - ,subject = coreProperties.getSubject()?:"" - ,title = coreProperties.getTitle()?:"" - ,lastAuthor = coreProperties.getLastAuthor()?:"" - ,keywords = coreProperties.getKeywords()?:"" - ,lastSaved = coreProperties.getLastSaveDateTime()?:"" - ,manager = documentProperties.getManager()?:"" - ,company = documentProperties.getCompany()?:"" - }; -} - -private boolean function cellExists( required workbook,required numeric rowNumber,required numeric columnNumber ){ - var rowIndex = rowNumber-1; - var columnIndex = columnNumber-1; - var checkRow = this.getActiveSheet( workbook ).getRow( JavaCast( "int",rowIndex ) ); - return !IsNull( checkRow ) AND !IsNull( checkRow.getCell( JavaCast( "int",columnIndex ) ) ); -} - -private numeric function columnCountFromRanges( required array ranges ){ - var result=0; - for( var thisRange in ranges ){ - for( var i=thisRange.startAt; i LTE thisRange.endAt; i++ ){ - result++; - } - } - return result; -} - -private function createCell( required row,numeric cellNum=arguments.row.getLastCellNum(),overwrite=true ){ - /* get existing cell (if any) */ - var cell = row.getCell( JavaCast( "int",cellNum ) ); - if( overwrite AND !IsNull( cell ) ) - arguments.row.removeCell( cell );/* forcibly remove the existing cell */ - if( overwrite OR IsNull( cell ) ) - cell = row.createCell( JavaCast( "int",cellNum ) );/* create a brand new cell */ - return cell; -} - -private function createRow( required workbook,numeric rowNum=getNextEmptyRow( workbook ),boolean overwrite=true ){ - /* get existing row (if any) */ - var row = getActiveSheet( workbook ).getRow( JavaCast( "int",rowNum ) ); - if( overwrite AND !IsNull( row ) ) - getActiveSheet( workbook ).removeRow( row ) /* forcibly remove existing row and all cells */ - if( overwrite OR IsNull( getActiveSheet( workbook ).getRow( JavaCast( "int",rowNum ) ) ) ) - row = getActiveSheet( workbook ).createRow( JavaCast("int", rowNum ) ); - return row; -} - -private function createWorkBook( required string sheetName,boolean useXmlFormat=false ){ - this.validateSheetName( sheetName ); - var className = useXmlFormat? "org.apache.poi.xssf.usermodel.XSSFWorkbook": "org.apache.poi.hssf.usermodel.HSSFWorkbook"; - return loadPoi( className ).init(); -} - -private void function deleteSheetAtIndex( required workbook,required numeric sheetIndex ){ - workbook.removeSheetAt( JavaCast( "int",sheetIndex ) ); -} - -private numeric function estimateColumnWidth( required workbook,required any value ){ - /* Estimates approximate column width based on cell value and default character width. */ - /* - "Excel bases its measurement of column widths on the number of digits (specifically, the number of zeros) in the column, using the Normal style font." - This function approximates the column width using the number of characters and the default character width in the normal font. POI expresses the width in 1/256 of Excel's character unit. The maximum size in POI is: (255 * 256) - */ - var defaultWidth = getDefaultCharWidth( workbook ); - var numOfChars = Len( arguments.value ); - var width = ( numOfChars*defaultWidth+5 ) / ( defaultWidth*256 ); - // Do not allow the size to exceed POI's maximum - return Min( width,( 255*256 ) ); -} - -private array function extractRanges( required string rangeList ){ - /* - A range is a comma-delimited list of ranges, and each value can be either a single number or a range of numbers with a hyphen. Ignores any white space. - Parses and validates a list of row/column numbers. Returns an array of structures with the keys: startAt, endAt - */ - var result = []; - var rangeTest = "^[0-9]{1,}(-[0-9]{1,})?$"; - var ranges = ListToArray( rangeList ); - for( var thisRange in ranges ){ - /* remove all white space */ - thisRange.REReplace( "\s+","","ALL" ); - if( !REFind( rangeTest,thisRange ) ) - throw( type=exceptionType,message="Invalid range value",detail="The range value '#thisRange#' is not valid." ); - var parts = ListToArray( thisRange,"-" ); - //if this is a single number, the start/endAt values are the same - var range = { - startAt = parts[ 1 ] - ,endAt = parts[ parts.Len() ] - }; - result.Append( range ); - } - return result; -} - -private string function filenameSafe( required string input ){ - var charsToRemove = "\|\\\*\/\:""<>~&"; - var result = input.REReplace( "[#charsToRemove#]+","","ALL" ).Left( 255 ); - if( result.isEmpty() ) - return "renamed"; // in case all chars have been replaced (unlikely but possible) - return result; -} - -private void function fillMergedCellsWithVisibleValue( required workbook,required sheet ){ - if( !sheetHasMergedRegions( sheet ) ) - return; - for( var regionIndex=0; regionIndex LT sheet.getNumMergedRegions(); regionIndex++ ){ - var region=sheet.getMergedRegion( regionIndex ); - var regionStartRowNumber=region.getFirstRow()+1; - var regionEndRowNumber=region.getLastRow()+1; - var regionStartColumnNumber=region.getFirstColumn()+1; - var regionEndColumnNumber=region.getLastColumn()+1; - var visibleValue=getCellValue( workbook,regionStartRowNumber,regionStartColumnNumber ); - setCellRangeValue( workbook,visibleValue,regionStartRowNumber,regionEndRowNumber,regionStartColumnNumber,regionEndColumnNumber ); - } -} - -private string function generateUniqueSheetName( required workbook ){ - /* Generates a unique sheet name (Sheet1, Sheet2, etecetera). */ - var startNumber = workbook.getNumberOfSheets()+1; - var maxRetry = startNumber+250; - for( var sheetNumber=startNumber; sheetNumber LTE maxRetry; sheetNumber++ ){ - var proposedName = "Sheet" & sheetNumber; - if( !sheetExists( workbook,proposedName ) ) - return proposedName; - } - /* this should never happen. but if for some reason it did, warn the action failed and abort */ - throw( type=exceptionType,message="Unable to generate name",detail="Unable to generate a unique sheet name" ); -} - -private function getActiveSheet( required workbook ){ - return workbook.getSheetAt( JavaCast( "int",workbook.getActiveSheetIndex() ) ); -} - -private function getActiveSheetName( required workbook ){ - return this.getActiveSheet( workbook ).getSheetName(); -} - -private numeric function getAWTFontStyle( required any poiFont ){ - var font = loadPOI( "java.awt.Font" ); - var isBold = poiFont.getBoldweight() == poiFont.BOLDWEIGHT_BOLD; - if( isBold && arguments.poiFont.getItalic() ) - return BitOr( font.BOLD,font.ITALIC ); - if( isBold ) - return font.BOLD; - if( poiFont.getItalic() ) - return font.ITALIC; - return font.PLAIN; -} - -private function getCellAt( required workbook,required numeric rowNumber,required numeric columnNumber ){ - if( !cellExists( argumentCollection=arguments ) ) - throw( type=exceptionType,message="Invalid cell",detail="The requested cell [#rowNumber#,#columnNumber#] does not exist in the active sheet" ); - var rowIndex = rowNumber-1; - var columnIndex = columnNumber-1; - return getActiveSheet( workbook ).getRow( JavaCast( "int",rowIndex ) ).getCell( JavaCast( "int",columnIndex ) ); -} - -private function getCellUtil(){ - if( IsNull( variables.cellUtil ) ) - variables.cellUtil = loadPoi( "org.apache.poi.ss.util.CellUtil" ); - return variables.cellUtil; -} - -private function getCellValueAsType( required workbook,required cell ){ - /* When getting the value of a cell, it is important to know what type of cell value we are dealing with. If you try to grab the wrong value type, an error might be thrown. For that reason, we must check to see what type of cell we are working with. These are the cell types and they are constants of the cell object itself: - - 0 - CELL_TYPE_NUMERIC - 1 - CELL_TYPE_STRING - 2 - CELL_TYPE_FORMULA - 3 - CELL_TYPE_BLANK - 4 - CELL_TYPE_BOOLEAN - 5 - CELL_TYPE_ERROR */ - - var cellType = cell.GetCellType(); - /* Get the value of the cell based on the data type. The thing to worry about here is cell forumlas and cell dates. Formulas can be strange and dates are stored as numeric types. Here I will just grab dates as floats and formulas I will try to grab as numeric values. */ - if( cellType EQ cell.CELL_TYPE_NUMERIC ){ - /* Get numeric cell data. This could be a standard number, could also be a date value. */ - var dateUtil = this.getDateUtil(); - if( dateUtil.isCellDateFormatted( cell ) ) - return cell.getDateCellValue(); - return cell.getNumericCellValue(); - } - if( cellType EQ cell.CELL_TYPE_FORMULA ){ - var formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); - return this.getFormatter().formatCellValue( cell,formulaEvaluator ); - } - if( cellType EQ cell.CELL_TYPE_BOOLEAN ) - return cell.getBooleanCellValue(); - if( cellType EQ cell.CELL_TYPE_BLANK ) - return ""; - try{ - return cell.getStringCellValue(); - } - catch( any exception ){ - return ""; - } -} - -private function getDateUtil(){ - if( IsNull( variables.dateUtil ) ) - variables.dateUtil = loadPoi( "org.apache.poi.ss.usermodel.DateUtil" ); - return variables.dateUtil; -} - -private string function getDateTimeValueFormat( required any value ){ - /* Returns the default date mask for the given value: DATE (only), TIME (only) or TIMESTAMP */ - var dateTime = ParseDateTime( value ); - var dateOnly = CreateDate( Year( dateTime ),Month( dateTime ),Day( dateTime ) ); - if( DateCompare( value,dateOnly,"s" ) EQ 0 ) - return variables.dateFormats.DATE; - if( DateCompare( "1899-12-30",dateOnly,"d" ) EQ 0 ) - return variables.dateFormats.TIME; - return variables.dateFormats.TIMESTAMP; -} - -private numeric function getDefaultCharWidth( required workbook ){ - /* Estimates the default character width using Excel's 'Normal' font */ - /* this is a compromise between hard coding a default value and the more complex method of using an AttributedString and TextLayout */ - var defaultFont = workbook.getFontAt( 0 ); - var style = getAWTFontStyle( defaultFont ); - var font = loadPOI( "java.awt.Font" ); - var javaFont = font.init( defaultFont.getFontName(),style,defaultFont.getFontHeightInPoints() ); - // this works - var transform = CreateObject( "java","java.awt.geom.AffineTransform" ); - var fontContext = CreateObject( "java","java.awt.font.FontRenderContext" ).init( transform,true,true ); - var bounds = javaFont.getStringBounds( "0",fontContext ); - return bounds.getWidth(); -} - -private numeric function getFirstRowNum( required workbook ){ - var firstRow = getActiveSheet( workbook ).getFirstRowNum(); - if( firstRow EQ 0 AND getActiveSheet( workbook ).getPhysicalNumberOfRows() EQ 0 ) - return -1; - return firstRow; -} - -private function getFormatter(){ - /* Returns cell formatting utility object ie org.apache.poi.ss.usermodel.DataFormatter */ - if( IsNull( variables.dataFormatter ) ) - variables.dataFormatter = this.loadPOI( "org.apache.poi.ss.usermodel.DataFormatter" ).init(); - return dataFormatter; -} - -private struct function getJavaColorRGB( required string colorName ){ - /* Returns a struct containing RGB values from java.awt.Color for the color name passed in */ - var findColor = colorName.Trim().UCase(); - var color = CreateObject( "Java","java.awt.Color" ); - if( IsNull( color[ findColor ] ) OR !IsInstanceOf( color[ findColor ],"java.awt.Color" ) )//don't use member functions on color - throw( type=exceptionType,message="Invalid color",detail="The color provided (#colorName#) is not valid." ); - color = color[ findColor ]; - var colorRGB = { - red = color.getRed() - ,green = color.getGreen() - ,blue = color.getBlue() - }; - return colorRGB; -} - -private numeric function getLastRowNum( required workbook ){ - var lastRow = getActiveSheet( workbook ).getLastRowNum(); - if( lastRow EQ 0 AND getActiveSheet( workbook ).getPhysicalNumberOfRows() EQ 0 ) - return -1;//The sheet is empty. Return -1 instead of 0 - return lastRow; -} - -private numeric function getNextEmptyRow( workbook ){ - return getLastRowNum( workbook )+1; -} - -private array function getQueryColumnFormats( required workbook,required query query ){ - /* extract the query columns and data types */ - //var cell = CreateObject( "Java","org.apache.poi.ss.usermodel.Cell" ); - var formatter = workbook.getCreationHelper().createDataFormat(); - var metadata = GetMetaData( query ); - /* assign default formats based on the data type of each column */ - for( var col in metadata ){ - switch( col.typeName ){ - /* apply basic formatting to dates and times for increased readability */ - case "DATE": case "TIMESTAMP": - col.cellDataType = "DATE"; - col.defaultCellStyle = this.buildCellStyle( workbook,{ dataFormat = variables.dateFormats[ col.typeName ] } ); - break; - case "TIME": - col.cellDataType = "TIME"; - col.defaultCellStyle = this.buildCellStyle( workbook,{ dataFormat = variables.dateFormats[ col.typeName ] } ); - break; - /* Note: Excel only supports "double" for numbers. Casting very large DECIMIAL/NUMERIC or BIGINT values to double may result in a loss of precision or conversion to NEGATIVE_INFINITY / POSITIVE_INFINITY. */ - case "DECIMAL": case "BIGINT": case "NUMERIC": case "DOUBLE": case "FLOAT": case "INTEGER": case "REAL": case "SMALLINT": case "TINYINT": - col.cellDataType = "DOUBLE"; - break; - case "BOOLEAN": case "BIT": - col.cellDataType = "BOOLEAN"; - break; - default: - col.cellDataType = "STRING"; - } - } - return metadata; -} - -private array function getRowData( required workbook,required row,array columnRanges=[] ){ - var result=[]; - if( !columnRanges.Len() ){ - var columnRange={ - startAt=1 - ,endAt=row.GetLastCellNum() - }; - arguments.columnRanges=[ columnRange ]; - } - for( var thisRange in columnRanges ){ - for( var i=thisRange.startAt; i LTE thisRange.endAt; i++ ){ - var colIndex=i-1; - var cell = row.GetCell( JavaCast( "int",colIndex ) ); - if( IsNull( cell ) ){ - result.Append( "" ); - continue; - } - var cellValue = this.getCellValueAsType( workbook,cell ); - result.Append( cellValue ); - } - } - return result; -} - -private numeric function getSheetIndexFromName( required workbook,required string sheetName ){ - //returns -1 if non-existent - return workbook.getSheetIndex( JavaCast( "string",sheetName ) ); -} - -private function initializeCell( required workbook,required numeric rowNumber,required numeric columnNumber ){ - var rowIndex = JavaCast( "int",rowNumber-1 ); - var columnIndex = JavaCast( "int",columnNumber-1 ); - var rowObject = getCellUtil().getRow( rowIndex,getActiveSheet( workbook ) ); - var cellObject = getCellUtil().getCell( rowObject,columnIndex ); - return cellObject; -} - -private boolean function isDateObject( required input ){ - return input.getClass().getName() IS "java.util.Date"; -} - -private boolean function isString( required input ){ - return input.getClass().getName() IS "java.lang.String"; -} - -private function loadPoi( required string javaclass ){ - if( !server.KeyExists( poiLoaderName ) ){ - var paths = []; - var libPath = ExpandPath( GetDirectoryFromPath( GetCurrentTemplatePath() ) & "lib/" ); - paths.Append( libPath & "poi-3.12-20150511.jar" ); - paths.Append( libPath & "poi-ooxml-3.12-20150511.jar" ); - paths.Append( libPath & "poi-ooxml-schemas-3.12-20150511.jar" ); - paths.Append( libPath & "xmlbeans-2.6.0.jar" ); - if( !server.KeyExists( poiLoaderName ) ){ - server[ poiLoaderName ] = CreateObject( "component","models.javaLoader.JavaLoader" ).init( loadPaths=paths,loadColdFusionClassPath=true,trustedSource=true ); - } - } - return server[ poiLoaderName ].create( arguments.javaclass ); -} - -private void function moveSheet( required workbook,required string sheetName,required string moveToIndex ){ - workbook.setSheetOrder( JavaCast( "String",sheetName ),JavaCast( "int",moveToIndex ) ); -} - -private array function parseRowData( required string line,required string delimiter,boolean handleEmbeddedCommas=true ){ - var elements = ListToArray( arguments.line,arguments.delimiter ); - var potentialQuotes = 0; - arguments.line = ToString( arguments.line ); - if( arguments.delimiter EQ "," AND arguments.handleEmbeddedCommas ) - potentialQuotes = arguments.line.replaceAll("[^']", "").length(); - if (potentialQuotes <= 1) - return elements; - //For ACF compatibility, find any values enclosed in single quotes and treat them as a single element. - var currentValue = 0; - var nextValue = ""; - var isEmbeddedValue = false; - var values = []; - var buffer = CreateObject( "Java","java.lang.StringBuilder" ).init(); - var maxElements = ArrayLen( elements ); - - for( var i=1; i LTE maxElements; i++) { - currentValue = Trim( elements[ i ] ); - nextValue = i < maxElements ? elements[ i + 1 ] : ""; - var isComplete = false; - var hasLeadingQuote = currentValue.hasPrefix( "'" ); - var hasTrailingQuote = currentValue.hasSuffix( "'" ); - var isFinalElement = ( i==maxElements ); - if( hasLeadingQuote ) - isEmbeddedValue = true; - if( isEmbeddedValue AND hasTrailingQuote ) - isComplete = true; - /* We are finished with this value if: - * no quotes were found OR - * it is the final value OR - * the next value is embedded in quotes - */ - if( !isEmbeddedValue || isFinalElement || nextValue.hasPrefix( "'" ) ) - isComplete = true; - if( isEmbeddedValue || isComplete ){ - // if this a partial value, append the delimiter - if( isEmbeddedValue AND buffer.length() GT 0 ) - buffer.append( "," ); - buffer.append( elements[i] ); - } - if( isComplete ){ - var finalValue = buffer.toString(); - var startAt = finalValue.indexOf( "'" ); - var endAt = finalValue.lastIndexOf( "'" ); - if( isEmbeddedValue AND startAt GTE 0 AND endAt GT startAt ) - finalValue = finalValue.substring( startAt+1,endAt ); - values.add( finalValue ); - buffer.setLength( 0 ); - isEmbeddedValue = false; - } - } - return values; -} - -private string function queryToCsv( required query query,numeric headerRow,boolean includeHeaderRow ){ - var result=[]; - var crlf=Chr( 13 ) & Chr( 10 ); - var columns=query.ColumnArray(); - var hasHeaderRow=( arguments.KeyExists( "headerRow" ) AND Val( headerRow ) ); - if( hasHeaderRow ) - result.Append( generateCsvRow( columns ) ); - for( var row in query ){ - var rowValues=[]; - for( column in columns ){ - rowValues.Append( row[ column ] ); - } - result.Append( generateCsvRow( rowValues ) ); - } - return result.ToList( crlf ); -} - -private string function generateCsvRow( required array values,delimiter="," ){ - var result=[]; - for( var value in values ){ - if( this.isDateObject( value ) ){ - value= DateTimeFormat( value,dateFormats.DATETIME ); - } - value=Replace( value,'"','""',"ALL" );//can't use member function in case its a non-string - result.Append( '"#value#"' ); - } - return result.ToList( delimiter ); -} - -private string function queryToHtml( required query query,numeric headerRow,boolean includeHeaderRow ){ - var result=[]; - var columns=query.ColumnArray(); - var hasHeaderRow=( arguments.KeyExists( "headerRow" ) AND Val( headerRow ) ); - if( hasHeaderRow ){ - result.Append( "" ); - result.Append( generateHtmlRow( columns,true ) ); - result.Append( "" ); - } - result.Append( "" ); - for( var row in query ){ - var rowValues=[]; - for( column in columns ){ - rowValues.Append( row[ column ] ); - } - result.Append( generateHtmlRow( rowValues ) ); - } - result.Append( "" ); - return result.ToList( "" ); -} - -private string function generateHtmlRow( required array values,boolean isHeader=false ){ - var result=[ "" ]; - var columnTag=isHeader? "th": "td"; - for( var value in values ){ - if( this.isDateObject( value ) ){ - value= DateTimeFormat( value,dateFormats.DATETIME ); - } - result.Append( "<#columnTag#>#value#" ); - } - result.Append( "" ); - return result.ToList( "" ); -} - -private boolean function rowIsEmpty( required row ){ - for( var i=row.getFirstCellNum(); i LT row.getLastCellNum(); i++ ){ - var cell = row.getCell( i ); - if( !IsNull( cell ) && ( cell.getCellType() != cell.CELL_TYPE_BLANK ) ) - return false; - } - return true; -} - -private void function setCellValueAsType( required workbook,required cell,required value ){ - if( IsNumeric( value ) AND !REFind( value,"^0[\d]+" ) ){ /* skip numeric strings with leading zeroes. treat those as text */ - /* NUMERIC */ - cell.setCellType( cell.CELL_TYPE_NUMERIC ); - cell.setCellValue( JavaCast( "double",Val( value ) ) ); - return; - } - if( IsDate( value ) ){ - /* DATE */ - var cellFormat = this.getDateTimeValueFormat( value ); - cell.setCellStyle( this.buildCellStyle( workbook,{ dataFormat=cellFormat } ) ); - cell.setCellType( cell.CELL_TYPE_NUMERIC ); - /* Excel's uses a different epoch than CF (1900-01-01 versus 1899-12-30). "Time" only values will not display properly without special handling - */ - if( cellFormat EQ variables.dateFormats.TIME ){ - var dateUtil = this.getDateUtil(); - value = TimeFormat( value, "HH:MM:SS" ); - cell.setCellValue( dateUtil.convertTime( value ) ); - } else { - cell.setCellValue( ParseDateTime( value ) ); - } - return; - } - if( IsBoolean( value ) ){ - /* BOOLEAN */ - cell.setCellType( cell.CELL_TYPE_BOOLEAN ); - cell.setCellValue( JavaCast( "boolean",value ) ); - return; - } - if( !value.Trim().Len() ){ - /* EMPTY */ - cell.setCellType( cell.CELL_TYPE_BLANK ); - cell.setCellValue( "" ); - return; - } - /* STRING */ - cell.setCellType( cell.CELL_TYPE_STRING ); - cell.setCellValue( JavaCast( "string",value ) ); -} - -private boolean function sheetExists( required workbook,string sheetName,numeric sheetNumber ){ - validateSheetNameOrNumberWasProvided( argumentCollection=arguments ); - if( arguments.KeyExists( "sheetName" ) ) - arguments.sheetNumber = this.getSheetIndexFromName( workbook,sheetName )+1; - //the position is valid if it an integer between 1 and the total number of sheets in the workbook - if( sheetNumber AND ( sheetNumber EQ Round( sheetNumber ) ) AND ( sheetNumber LTE workbook.getNumberOfSheets() ) ) - return true; - return false; -} - -private boolean function sheetHasMergedRegions( required sheet ){ - return ( sheet.getNumMergedRegions() GT 0 ); -} - -private query function sheetToQuery( - required workbook - ,string sheetName - ,numeric sheetNumber=1 - ,numeric headerRow - ,boolean includeHeaderRow=false - ,boolean includeBlankRows=false - ,boolean fillMergedCellsWithVisibleValue=false - ,string rows //range - ,string columns //range - ,string columnNames -){ - var sheet={ - includeHeaderRow=includeHeaderRow - ,hasHeaderRow=( arguments.KeyExists( "headerRow" ) AND Val( headerRow ) ) - ,includeBlankRows=includeBlankRows - ,columnNames=[] - ,columnRanges=[] - ,totalColumnCount=0 - }; - sheet.headerRowIndex = sheet.hasHeaderRow? headerRow-1: -1; - if( arguments.KeyExists( "columns" ) ){ - sheet.columnRanges=this.extractRanges( arguments.columns ); - sheet.totalColumnCount=columnCountFromRanges( sheet.columnRanges ); - } - if( arguments.KeyExists( "sheetName" ) ){ - validateSheetExistsWithName( workbook,sheetName ); - arguments.sheetNumber = getSheetIndexFromName( workbook,sheetName )+1; - } - sheet.object = workbook.GetSheetAt( JavaCast( "int",sheetNumber-1 ) ); - if( fillMergedCellsWithVisibleValue ) - this.fillMergedCellsWithVisibleValue( workbook,sheet.object ); - sheet.data = []; - if( arguments.KeyExists( "rows" ) ){ - var allRanges = this.extractRanges( arguments.rows ); - for( var thisRange in allRanges ){ - for( var rowNumber=thisRange.startAt; rowNumber LTE thisRange.endAt; rowNumber++ ){ - var rowIndex=rowNumber-1; - this.addRowToSheetData( workbook,sheet,rowIndex ); - } - } - } else { - var lastRowIndex = sheet.object.GetLastRowNum();// zero based - for( var rowIndex=0; rowIndex LTE lastRowIndex; rowIndex++ ){ - this.addRowToSheetData( workbook,sheet,rowIndex ); - } - } - //generate the query columns - if( arguments.KeyExists( "columnNames" ) AND arguments.columnNames.Len() ){ - arguments.columnNames=arguments.columnNames.ListToArray(); - for( var i=1; i LTE sheet.totalColumnCount; i++ ){ - var columnName=columnNames[ i ]?: "column" & i; - sheet.columnNames.Append( columnName ); - } - } else if( sheet.hasHeaderRow ){ - var headerRow=sheet.object.GetRow( JavaCast( "int",sheet.headerRowIndex ) ); - var rowData=getRowData( workbook,headerRow,sheet.columnRanges ); - var i=1; - for( var value in rowData ){ - var columnName="column" & i; - if( this.isString( value ) AND value.Len() ) - columnName=value; - sheet.columnNames.Append( columnName ); - i++; - } - } else { - for( var i=1; i LTE sheet.totalColumnCount; i++ ){ - sheet.columnNames.Append( "column" & i ); - } - } - return QueryNew( sheet.columnNames,"",sheet.data ); -} - -private void function validateSheetExistsWithName( required workbook,required string sheetName ){ - if( !this.sheetExists( workbook=workbook,sheetName=sheetName ) ) - throw( type=exceptionType,message="Invalid sheet name [#sheetName#]", detail="The specified sheet was not found in the current workbook." ); -} - -private void function validateSheetNumber( required workbook,required numeric sheetNumber ){ - if( !this.sheetExists( workbook=workbook,sheetNumber=sheetNumber ) ){ - var sheetCount = workbook.getNumberOfSheets(); - throw( type=exceptionType,message="Invalid sheet number [#sheetNumber#]",detail="The sheetNumber must a whole number between 1 and the total number of sheets in the workbook [#sheetCount#]" ); - } -} - -private void function validateSheetName( required string sheetName ){ - var poiTool = loadPoi( "org.apache.poi.ss.util.WorkbookUtil" ); - try{ - poiTool.validateSheetName( JavaCast( "String",sheetName ) ); - } - catch( "java.lang.IllegalArgumentException" exception ){ - throw( type=exceptionType,message="Invalid characters in sheet name",detail=exception.message ); - } -} - -private void function validateSheetNameOrNumberWasProvided(){ - if( !arguments.KeyExists( "sheetName" ) AND !arguments.KeyExists( "sheetNumber" ) ) - throw( type=exceptionType,message="Missing Required Argument", detail="Either sheetName or sheetNumber must be provided" ); - if( arguments.KeyExists( "sheetName" ) AND arguments.KeyExists( "sheetNumber" ) ) - throw( type=exceptionType,message="Too Many Arguments", detail="Only one argument is allowed. Specify either a sheetName or sheetNumber, not both" ); -} - -private function workbookFromFile( required string path ){ - // works with both xls and xlsx - try{ - lock name="#path#" timeout=5{ - var file = CreateObject( "java","java.io.FileInputStream" ).init( path ); - var workbook = loadPoi( "org.apache.poi.ss.usermodel.WorkbookFactory" ).create( file ); - } - return workbook; - } - finally{ - file.close(); - } -} - -private struct function xmlInfo( required workbook ){ - var documentProperties = workbook.getProperties().getExtendedProperties().getUnderlyingProperties(); - var coreProperties = workbook.getProperties().getCoreProperties(); - return { - author = coreProperties.getCreator()?:"" - ,category = coreProperties.getCategory()?:"" - ,comments = coreProperties.getDescription()?:"" - ,creationDate = coreProperties.getCreated()?:"" - ,lastEdited = coreProperties.getModified()?:"" - ,subject = coreProperties.getSubject()?:"" - ,title = coreProperties.getTitle()?:"" - ,lastAuthor = coreProperties.getUnderlyingProperties().getLastModifiedByProperty().getValue()?:"" - ,keywords = coreProperties.getKeywords()?:"" - ,lastSaved = ""// not available in xml - ,manager = documentProperties.getManager()?:"" - ,company = documentProperties.getCompany()?:"" - }; -} - \ No newline at end of file diff --git a/models/UtilService.cfc b/models/UtilService.cfc deleted file mode 100644 index 10c3b8c..0000000 --- a/models/UtilService.cfc +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/models/VarScoper/license.txt b/models/VarScoper/license.txt deleted file mode 100644 index f3f1e1d..0000000 --- a/models/VarScoper/license.txt +++ /dev/null @@ -1,14 +0,0 @@ -LICENSE -Copyright 2006 Mike Schierberl - - Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/models/VarScoper/readme.txt b/models/VarScoper/readme.txt deleted file mode 100644 index 90053d9..0000000 --- a/models/VarScoper/readme.txt +++ /dev/null @@ -1,88 +0,0 @@ -LICENSE -Copyright 2006 Mike Schierberl - - Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - -varScoper -Project Homepage: -http://www.schierberl.com/varscoper - - -Installation Instructions: - Extract all files to a publicly accesible directory on your CFMX 6 or 7 server. - Navigate to index.cfm or varscoper.cfm and enter the absolute or relative - path to the template or directory that you would like to check. - -History - -v1.3 - -CF Builder Extension Support - -Recognizes var statements anywhere in a function (CF9) - -Issues (13,14,15,16,17,18,19,20,21,23,25,26,27,28,30,31,32) Fixed - -Open BD/Railo Supported - -CFScript comments parsed correctly - -v1.2 - -Significant improvements to cfscript parsing engine - -Issues (6,7,8,9,10,11) fixed - -Ability to exclude files/folders using properties.xml (only when parsing a folder) - -Ability to identify tags with "multiple personalities" i.e. cffeed/cfprocparam that can have different behaviors for output variables based on params - -More agressive var scope checking (newly identified scenarios that were missed before) - -Addition of unit testing suite - -v1.12 - -added new tags to the parsing engine - -added XML output support - -fixed some bugs related to directory parsing in CF6 - -v1.1 - -added support for cfscript - -v1.0 - -initial release - -cf tag support - -Find unscoped variables created with a cfset within a cffunction - -Find unscoped variables created with cftags (cfloop, cfquery, etc) - -Report line numbers and link directly to the line in the file - -Output to screen or csv - - - - - - -Features: - -Identifies unscoped variables within cffunctions - -can return line numbers of functions/variables - -Known Limitations: - - -(fixed 1.13) Returns false positive when variables are set within a comments block - -(fixed 1.13) If you don't scope an argument value, and then reference that value it - will "technically" return a false positive... - - - instead of... - - -Future TODOs: - -(fixed 1.13) create a library of all cf tags that can create variables - -(fixed 1.13) cfscript - -(fixed 1.13) ignore things in comments (May need to use lookbehind? Not supported in CF as far as I know) - -Integration with cfeclipse - -How can I help? - -I need help extending the testCaseCFC file. If you come across false positives (or negatives) - within your code, please send me a snippet so I can add it to the testCaseCFC - -I need help finding all cftags that create variables (cfloop, cfquery, etc) - I'm sure there are some corner cases out there, I'd like to compile a comprehensive list. - -Send all requests for help or suggestions to mike@schierberl.com - - - diff --git a/models/VarScoper/varScoper.cfc b/models/VarScoper/varScoper.cfc deleted file mode 100644 index 5b1f47c..0000000 --- a/models/VarScoper/varScoper.cfc +++ /dev/null @@ -1,798 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ",fileParseText,currentPositionInFile,true)> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ' /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ",arguments.stringToProcess,currentPositionVariableFind)/> - - - - ",arguments.stringToProcess, variableCFScriptStart+1)/> - - - - - - '), - variableCFScriptEND-variableCFScriptSTART- len('') )/> - - - - - - - - - - - - - - - - - - ",arguments.stringToProcess,currentPositionVariableFind)> - - ")> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ' /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ---> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ---> - - - - - - - - - - - - - ]+\s*return\s(.*?)+;","","all")> - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/models/javaLoader/JavaCompiler.cfc b/models/javaLoader/JavaCompiler.cfc deleted file mode 100644 index 9f4f172..0000000 --- a/models/javaLoader/JavaCompiler.cfc +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - var data = {}; - var defaultCompiler = "com.sun.tools.javac.api.JavacTool"; - - //we have to manually go looking for the compiler - - try - { - data.compiler = getPageContext().getClass().getClassLoader().loadClass(defaultCompiler).newInstance(); - } - catch(any exc) - { - println("Error loading compiler:"); - println(exc.toString()); - } - - /* - If not by THIS point do we have a compiler, then throw an exception - */ - if(NOT StructKeyExists(data, "compiler")) - { - throwException("javaCompiler.NoCompilerAvailableException", - "No Java Compiler is available", - "There is no Java Compiler available. Make sure tools.jar is in your classpath and you are running Java 1.6+"); - } - - setCompiler(data.compiler); - setJarDirectory(arguments.jarDirectory); - - return this; - - - - - - - - - //setup file manager with default exception handler, default locale, and default character set - var fileManager = getCompiler().getStandardFileManager(JavaCast("null", ""), JavaCast("null", ""), JavaCast("null", "")); - var qFiles = 0; - var fileArray = []; - var directoryToCompile = 0; - var fileObjects = 0; - var osw = createObject("java", "java.io.StringWriter").init(); - var options = []; - var compilePass = 0; - var jarPath = getJarDirectory() & "/" & arguments.jarName; - - - - - - - - ArrayAppend(fileArray, qFiles.directory & "/" & qFiles.name); - - - - - if(structKeyExists(arguments, "classLoader")) - { - options = addClassLoaderFiles(options, arguments.classLoader, arguments.directoryArray); - } - - fileObjects = fileManager.getJavaFileObjectsFromStrings(fileArray); - - - - - //does the compilation - compilePass = getCompiler().getTask(osw, fileManager, JavaCast("null", ""), options, JavaCast("null", ""), fileObjects).call(); - - if(NOT compilePass) - { - throwException("javacompiler.SourceCompilationException", "There was an error compiling your source code", osw.toString()); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - var urls = 0; - var uri = 0; - var classPaths = createObject("java", "java.lang.StringBuilder").init(); - var File = createObject("java", "java.io.File"); - var path = 0; - - - - - - - - classPaths.append(uri.getFile()).append(File.pathSeparator); - - - - - - - - - - - - ArrayAppend(arguments.options, "-classpath"); - ArrayAppend(arguments.options, classPaths.toString()); - - return arguments.options; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - createObject("Java", "java.lang.System").out.println(arguments.str); - - - - \ No newline at end of file diff --git a/models/javaLoader/JavaLoader.cfc b/models/javaLoader/JavaLoader.cfc deleted file mode 100644 index 7280bdf..0000000 --- a/models/javaLoader/JavaLoader.cfc +++ /dev/null @@ -1,570 +0,0 @@ - - - - - instance = StructNew(); - instance.static.uuid = "A0608BEC-0AEB-B46A-0E1E1EC5F3CE7C9C"; - - - - - - - - - - - - - - - - initUseJavaProxyCFC(); - - if(arguments.loadColdFusionClassPath) - { - //arguments.parentClassLoader = createObject("java", "java.lang.Thread").currentThread().getContextClassLoader(); - //can't use above, as doesn't work in some... things - - arguments.parentClassLoader = getPageContext().getClass().getClassLoader(); - - //arguments.parentClassLoader = createObject("java", "java.lang.ClassLoader").getSystemClassLoader(); - //can't use the above, it doesn't have the CF stuff in it. - } - - setClassLoadPaths(arguments.loadPaths); - setParentClassLoader(arguments.parentClassLoader); - - ensureNetworkClassLoaderOnServerScope(); - - loadClasses(); - - if(structKeyExists(arguments, "sourceDirectories") AND ArrayLen(arguments.sourceDirectories)) - { - setJavaCompiler(createObject("component", "JavaCompiler").init(arguments.compileDirectory)); - setSourceDirectories(arguments.sourceDirectories); - setCompileDirectory(arguments.compileDirectory); - - setTrustedSource(arguments.trustedSource); - - compileSource(); - - setSourceLastModified(calculateSourceLastModified()); - - //do the method switching for non-trusted source - if(NOT arguments.trustedSource) - { - variables.createWithoutCheck = variables.create; - - StructDelete(this, "create"); - StructDelete(variables, "create"); - - this.create = variables.createWithSourceCheck; - } - } - - return this; - - - - - - - try - { - //do this in one line just for speed. - return createJavaProxy(getURLClassLoader().loadClass(arguments.className)); - } - catch(java.lang.ClassNotFoundException exc) - { - throwException("javaloader.ClassNotFoundException", "The requested class could not be found.", "The requested class '#arguments.className#' could not be found in the loaded jars/directories."); - } - - - - - - - - - - - - - - - var local = {}; - var System = createObject("java", "java.lang.System"); - var Thread = createObject("java", "java.lang.Thread"); - var currentClassloader = Thread.currentThread().getContextClassLoader(); - - if(structCount(arguments) == 2 && !isSimpleValue(arguments[2])) - { - classLoader = arguments[2]; - } - else if(structCount(arguments) == 3) - { - classLoader = arguments[3]; - } - else //assume we are still in JL - { - classLoader = getURLClassLoader(); - } - - - - - Thread.currentThread().setContextClassLoader(classloader); - - - - - - - local.func = arguments[1]; - local.return = local.func(); - - - - - - - - - - Thread.currentThread().setContextClassLoader(currentClassloader); - - - - - - - //need to do this twice, as cf8 has no finally. - Thread.currentThread().setContextClassLoader(currentClassloader); - - if(structKeyExists(local, "return")) - { - return local.return; - } - - - - - - - - - - - - - - - var dateLastModified = calculateSourceLastModified(); - - /* - If the source has changed in any way, recompile and load - */ - if(dateCompare(dateLastModified, getSourceLastModified()) eq 1) - { - loadClasses(); - compileSource(); - } - - //if all the comilation goes according to plan, set the date last modified - setSourceLastModified(dateLastModified); - - return createWithoutCheck(argumentCollection=arguments); - - - - - - var iterator = getClassLoadPaths().iterator(); - var file = 0; - var classLoader = 0; - var networkClassLoaderClass = 0; - var networkClassLoaderProxy = 0; - - networkClassLoaderClass = getServerURLClassLoader().loadClass("com.compoundtheory.classloader.NetworkClassLoader"); - - networkClassLoaderProxy = createJavaProxy(networkClassLoaderClass); - - if(isObject(getParentClassLoader())) - { - classLoader = networkClassLoaderProxy.init(getParentClassLoader()); - } - else - { - classLoader = networkClassLoaderProxy.init(); - } - - while(iterator.hasNext()) - { - file = createObject("java", "java.io.File").init(iterator.next()); - if(NOT file.exists()) - { - throwException("javaloader.PathNotFoundException", "The path you have specified could not be found", file.getAbsolutePath() & " does not exist"); - } - - classLoader.addUrl(file.toURL()); - } - - setURLClassLoader(classLoader); - - - - - - var dir = 0; - var path = 0; - - var paths = 0; - var file = 0; - var counter = 1; - var len = 0; - var directories = 0; - - //do check to see if the compiled jar is already there - var jarName = calculateJarName(getSourceDirectories()); - var jar = getCompileDirectory() & "/" & jarName; - - - - - - - - - - - - - - - - - - - - //first we copy the source to our tmp dir - directories = getSourceDirectories(); - len = arraylen(directories); - for(; counter lte len; counter = counter + 1) - { - dir = directories[counter]; - directoryCopy(dir, path); - } - - //then we compile it, and grab that jar - - paths = ArrayNew(1); //have to write it this way so CF7 compiles - ArrayAppend(paths, path); - - jar = getJavaCompiler().compile(paths, getURLClassLoader(), jarName); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - var file = hash(arrayToList(arguments.directoryArray)) & ".jar"; - - return file; - - - - - - var lastModified = createDate(1900, 1, 1); - var dir = 0; - var qLastModified = 0; - var directories = getSourceDirectories(); - var len = arraylen(directories); - var counter = 0; - - - - - - - - //it's possible there are no source files. - if(qLastModified.recordCount) - { - //get the latest date modified - if(dateCompare(lastModified, qlastModified.dateLastModified) eq -1) - { - /* - This is here, because cfdirectory only ever gives you minute accurate modified - date, which is not good enough. - */ - lastModified = createObject("java", "java.util.Date").init(createObject("java", "java.io.File").init(qLastModified.directory & "/" & qLastModified.name).lastModified()); - } - } - else - { - lastModified = Now(); - } - - - - - - - - - var Class = createObject("java", "java.lang.Class"); - var Array = createObject("java", "java.lang.reflect.Array"); - var jars = queryJars(); - var iterator = jars.iterator(); - var file = 0; - var urls = Array.newInstance(Class.forName("java.net.URL"), ArrayLen(jars)); - var counter = 0; - var urlClassLoader = 0; - var key = instance.static.uuid & "." & getVersion(); - - - - - - if(NOT StructKeyExists(server, key)) - { - while(iterator.hasNext()) - { - Array.set(urls, counter, createObject("java", "java.io.File").init(iterator.next()).toURL()); - counter = counter + 1; - } - - urlClassLoader = createObject("java", "java.net.URLClassLoader").init(urls); - - //put it on the server scope - server[key] = urlClassLoader; - } - - - - - - - - - return createObject("java", "coldfusion.runtime.java.JavaProxy").init(arguments.class); - - - - - - - return createObject("component", "JavaProxy")._init(arguments.class); - - - - - - try - { - createObject("java", "coldfusion.runtime.java.JavaProxy"); - } - catch(Object exc) - { - //do method replacement, as it will be much faster long term - variables.createJavaProxy = variables.createJavaProxyCFC; - } - - - - - - var qJars = 0; - //the path to my jar library - var path = getDirectoryFromPath(getMetaData(this).path) & "lib/"; - var jarList = ""; - var aJars = ArrayNew(1); - var libName = 0; - - - - - - libName = ListGetAt(name, 1, "-"); - //let's not use the lib's that have the same name, but a lower datestamp - if(NOT ListFind(jarList, libName)) - { - ArrayAppend(aJars, path & "/" & name); - jarList = ListAppend(jarList, libName); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/models/javaLoader/JavaProxy.cfc b/models/javaLoader/JavaProxy.cfc deleted file mode 100644 index 3f1b812..0000000 --- a/models/javaLoader/JavaProxy.cfc +++ /dev/null @@ -1,354 +0,0 @@ - - - - - - - - - - var classLoader = createObject("java", "java.lang.ClassLoader").getSystemClassLoader(); - var objectClass = classLoader.loadClass("java.lang.Object"); - - _setArray(createObject("java", "java.lang.reflect.Array")); - - _setClassMethod(objectClass.getMethod("getClass", JavaCast("null", 0))); - - _setObjectClass(objectClass); - - _setClass(arguments.class); - - _setModifier(createObject("java", "java.lang.reflect.Modifier")); - - _setStaticFields(); - - _initMethodCollection(); - - return this; - - - - - - var constructor = 0; - var instance = 0; - - //make sure we only ever have one instance - if(_hasClassInstance()) - { - return _getClassInstance(); - } - - constructor = _resolveMethodByParams("Constructor", _getClass().getConstructors(), arguments); - - instance = constructor.newInstance(_buildArgumentArray(arguments)); - - _setClassInstance(instance); - - return _getClassInstance(); - - - - - - - - - var method = _findMethod(arguments.missingMethodName, arguments.missingMethodArguments); - - if(_getModifier().isStatic(method.getModifiers())) - { - return method.invoke(JavaCast("null", 0), _buildArgumentArray(arguments.missingMethodArguments)); - } - else - { - if(NOT _hasClassInstance()) - { - //run the default constructor, just like in normal CF, if there is no instance - init(); - } - - return method.invoke(_getClassInstance(), _buildArgumentArray(arguments.missingMethodArguments)); - } - - - - - - - - - - - - var fields = _getClass().getFields(); - var counter = 1; - var len = ArrayLen(fields); - var field = 0; - - for(; counter <= len; counter++) - { - field = fields[counter]; - if(_getModifier().isStatic(field.getModifiers())) - { - this[field.getName()] = field.get(JavaCast("null", 0)); - } - } - - - - - - - var len = StructCount(arguments); - var objArray = _getArray().newInstance(_getObjectClass(), len); - var counter = 1; - var obj = 0; - - for(; counter <= len; counter++) - { - obj = arguments[counter]; - _getArray().set(objArray, counter - 1, obj); - } - - return objArray; - - - - - - - - var decision = 0; - - if(StructKeyExists(_getMethodCollection(), arguments.methodName)) - { - decision = StructFind(_getMethodCollection(), arguments.methodName); - - //if there is only one option, try it, it's only going to throw a runtime exception if it doesn't work. - if(ArrayLen(decision) == 1) - { - return decision[1]; - } - else - { - return _resolveMethodByParams(arguments.methodName, decision, arguments.methodArgs); - } - } - - throwException("JavaProxy.MethodNotFoundException", "Could not find the designated method", "Could not find the method '#arguments.methodName#' in the class #_getClass().getName()#"); - - - - - - - - - var decisionLen = ArrayLen(arguments.decision); - var method = 0; - var counter = 1; - var argLen = ArrayLen(arguments.methodArgs); - var parameters = 0; - var paramLen = 0; - var pCounter = 0; - var param = 0; - var class = 0; - var found = true; - - for(; counter <= decisionLen; counter++) - { - method = arguments.decision[counter]; - parameters = method.getParameterTypes(); - paramLen = ArrayLen(parameters); - - found = true; - - if(argLen eq paramLen) - { - for(pCounter = 1; pCounter <= paramLen AND found; pCounter++) - { - param = parameters[pCounter]; - class = _getClassMethod().invoke(arguments.methodArgs[pCounter], JavaCast("null", 0)); - - if(param.isAssignableFrom(class)) - { - found = true; - } - else if(param.isPrimitive()) //if it's a primitive, it can be mapped to object primtive classes - { - if(param.getName() eq "boolean" AND class.getName() eq "java.lang.Boolean") - { - found = true; - } - else if(param.getName() eq "int" AND class.getName() eq "java.lang.Integer") - { - found = true; - } - else if(param.getName() eq "long" AND class.getName() eq "java.lang.Long") - { - found = true; - } - else if(param.getName() eq "float" AND class.getName() eq "java.lang.Float") - { - found = true; - } - else if(param.getName() eq "double" AND class.getName() eq "java.lang.Double") - { - found = true; - } - else if(param.getName() eq "char" AND class.getName() eq "java.lang.Character") - { - found = true; - } - else if(param.getName() eq "byte" AND class.getName() eq "java.lang.Byte") - { - found = true; - } - else if(param.getName() eq "short" AND class.getName() eq "java.lang.Short") - { - found = true; - } - else - { - found = false; - } - } - else - { - found = false; - } - } - - if(found) - { - return method; - } - } - } - - throwException("JavaProxy.MethodNotFoundException", "Could not find the designated method", "Could not find the method '#arguments.methodName#' in the class #_getClass().getName()#"); - - - - - - var methods = _getClass().getMethods(); - var len = ArrayLen(methods); - var counter = 1; - var method = 0; - - _setMethodCollection(StructNew()); - - for(; counter <= len; counter++) - { - method = methods[counter]; - - if(NOT StructKeyExists(_getMethodCollection(), method.getName())) - { - StructInsert(_getMethodCollection(), method.getName(), ArrayNew(1)); - } - - ArrayAppend(StructFind(_getMethodCollection(), method.getName()), method); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/models/javaLoader/lib/classloader-20120103162851.jar b/models/javaLoader/lib/classloader-20120103162851.jar deleted file mode 100644 index ea07000..0000000 Binary files a/models/javaLoader/lib/classloader-20120103162851.jar and /dev/null differ diff --git a/models/javaLoader/lib/classloader-src.zip b/models/javaLoader/lib/classloader-src.zip deleted file mode 100644 index e86f27e..0000000 Binary files a/models/javaLoader/lib/classloader-src.zip and /dev/null differ diff --git a/models/javaLoader/licence.txt b/models/javaLoader/licence.txt deleted file mode 100644 index c9990a7..0000000 --- a/models/javaLoader/licence.txt +++ /dev/null @@ -1,213 +0,0 @@ -Common Public License Version 1.0 - -THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC -LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM -CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. - -1. DEFINITIONS - -"Contribution" means: - - a) in the case of the initial Contributor, the initial code and -documentation distributed under this Agreement, and - - b) in the case of each subsequent Contributor: - - i) changes to the Program, and - - ii) additions to the Program; - - where such changes and/or additions to the Program originate from and are -distributed by that particular Contributor. A Contribution 'originates' from a -Contributor if it was added to the Program by such Contributor itself or anyone -acting on such Contributor's behalf. Contributions do not include additions to -the Program which: (i) are separate modules of software distributed in -conjunction with the Program under their own license agreement, and (ii) are not -derivative works of the Program. - -"Contributor" means any person or entity that distributes the Program. - -"Licensed Patents " mean patent claims licensable by a Contributor which are -necessarily infringed by the use or sale of its Contribution alone or when -combined with the Program. - -"Program" means the Contributions distributed in accordance with this Agreement. - -"Recipient" means anyone who receives the Program under this Agreement, -including all Contributors. - -2. GRANT OF RIGHTS - - a) Subject to the terms of this Agreement, each Contributor hereby grants -Recipient a non-exclusive, worldwide, royalty-free copyright license to -reproduce, prepare derivative works of, publicly display, publicly perform, -distribute and sublicense the Contribution of such Contributor, if any, and such -derivative works, in source code and object code form. - - b) Subject to the terms of this Agreement, each Contributor hereby grants -Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed -Patents to make, use, sell, offer to sell, import and otherwise transfer the -Contribution of such Contributor, if any, in source code and object code form. -This patent license shall apply to the combination of the Contribution and the -Program if, at the time the Contribution is added by the Contributor, such -addition of the Contribution causes such combination to be covered by the -Licensed Patents. The patent license shall not apply to any other combinations -which include the Contribution. No hardware per se is licensed hereunder. - - c) Recipient understands that although each Contributor grants the licenses -to its Contributions set forth herein, no assurances are provided by any -Contributor that the Program does not infringe the patent or other intellectual -property rights of any other entity. Each Contributor disclaims any liability to -Recipient for claims brought by any other entity based on infringement of -intellectual property rights or otherwise. As a condition to exercising the -rights and licenses granted hereunder, each Recipient hereby assumes sole -responsibility to secure any other intellectual property rights needed, if any. -For example, if a third party patent license is required to allow Recipient to -distribute the Program, it is Recipient's responsibility to acquire that license -before distributing the Program. - - d) Each Contributor represents that to its knowledge it has sufficient -copyright rights in its Contribution, if any, to grant the copyright license set -forth in this Agreement. - -3. REQUIREMENTS - -A Contributor may choose to distribute the Program in object code form under its -own license agreement, provided that: - - a) it complies with the terms and conditions of this Agreement; and - - b) its license agreement: - - i) effectively disclaims on behalf of all Contributors all warranties and -conditions, express and implied, including warranties or conditions of title and -non-infringement, and implied warranties or conditions of merchantability and -fitness for a particular purpose; - - ii) effectively excludes on behalf of all Contributors all liability for -damages, including direct, indirect, special, incidental and consequential -damages, such as lost profits; - - iii) states that any provisions which differ from this Agreement are offered -by that Contributor alone and not by any other party; and - - iv) states that source code for the Program is available from such -Contributor, and informs licensees how to obtain it in a reasonable manner on or -through a medium customarily used for software exchange. - -When the Program is made available in source code form: - - a) it must be made available under this Agreement; and - - b) a copy of this Agreement must be included with each copy of the Program. - -Contributors may not remove or alter any copyright notices contained within the -Program. - -Each Contributor must identify itself as the originator of its Contribution, if -any, in a manner that reasonably allows subsequent Recipients to identify the -originator of the Contribution. - -4. COMMERCIAL DISTRIBUTION - -Commercial distributors of software may accept certain responsibilities with -respect to end users, business partners and the like. While this license is -intended to facilitate the commercial use of the Program, the Contributor who -includes the Program in a commercial product offering should do so in a manner -which does not create potential liability for other Contributors. Therefore, if -a Contributor includes the Program in a commercial product offering, such -Contributor ("Commercial Contributor") hereby agrees to defend and indemnify -every other Contributor ("Indemnified Contributor") against any losses, damages -and costs (collectively "Losses") arising from claims, lawsuits and other legal -actions brought by a third party against the Indemnified Contributor to the -extent caused by the acts or omissions of such Commercial Contributor in -connection with its distribution of the Program in a commercial product -offering. The obligations in this section do not apply to any claims or Losses -relating to any actual or alleged intellectual property infringement. In order -to qualify, an Indemnified Contributor must: a) promptly notify the Commercial -Contributor in writing of such claim, and b) allow the Commercial Contributor to -control, and cooperate with the Commercial Contributor in, the defense and any -related settlement negotiations. The Indemnified Contributor may participate in -any such claim at its own expense. - -For example, a Contributor might include the Program in a commercial product -offering, Product X. That Contributor is then a Commercial Contributor. If that -Commercial Contributor then makes performance claims, or offers warranties -related to Product X, those performance claims and warranties are such -Commercial Contributor's responsibility alone. Under this section, the -Commercial Contributor would have to defend claims against the other -Contributors related to those performance claims and warranties, and if a court -requires any other Contributor to pay any damages as a result, the Commercial -Contributor must pay those damages. - -5. NO WARRANTY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR -IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each -Recipient is solely responsible for determining the appropriateness of using and -distributing the Program and assumes all risks associated with its exercise of -rights under this Agreement, including but not limited to the risks and costs of -program errors, compliance with applicable laws, damage to or loss of data, -programs or equipment, and unavailability or interruption of operations. - -6. DISCLAIMER OF LIABILITY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY -CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST -PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS -GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -7. GENERAL - -If any provision of this Agreement is invalid or unenforceable under applicable -law, it shall not affect the validity or enforceability of the remainder of the -terms of this Agreement, and without further action by the parties hereto, such -provision shall be reformed to the minimum extent necessary to make such -provision valid and enforceable. - -If Recipient institutes patent litigation against a Contributor with respect to -a patent applicable to software (including a cross-claim or counterclaim in a -lawsuit), then any patent licenses granted by that Contributor to such Recipient -under this Agreement shall terminate as of the date such litigation is filed. In -addition, if Recipient institutes patent litigation against any entity -(including a cross-claim or counterclaim in a lawsuit) alleging that the Program -itself (excluding combinations of the Program with other software or hardware) -infringes such Recipient's patent(s), then such Recipient's rights granted under -Section 2(b) shall terminate as of the date such litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it fails to -comply with any of the material terms or conditions of this Agreement and does -not cure such failure in a reasonable period of time after becoming aware of -such noncompliance. If all Recipient's rights under this Agreement terminate, -Recipient agrees to cease use and distribution of the Program as soon as -reasonably practicable. However, Recipient's obligations under this Agreement -and any licenses granted by Recipient relating to the Program shall continue and -survive. - -Everyone is permitted to copy and distribute copies of this Agreement, but in -order to avoid inconsistency the Agreement is copyrighted and may only be -modified in the following manner. The Agreement Steward reserves the right to -publish new versions (including revisions) of this Agreement from time to time. -No one other than the Agreement Steward has the right to modify this Agreement. -IBM is the initial Agreement Steward. IBM may assign the responsibility to serve -as the Agreement Steward to a suitable separate entity. Each new version of the -Agreement will be given a distinguishing version number. The Program (including -Contributions) may always be distributed subject to the version of the Agreement -under which it was received. In addition, after a new version of the Agreement -is published, Contributor may elect to distribute the Program (including its -Contributions) under the new version. Except as expressly stated in Sections -2(a) and 2(b) above, Recipient receives no rights or licenses to the -intellectual property of any Contributor under this Agreement, whether -expressly, by implication, estoppel or otherwise. All rights in the Program not -expressly granted under this Agreement are reserved. - -This Agreement is governed by the laws of the State of New York and the -intellectual property laws of the United States of America. No party to this -Agreement will bring a legal action under this Agreement more than one year -after the cause of action arose. Each party waives its rights to a jury trial in -any resulting litigation. diff --git a/models/javaLoader/readme.txt b/models/javaLoader/readme.txt deleted file mode 100644 index 1d035a6..0000000 --- a/models/javaLoader/readme.txt +++ /dev/null @@ -1,6 +0,0 @@ -JavaLoader v1.0 -Author: Mark Mandel -Date: 10 September 2010 - -Documentation can now be found at: -http://www.compoundtheory.com/javaloader/docs/ \ No newline at end of file diff --git a/models/javaLoader/support/cfcdynamicproxy/lib/cfcdynamicproxy-src.zip b/models/javaLoader/support/cfcdynamicproxy/lib/cfcdynamicproxy-src.zip deleted file mode 100644 index f3b9d83..0000000 Binary files a/models/javaLoader/support/cfcdynamicproxy/lib/cfcdynamicproxy-src.zip and /dev/null differ diff --git a/models/javaLoader/support/cfcdynamicproxy/lib/cfcdynamicproxy.jar b/models/javaLoader/support/cfcdynamicproxy/lib/cfcdynamicproxy.jar deleted file mode 100644 index 4c4afc2..0000000 Binary files a/models/javaLoader/support/cfcdynamicproxy/lib/cfcdynamicproxy.jar and /dev/null differ diff --git a/models/javaLoader/support/spring/lib/spring-coldfusion-src.zip b/models/javaLoader/support/spring/lib/spring-coldfusion-src.zip deleted file mode 100644 index d308f05..0000000 Binary files a/models/javaLoader/support/spring/lib/spring-coldfusion-src.zip and /dev/null differ diff --git a/models/javaLoader/support/spring/lib/spring-coldfusion.jar b/models/javaLoader/support/spring/lib/spring-coldfusion.jar deleted file mode 100644 index daa64a1..0000000 Binary files a/models/javaLoader/support/spring/lib/spring-coldfusion.jar and /dev/null differ diff --git a/models/javaLoader/tags/directory.cfm b/models/javaLoader/tags/directory.cfm deleted file mode 100644 index 3601708..0000000 --- a/models/javaLoader/tags/directory.cfm +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - diff --git a/modules/PutStuffHere.txt b/modules/PutStuffHere.txt deleted file mode 100644 index e69de29..0000000 diff --git a/views/_templates/404.html b/views/_templates/404.html deleted file mode 100644 index c024a94..0000000 --- a/views/_templates/404.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - The page you requested does not exist - - - - -
-

The page you requested does not exist.

-

You may have mistyped the address or the page may have moved. Please check your address again.

-
- - \ No newline at end of file diff --git a/views/_templates/generic_error.cfm b/views/_templates/generic_error.cfm deleted file mode 100644 index ee39085..0000000 --- a/views/_templates/generic_error.cfm +++ /dev/null @@ -1,43 +0,0 @@ - -

An Unhandled Exception Occurred

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
An unhandled exception has occurred. Please look at the diagnostic information below:
Type#exception.getType()#
Message#exception.getMessage()#
Detail#exception.getDetail()#
Extended Info#exception.getExtendedInfo()#
Message#exception.getMessage()#
Tag Context - - - - #variables.tagCtx['template']# (#variables.tagCtx['line']#)
-
-
Stack Trace#exception.getStackTrace()#
-
diff --git a/views/main/print.cfm b/views/main/print.cfm index 27b24b2..2a7a265 100644 --- a/views/main/print.cfm +++ b/views/main/print.cfm @@ -1,63 +1,6 @@ - - - - - - -result=queryNew("directory,file,rule,message,linenumber,category,severity"); -for(var i=1; i<=ArrayLen(session.results);i=(i+1)){ -queryAddRow(result); -querySetCell(result,"directory",session.results[i].directory); -querySetCell(result,"file",session.results[i].file); -querySetCell(result,"rule",session.results[i].rule); -querySetCell(result,"message",session.results[i].message); -querySetCell(result,"linenumber",session.results[i].linenumber); -querySetCell(result,"category",session.results[i].category); -querySetCell(result,"severity",session.results[i].severity); -} - - - - - - - - - select directory,file,rule,message,linenumber,category,severity from result where category= order by category - - - - - - counter = 0; - spreadsheet = createObject('component','models.SpreadSheet.Spreadsheet').init(); - writeDump( spreadsheet ); - //spreadsheet = New spreadsheet(); - workbook = spreadsheet.new(); -for(i=1;i<=arrayLen(vCategories);i++){ - counter = counter + 1; - value = safeVariable(vCategories[i]); - rc = value & '.recordcount'; - if(rc gt 0); { - data = 'data' & counter; - data = Evaluate(value); - spreadsheet.createSheet( workbook,#left(LCase(value),30)#); - spreadsheet.setActiveSheet(workbook,#left(LCase(value),30)#); - spreadsheet.addRow(workbook=workbook, data="directory,file,rule,message,linenumber,category,severity,Developer-Assigned,Status", autoSizeColumns=1); - spreadsheet.addRows(workbook,data); - } -} - - spreadsheet.removesheet(workbook,"Sheet1"); - spreadsheet.setActiveSheetNumber(workbook,1); - //path = "checker.xls"; - //overwrite="yes"; - //spreadsheet.write( workbook,path,overwrite ); - binary=spreadsheet.readBinary(workbook); - - +