CFDocs: CFML Reference Tool

repository·master·Indexed 41 days ago

https://github.com/foundeo/cfdocs

A community-maintained reference tool for CFML (ColdFusion Markup Language) providing documentation for tags and functions. It includes guides on Application.cfc lifecycle methods, the APPLICATION and CGI scopes, CF_SQL_* type mappings, and identification of Adobe ColdFusion specific features.

Tokens
43K
Snippets
107
Records
161
Agent score
52%

What's inside CFDocs

  1. Understand the ColdFusion installation directory structure

    master

    The cf_root directory (e.g., C:\ColdFusion11 on Windows or /opt/ColdFusion11 on UNIX) contains the following key directories:

    • cfusion/bin: Programs for starting/stopping ColdFusion, viewing info, running Crystal Reports (Windows), and password reset scripts.
    • cfusion/cache: Repository for temporary files.
    • cfusion/lib: Core JAR, XML, and property files for queries, charting, mail, security, Solr, etc.
    • cfusion/logs: ColdFusion log files. Console outputs are logged to coldfusion-out.log.
    • cfusion/runtime: ColdFusion runtime programs and Tomcat libraries. The conf directory inside contains Tomcat configuration files.
    • cfusion/wwwroot: Default web root directory for the built-in web server.
    • config: Contains instances.xml, cluster configuration (cluster.xml), and connector configuration files.
    • jre: Java runtime files.
    • uninstall: Files used to uninstall ColdFusion.
  2. Customize the constructor method with `initmethod`

    master

    If you do not want to use the default init method as your constructor, you can specify a different method using the initmethod attribute in the component tag. The method specified will be called upon instantiation.

    component initmethod="birth" {
        public Dog function birth( required string name, string breed="mixed" ) {
            variables.name = name;
            return this;
        }
    }
    
    <!--- Usage --->
    <cfset pet = new Dog( "fido" )>
  3. Understand ColdFusion Server Profile characteristics

    master

    Development Profile

    Use this profile for local development. It provides enhanced debugging, remote inspection, remote start/stop, and support for bundled servers like Node.js or Weinre. It has low security settings and does not enforce complex passwords.

    Production Profile

    Use this for internal production servers. It disables RDS (Remote Development Services) and enables strict enforcement of complex passwords. It disables most debugging and remote inspection features to improve stability and security.

    Production Profile (Secure)

    Use this for high-security production environments. It includes all the security hardening of the standard Production Profile, plus it enables the 'Secure Profile' settings by default.

  4. Choose between ECB and CBC encryption modes

    master

    When using encrypt() and decrypt(), you must choose a cipher mode:

    • ECB (Electronic Code Book): The default mode. It is considered a weak cipher mode because it encrypts blocks in parallel, making it easier to perform forced decryption once one block is broken. Use this only when you need repeatable encryption (e.g., for user authentication lookups).
    • CBC (Cipher-Block Chaining): A more secure mode that uses an XOR of the previous block as an initialization vector. This makes it much harder to decipher the key from a single block.

    Note: Using CBC with PKCS5Padding will produce a different encrypted output every time you encrypt the same input. This is ideal for security but prevents you from using the encrypted value as a lookup key in a database.

    // Example of secure CBC encryption
    myString = 'dog';
    myKey = 'ITRkCTb/XMtGT0g9WUkKak/hhNvPml3k+UbsVDqSBE=';
    myAlgorithm = 'AES/CBC/PKCS5Padding';
    myEncoding = 'HEX';
    encString = encrypt( myString, myKey, myAlgorithm, myEncoding );
  5. Understand the `server` scope

    master
    The server scope is a global scope in CFML that holds variables accessible to all applications running on the server. It is used to store server-wide configuration, environment details, and system information that does not change between individual application requests.
  6. What are ColdFusion Member Functions

    master

    Introduced in CF11+, Member Functions allow CFML data types (like Arrays, Strings, and Structs) to be treated as objects. Instead of passing a variable into a standalone function (e.g., arrayAppend(myArray, item)), you invoke the function directly on the variable (e.g., myArray.append(item)). This results in more concise and readable code.

    Key Benefits:

    • Conciseness: Skips passing the variable as the first argument.
    • Chaining: On Lucee or CF2018+, you can chain multiple member functions together in a single statement.
    • Object-Oriented Syntax: Allows interacting with Java objects using CF-style member syntax.
    // Standard headless function
    arrayAppend(empArr, emp)
    
    // Member function equivalent
    empArr.append(emp)
    
    // Chaining (Lucee or CF2018+)
    s = "the";
    s = s.listAppend("quick brown fox", " ")
         .listAppend("jumps over the lazy dog", " ")
         .uCase()
         .reverse();
  7. How session rotation and updates work

    master

    To maintain high security, sessions should be rotated (changing the session ID) and updated (refreshing the last activity timestamp) on every request.

    • Session Rotation: Generates a new unique ID (e.g., using createUUID() and now() hashed with SHA-384) and assigns it to the session object. This helps mitigate session fixation attacks.
    • Session Update: Clears the old session entry from storage, updates the lastActionAt timestamp to the current time, and saves the updated object back to storage (e.g., the cache).

    Warning: Session rotation can interfere with browser 'Back' button functionality, as the previously assigned cookie will become invalid. Some applications may choose to omit rotation for better UX.

    // Example of rotation logic
    public any function rotateUserSession( required any sessionObj ) {
        arguments.sessionObj.setSessionId( getSessionId() );
        return arguments.sessionObj;
    }
    
    // Example of update logic
    public any function updateUserSession( required any sessionObj ) {
        clearUserSession( arguments.sessionObj );
        arguments.sessionObj.setLastActionAt( now() );
        setUserSession( arguments.sessionObj );
        return arguments.sessionObj;
    }
  8. Use built-in ColdFusion functions as first-class citizens

    master

    In CFDocs, built-in ColdFusion functions are treated as 'first-class' functions. This means you can treat functions like lCase(), uCase(), or any other built-in CFML function as objects. You can assign them to variables or pass them directly as arguments to other functions (callbacks).

    Note: The ability to return built-in functions from other functions (e.g., return lCase;) is specific to ColdFusion versions CF11 through CF2021.

    function convertCaseForArray(array array, function convertor)
    {
        for (var i=1; i <= arrayLen(array); i++) {
            array[i] = convertor(array[i]);
        } 
        return array;
    }
    
    // Passing the built-in lCase function as a callback argument
    resultantArray = convertCaseForArray(['One', 'Two','Three'], lCase);
  9. Avoid UI-generating tags in CFML

    master

    The CFML community generally discourages the use of tags that generate client-side UI code directly. Instead of using these tags, consider using modern web standards or manual HTML/JavaScript generation to maintain better control over your frontend.

    Discouraged UI tags include:
    - `cfcol`
    - `cfdiv`
    - `cfgrid`, `cfgridcolumn`, `cfgridrow`, `cfgridupdate`
    - `cflayout`, `cflayoutarea`, `cfpod`
    - `cfmap`, `cfmapitem`
    - `cfmenu`, `cfmenuitem`
    - `cfprogressbar`
    - `cfselect`
    - `cftable`
    - `cftooltip`
    - `cftree`, `cftreeitem`
    - `cfwindow`
  10. Use the APPLICATION scope for shared data

    master

    The APPLICATION scope is used to store information that is shared across all requests within a specific application.

    • Availability: Variables set in the APPLICATION scope are accessible from anywhere within the application.
    • Lifecycle: Variables are typically initialized during onApplicationStart and remain constant throughout the application lifecycle.
    • Timeout: The default timeout is 2 days, but you can customize it by setting this.applicationTimeout in your Application.cfc.

    Example of initializing a variable in onApplicationStart:

    component {
        this.name = "myApplication";
    
        function onApplicationStart() {
            application.something = "otherthing";
        }
    }
  11. Handle concurrency and locking in the APPLICATION scope

    master

    Because the APPLICATION scope is shared across multiple simultaneous requests (threads), you must manage concurrency to prevent data corruption.

    When locking is NOT required:

    • If you only set variables in onApplicationStart and do not modify them later (except for reading in onRequestStart).
    • In most modern ColdFusion/Lucee environments, simple reads/writes are handled automatically.

    When locking IS required:

    • When performing operations that use the application scope on both sides of an assignment (e.g., incrementing a counter).
    • To ensure a consistent value if a variable might be changed mid-request by another thread.

    Use the lock block to ensure atomicity:

    lock scope="application" timeout="1" type="exclusive" {
        application.counter += 1;
    }
  12. Use the Ternary Operator for conditional logic

    master

    The Ternary operator (? :) is a decision-making operator that allows you to execute one of two statements based on a condition. It requires three operands: a condition, a true statement, and a false statement.

    Syntax: ((condition) ? trueStatement : falseStatement)

    If the condition evaluates to true, the trueStatement is executed; otherwise, the falseStatement is executed.

    // Example of ternary usage
    result = isNumeric("nineteen") ? "it's numeric" : "no it isn't"; // returns "no it isn't"