Task 019: .AHK File Format

Task 019: .AHK File Format

1. List of Properties of the .AHK File Format Intrinsic to Its File System

The .AHK file format is used for AutoHotkey scripts, which are plain text files containing automation instructions for Microsoft Windows. There is no binary structure or magic number associated with .AHK files; they follow standard text file conventions, typically encoded in UTF-8 or ANSI. Properties intrinsic to the file system refer to metadata attributes maintained by the operating system for any file, including .AHK files. These are not unique to .AHK but are standard file system attributes. Based on cross-platform file system standards (e.g., POSIX stat structure, adaptable to Windows NTFS), the comprehensive list includes:

  • File Name: The name of the file, including the .ahk extension.
  • File Size: The size of the file in bytes.
  • Last Access Time: The timestamp of the last time the file was accessed.
  • Last Modification Time: The timestamp of the last time the file content was modified.
  • Creation Time: The timestamp when the file was created (on Windows) or metadata last changed (on Unix-like systems).
  • Permissions: The file access mode, represented as an octal value or descriptive flags (e.g., read, write, execute for owner, group, and others).
  • User ID: The numeric identifier of the file's owner.
  • Group ID: The numeric identifier of the file's group.

These properties are retrieved using system calls or APIs in programming languages. Timestamps are typically in Unix epoch format but can be converted to human-readable dates.

The following are direct download links to sample .AHK files hosted on public repositories:

These files contain example AutoHotkey scripts and can be downloaded directly via a web browser or tools like wget.

3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .AHK File Property Dump

The following is an HTML snippet with embedded JavaScript suitable for embedding in a Ghost blog post (or any HTML-based platform). It creates a drag-and-drop zone where a user can drop a .AHK file. Upon dropping, it validates the file extension and displays the available file system properties (limited to those accessible via the browser's File API: name, size, type, and last modified time). Properties are dumped to the screen in a designated output area. Note that browser security restrictions prevent access to full file system metadata like creation time, permissions, user ID, or group ID.

Drag-and-Drop .AHK File Analyzer

Drag and Drop .AHK File

Drop a .AHK file here

This code can be copied into a Ghost blog post's HTML block for embedding.

4. Python Class for Handling .AHK Files

The following Python class uses the os and stat modules to open a .AHK file, read its file system properties, print them to the console, and support writing (modifying) modifiable properties like timestamps and permissions. Decoding is not applicable as .AHK files are plain text, but metadata retrieval is handled. The write method allows setting last access and modification times (via os.utime) and permissions (via os.chmod).

import os
import stat
import time

class AhkFileHandler:
    def __init__(self, filepath):
        self.filepath = filepath
        if not self.filepath.endswith('.ahk'):
            raise ValueError("File must have .ahk extension")
        self.stats = os.stat(self.filepath)

    def read_properties(self):
        return {
            'File Name': os.path.basename(self.filepath),
            'File Size': self.stats.st_size,
            'Last Access Time': time.ctime(self.stats.st_atime),
            'Last Modification Time': time.ctime(self.stats.st_mtime),
            'Creation Time': time.ctime(self.stats.st_ctime),
            'Permissions': oct(self.stats.st_mode),
            'User ID': self.stats.st_uid,
            'Group ID': self.stats.st_gid
        }

    def print_properties(self):
        props = self.read_properties()
        for key, value in props.items():
            print(f"{key}: {value}")

    def write_properties(self, atime=None, mtime=None, permissions=None):
        if atime is not None and mtime is not None:
            os.utime(self.filepath, (atime, mtime))
        if permissions is not None:
            os.chmod(self.filepath, permissions)
        self.stats = os.stat(self.filepath)  # Refresh stats

# Example usage:
# handler = AhkFileHandler('example.ahk')
# handler.print_properties()
# handler.write_properties(atime=time.time(), mtime=time.time(), permissions=0o644)

5. Java Class for Handling .AHK Files

The following Java class uses java.nio.file to open a .AHK file, read its file system properties, print them to the console, and support writing modifiable properties like timestamps and permissions. Java's BasicFileAttributes provides access to creation time. The write method uses Files.setLastModifiedTime and Files.setPosixFilePermissions (POSIX permissions may not apply on Windows).

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.time.Instant;
import java.util.Set;

public class AhkFileHandler {
    private final Path filepath;
    private BasicFileAttributes attrs;

    public AhkFileHandler(String filepath) throws IOException {
        this.filepath = Paths.get(filepath);
        if (!this.filepath.toString().endsWith(".ahk")) {
            throw new IllegalArgumentException("File must have .ahk extension");
        }
        this.attrs = Files.readAttributes(this.filepath, BasicFileAttributes.class);
    }

    public void readAndPrintProperties() throws IOException {
        attrs = Files.readAttributes(filepath, BasicFileAttributes.class);  // Refresh
        UserPrincipal owner = Files.getOwner(filepath);
        PosixFileAttributes posixAttrs = null;
        try {
            posixAttrs = Files.readAttributes(filepath, PosixFileAttributes.class);
        } catch (UnsupportedOperationException e) {
            // POSIX not supported (e.g., Windows)
        }

        System.out.println("File Name: " + filepath.getFileName());
        System.out.println("File Size: " + attrs.size());
        System.out.println("Last Access Time: " + attrs.lastAccessTime());
        System.out.println("Last Modification Time: " + attrs.lastModifiedTime());
        System.out.println("Creation Time: " + attrs.creationTime());
        System.out.println("Permissions: " + (posixAttrs != null ? posixAttrs.permissions() : "Not available"));
        System.out.println("User ID: " + owner.getName());  // User name as proxy for ID
        System.out.println("Group ID: " + (posixAttrs != null ? posixAttrs.group().getName() : "Not available"));
    }

    public void writeProperties(FileTime atime, FileTime mtime, Set<PosixFilePermission> permissions) throws IOException {
        if (atime != null) Files.setAttribute(filepath, "lastAccessTime", atime);
        if (mtime != null) Files.setLastModifiedTime(filepath, mtime);
        if (permissions != null) Files.setPosixFilePermissions(filepath, permissions);
        attrs = Files.readAttributes(filepath, BasicFileAttributes.class);  // Refresh
    }

    // Example usage:
    // public static void main(String[] args) throws IOException {
    //     AhkFileHandler handler = new AhkFileHandler("example.ahk");
    //     handler.readAndPrintProperties();
    //     handler.writeProperties(FileTime.from(Instant.now()), FileTime.from(Instant.now()), null);
    // }
}

6. JavaScript Class for Handling .AHK Files

The following JavaScript class (for Node.js environment) uses the fs module to open a .AHK file, read its file system properties, print them to the console, and support writing modifiable properties like timestamps and permissions. Requires Node.js for file system access.

const fs = require('fs');
const path = require('path');

class AhkFileHandler {
    constructor(filepath) {
        this.filepath = filepath;
        if (!this.filepath.endsWith('.ahk')) {
            throw new Error('File must have .ahk extension');
        }
        this.stats = fs.statSync(this.filepath);
    }

    readProperties() {
        this.stats = fs.statSync(this.filepath);  // Refresh
        return {
            'File Name': path.basename(this.filepath),
            'File Size': this.stats.size,
            'Last Access Time': new Date(this.stats.atime).toLocaleString(),
            'Last Modification Time': new Date(this.stats.mtime).toLocaleString(),
            'Creation Time': new Date(this.stats.birthtime).toLocaleString(),
            'Permissions': this.stats.mode.toString(8),
            'User ID': this.stats.uid,
            'Group ID': this.stats.gid
        };
    }

    printProperties() {
        const props = this.readProperties();
        for (const [key, value] of Object.entries(props)) {
            console.log(`${key}: ${value}`);
        }
    }

    writeProperties(atime = null, mtime = null, permissions = null) {
        if (atime !== null && mtime !== null) {
            fs.utimesSync(this.filepath, atime, mtime);
        }
        if (permissions !== null) {
            fs.chmodSync(this.filepath, permissions);
        }
        this.stats = fs.statSync(this.filepath);  // Refresh
    }
}

// Example usage:
// const handler = new AhkFileHandler('example.ahk');
// handler.printProperties();
// handler.writeProperties(new Date(), new Date(), 0o644);

7. C Struct and Functions for Handling .AHK Files

In C, classes are not native, so the following uses a struct with associated functions to open a .AHK file, read its file system properties (via stat), print them to the console, and support writing modifiable properties like timestamps and permissions (via utime and chmod). Compile with a standard C compiler (e.g., gcc).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <utime.h>
#include <unistd.h>

typedef struct {
    char *filepath;
    struct stat stats;
} AhkFileHandler;

void init_ahk_handler(AhkFileHandler *handler, const char *filepath) {
    handler->filepath = strdup(filepath);
    if (strstr(handler->filepath, ".ahk") != handler->filepath + strlen(handler->filepath) - 4) {
        fprintf(stderr, "File must have .ahk extension\n");
        exit(1);
    }
    if (stat(handler->filepath, &handler->stats) != 0) {
        perror("stat");
        exit(1);
    }
}

void read_and_print_properties(AhkFileHandler *handler) {
    if (stat(handler->filepath, &handler->stats) != 0) {
        perror("stat");
        return;
    }
    printf("File Name: %s\n", handler->filepath);
    printf("File Size: %ld\n", handler->stats.st_size);
    printf("Last Access Time: %s", ctime(&handler->stats.st_atime));
    printf("Last Modification Time: %s", ctime(&handler->stats.st_mtime));
    printf("Creation Time: %s", ctime(&handler->stats.st_ctime));
    printf("Permissions: %o\n", handler->stats.st_mode & 0777);
    printf("User ID: %d\n", handler->stats.st_uid);
    printf("Group ID: %d\n", handler->stats.st_gid);
}

void write_properties(AhkFileHandler *handler, time_t atime, time_t mtime, mode_t permissions) {
    struct utimbuf times = {atime, mtime};
    if (atime != -1 && mtime != -1) {
        if (utime(handler->filepath, &times) != 0) {
            perror("utime");
        }
    }
    if (permissions != -1) {
        if (chmod(handler->filepath, permissions) != 0) {
            perror("chmod");
        }
    }
    stat(handler->filepath, &handler->stats);  // Refresh
}

void free_ahk_handler(AhkFileHandler *handler) {
    free(handler->filepath);
}

// Example usage:
// int main() {
//     AhkFileHandler handler;
//     init_ahk_handler(&handler, "example.ahk");
//     read_and_print_properties(&handler);
//     time_t now = time(NULL);
//     write_properties(&handler, now, now, 0644);
//     free_ahk_handler(&handler);
//     return 0;
// }