Task 293: .HTA File Format

Task 293: .HTA File Format

1. List of all the properties of the .HTA file format intrinsic to its file system

The .HTA (HTML Application) file format is a text-based format consisting of HTML markup, optionally including a specialized <HTA:APPLICATION> tag in the <HEAD> section. This tag defines attributes that control the behavior and appearance of the application when executed via mshta.exe on Windows. These attributes represent the core "properties" intrinsic to the format, as they are embedded directly in the file's content and influence how the file system and runtime interpret the HTA (e.g., window styles, permissions, and execution settings). Note that .HTA files do not have binary structures or unique file system metadata beyond standard file attributes (like size, timestamps); the properties are parsed from the HTML text.

Based on the official Microsoft documentation for the HTA:APPLICATION object, here is the complete list of attributes (properties) that can be set in the <HTA:APPLICATION> tag, along with their descriptions and types where specified:

  • APPLICATIONNAME (or applicationName): Sets or gets the name of the HTML Application (HTA). Type: String.
  • BORDER (or border): Sets or gets the type of window border for the HTML Application (HTA). Type: String (e.g., "thick", "thin", "none").
  • BORDERSTYLE (or borderStyle): Sets or gets the style set for the content border in the HTML Application (HTA) window. Type: String (e.g., "normal", "complex").
  • CAPTION (or caption): Sets or gets a Boolean value that indicates whether the window is set to display a title bar or a caption. Type: Boolean (yes/no).
  • CONTEXTMENU (or contextMenu): Sets or gets a string value that indicates whether the context menu is displayed when the right mouse button is clicked. Type: String (yes/no).
  • ICON (or icon): Sets or gets the name and location of the icon specified in the HTML Application (HTA). Type: String (path to .ico file).
  • INNERBORDER (or innerBorder): Sets or gets a string value that indicates whether the inside 3-D border is displayed. Type: String (yes/no).
  • MAXIMIZEBUTTON (or maximizeButton): Sets or gets a Boolean value that indicates whether a Maximize button is displayed in the title bar. Type: Boolean (yes/no).
  • MINIMIZEBUTTON (or minimizeButton): Sets or gets a Boolean value that indicates whether a Minimize button is displayed in the title bar. Type: Boolean (yes/no).
  • NAVIGABLE (or navigable): Sets or gets a string value that indicates whether linked documents are loaded in the main HTA window or in a new browser window. Type: String (yes/no).
  • SCROLL (or scroll): Sets or gets a string value that indicates whether the scroll bars are displayed. Type: String (yes/no/auto).
  • SCROLLFLAT (or scrollFlat): Sets or gets a string value that indicates whether the scroll bar is 3-D or flat. Type: String (yes/no).
  • SELECTION (or selection): Sets or gets a string value that indicates whether the content can be selected with the mouse or keyboard. Type: String (yes/no).
  • SHOWINTASKBAR (or showInTaskBar): Sets or gets a value that indicates whether the HTML Application (HTA) is displayed in the Windows taskbar. Type: Boolean (yes/no).
  • SINGLEINSTANCE (or singleInstance): Sets or gets a value that indicates whether only one instance of the specified HTML Application (HTA) can run at a time. Type: Boolean (yes/no).
  • SYSMENU (or sysMenu): Sets or gets a Boolean value that indicates whether a system menu is displayed in the HTML Application (HTA). Type: Boolean (yes/no).
  • VERSION (or version): Sets or gets the version number of the HTML Application (HTA). Type: String.
  • WINDOWSTATE (or windowState): Sets or gets the initial size of the HTA window. Type: String (e.g., "normal", "minimize", "maximize").

Additionally, the tag often includes an ID attribute (e.g., id="htaApp") for scripting reference, though it's not strictly HTA-specific. Runtime properties like commandLine (gets the launch arguments) are derived at execution and not stored in the file.

Here are two direct download links to sample .HTA files from public repositories (these are harmless examples used for testing/demonstration):

3. Ghost blog embedded HTML JavaScript for drag-and-drop .HTA file dump

Assuming "ghost blog embedded" refers to a simple, embeddable HTML snippet (e.g., for a Ghost blogging platform or similar), here is an HTML page with embedded JavaScript. It allows users to drag and drop a .HTA file, reads it as text using FileReader, parses the HTML using DOMParser to find the <hta:application> tag (case-insensitive), extracts all attributes from the list above, and dumps them to the screen. Embed this in a blog post as an HTML block.

HTA Properties Dumper
Drag and drop a .HTA file here

4. Python class for .HTA file handling

Here is a Python class using the built-in html.parser module to parse the .HTA file, extract the properties from the <hta:application> tag, print them to console, and support writing modified properties back to a new file.

from html.parser import HTMLParser
import os

class HTAParser(HTMLParser):
    def __init__(self, filepath):
        super().__init__()
        self.filepath = filepath
        self.properties = {}
        self.in_hta = False
        self.hta_content = ""
        self.original_content = ""
        self.load_file()

    def load_file(self):
        with open(self.filepath, 'r', encoding='utf-8') as f:
            self.original_content = f.read()
        self.feed(self.original_content)

    def handle_starttag(self, tag, attrs):
        if tag.lower() == 'hta:application':
            self.in_hta = True
            attrs_dict = dict(attrs)
            for prop in [
                'applicationname', 'border', 'borderstyle', 'caption', 'contextmenu', 'icon',
                'innerborder', 'maximizebutton', 'minimizebutton', 'navigable', 'scroll',
                'scrollflat', 'selection', 'showintaskbar', 'singleinstance', 'sysmenu',
                'version', 'windowstate', 'id'
            ]:
                self.properties[prop] = attrs_dict.get(prop.lower(), 'Not set')

    def handle_endtag(self, tag):
        if tag.lower() == 'hta:application':
            self.in_hta = False

    def print_properties(self):
        print("Extracted HTA Properties:")
        for prop, value in self.properties.items():
            print(f"{prop}: {value}")

    def set_property(self, prop, value):
        if prop.lower() in [p.lower() for p in self.properties]:
            self.properties[prop.lower()] = value

    def write_file(self, output_path):
        # Simple replace; assumes single <hta:application> tag
        updated_tag = '<hta:application'
        for prop, value in self.properties.items():
            if value != 'Not set':
                updated_tag += f' {prop}="{value}"'
        updated_tag += '>'
        # Find and replace the tag in original content
        import re
        updated_content = re.sub(r'<hta:application[^>]*>', updated_tag, self.original_content, flags=re.IGNORECASE)
        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(updated_content)
        print(f"Written updated HTA to {output_path}")

# Example usage:
# parser = HTAParser('example.hta')
# parser.print_properties()
# parser.set_property('applicationname', 'NewApp')
# parser.write_file('modified.hta')

5. Java class for .HTA file handling

Here is a Java class using org.jsoup (assume it's available or add dependency) to parse the .HTA file, extract/print properties, and write modifications.

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class HTAParser {
    private String filepath;
    private Map<String, String> properties = new HashMap<>();
    private String originalContent;

    public HTAParser(String filepath) {
        this.filepath = filepath;
        loadFile();
    }

    private void loadFile() {
        try {
            originalContent = new String(Files.readAllBytes(Paths.get(filepath)));
            Document doc = Jsoup.parse(originalContent);
            Element htaTag = doc.select("hta\\:application").first();
            if (htaTag != null) {
                String[] propList = {
                    "applicationname", "border", "borderstyle", "caption", "contextmenu", "icon",
                    "innerborder", "maximizebutton", "minimizebutton", "navigable", "scroll",
                    "scrollflat", "selection", "showintaskbar", "singleinstance", "sysmenu",
                    "version", "windowstate", "id"
                };
                for (String prop : propList) {
                    properties.put(prop, htaTag.attr(prop).isEmpty() ? "Not set" : htaTag.attr(prop));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void printProperties() {
        System.out.println("Extracted HTA Properties:");
        properties.forEach((prop, value) -> System.out.println(prop + ": " + value));
    }

    public void setProperty(String prop, String value) {
        if (properties.containsKey(prop.toLowerCase())) {
            properties.put(prop.toLowerCase(), value);
        }
    }

    public void writeFile(String outputPath) {
        try {
            Document doc = Jsoup.parse(originalContent);
            Element htaTag = doc.select("hta\\:application").first();
            if (htaTag != null) {
                properties.forEach(htaTag::attr);
                Files.write(Paths.get(outputPath), doc.outerHtml().getBytes());
                System.out.println("Written updated HTA to " + outputPath);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // Example usage:
    // public static void main(String[] args) {
    //     HTAParser parser = new HTAParser("example.hta");
    //     parser.printProperties();
    //     parser.setProperty("applicationname", "NewApp");
    //     parser.writeFile("modified.hta");
    // }
}

6. JavaScript class for .HTA file handling

Here is a Node.js JavaScript class using fs for file I/O and jsdom (assume installed via npm) to parse, extract/print properties, and write modifications.

const fs = require('fs');
const { JSDOM } = require('jsdom');

class HTAParser {
    constructor(filepath) {
        this.filepath = filepath;
        this.properties = {};
        this.originalContent = '';
        this.loadFile();
    }

    loadFile() {
        this.originalContent = fs.readFileSync(this.filepath, 'utf-8');
        const dom = new JSDOM(this.originalContent);
        const htaTag = dom.window.document.querySelector('hta\\:application');
        if (htaTag) {
            const propList = [
                'applicationname', 'border', 'borderstyle', 'caption', 'contextmenu', 'icon',
                'innerborder', 'maximizebutton', 'minimizebutton', 'navigable', 'scroll',
                'scrollflat', 'selection', 'showintaskbar', 'singleinstance', 'sysmenu',
                'version', 'windowstate', 'id'
            ];
            propList.forEach(prop => {
                this.properties[prop] = htaTag.getAttribute(prop) || 'Not set';
            });
        }
    }

    printProperties() {
        console.log('Extracted HTA Properties:');
        Object.entries(this.properties).forEach(([prop, value]) => {
            console.log(`${prop}: ${value}`);
        });
    }

    setProperty(prop, value) {
        if (this.properties.hasOwnProperty(prop.toLowerCase())) {
            this.properties[prop.toLowerCase()] = value;
        }
    }

    writeFile(outputPath) {
        const dom = new JSDOM(this.originalContent);
        const htaTag = dom.window.document.querySelector('hta\\:application');
        if (htaTag) {
            Object.entries(this.properties).forEach(([prop, value]) => {
                if (value !== 'Not set') {
                    htaTag.setAttribute(prop, value);
                }
            });
            fs.writeFileSync(outputPath, dom.serialize());
            console.log(`Written updated HTA to ${outputPath}`);
        }
    }
}

// Example usage:
// const parser = new HTAParser('example.hta');
// parser.printProperties();
// parser.setProperty('applicationname', 'NewApp');
// parser.writeFile('modified.hta');

7. C class for .HTA file handling

Here is a C program (compiled as a class-like struct) using standard libraries to read the file, manually parse for the <hta:application> tag (simple string search, not full HTML parser), extract/print attributes, and write modifications. Note: Parsing is basic and assumes well-formed input.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_PROP_LEN 50
#define MAX_VALUE_LEN 256
#define NUM_PROPS 19

typedef struct {
    char *filepath;
    char *properties[NUM_PROPS][2]; // prop name, value
    char *originalContent;
    size_t contentLen;
} HTAParser;

void initProperties(HTAParser *parser) {
    const char *propList[NUM_PROPS] = {
        "applicationname", "border", "borderstyle", "caption", "contextmenu", "icon",
        "innerborder", "maximizebutton", "minimizebutton", "navigable", "scroll",
        "scrollflat", "selection", "showintaskbar", "singleinstance", "sysmenu",
        "version", "windowstate", "id"
    };
    for (int i = 0; i < NUM_PROPS; i++) {
        parser->properties[i][0] = strdup(propList[i]);
        parser->properties[i][1] = strdup("Not set");
    }
}

void loadFile(HTAParser *parser) {
    FILE *file = fopen(parser->filepath, "r");
    if (!file) {
        perror("Failed to open file");
        return;
    }
    fseek(file, 0, SEEK_END);
    parser->contentLen = ftell(file);
    fseek(file, 0, SEEK_SET);
    parser->originalContent = malloc(parser->contentLen + 1);
    fread(parser->originalContent, 1, parser->contentLen, file);
    parser->originalContent[parser->contentLen] = '\0';
    fclose(file);

    // Basic parse: find <hta:application ...>
    char *start = strcasestr(parser->originalContent, "<hta:application");
    if (start) {
        char *end = strchr(start, '>');
        if (end) {
            char tagContent[4096];
            strncpy(tagContent, start + 16, end - start - 16); // Skip <hta:application
            tagContent[end - start - 16] = '\0';
            // Parse attributes
            char *token = strtok(tagContent, " ");
            while (token) {
                char *eq = strchr(token, '=');
                if (eq) {
                    *eq = '\0';
                    char *prop = token;
                    char *value = eq + 1;
                    if (*value == '"') value++;
                    if (value[strlen(value) - 1] == '"') value[strlen(value) - 1] = '\0';
                    for (int i = 0; i < NUM_PROPS; i++) {
                        if (strcasecmp(parser->properties[i][0], prop) == 0) {
                            free(parser->properties[i][1]);
                            parser->properties[i][1] = strdup(value);
                            break;
                        }
                    }
                }
                token = strtok(NULL, " ");
            }
        }
    }
}

void printProperties(HTAParser *parser) {
    printf("Extracted HTA Properties:\n");
    for (int i = 0; i < NUM_PROPS; i++) {
        printf("%s: %s\n", parser->properties[i][0], parser->properties[i][1]);
    }
}

void setProperty(HTAParser *parser, const char *prop, const char *value) {
    for (int i = 0; i < NUM_PROPS; i++) {
        if (strcasecmp(parser->properties[i][0], prop) == 0) {
            free(parser->properties[i][1]);
            parser->properties[i][1] = strdup(value);
            break;
        }
    }
}

void writeFile(HTAParser *parser, const char *outputPath) {
    // Rebuild tag
    char newTag[4096] = "<hta:application";
    for (int i = 0; i < NUM_PROPS; i++) {
        if (strcmp(parser->properties[i][1], "Not set") != 0) {
            strcat(newTag, " ");
            strcat(newTag, parser->properties[i][0]);
            strcat(newTag, "=\"");
            strcat(newTag, parser->properties[i][1]);
            strcat(newTag, "\"");
        }
    }
    strcat(newTag, ">");

    // Replace in content
    char *newContent = malloc(parser->contentLen + 1024);
    char *start = strcasestr(parser->originalContent, "<hta:application");
    if (start) {
        char *end = strchr(start, '>');
        if (end) {
            strncpy(newContent, parser->originalContent, start - parser->originalContent);
            newContent[start - parser->originalContent] = '\0';
            strcat(newContent, newTag);
            strcat(newContent, end + 1);
        } else {
            strcpy(newContent, parser->originalContent);
        }
    } else {
        strcpy(newContent, parser->originalContent);
    }

    FILE *out = fopen(outputPath, "w");
    if (out) {
        fwrite(newContent, 1, strlen(newContent), out);
        fclose(out);
        printf("Written updated HTA to %s\n", outputPath);
    }
    free(newContent);
}

void freeParser(HTAParser *parser) {
    for (int i = 0; i < NUM_PROPS; i++) {
        free(parser->properties[i][0]);
        free(parser->properties[i][1]);
    }
    free(parser->originalContent);
    free(parser->filepath);
}

// Example usage:
// int main() {
//     HTAParser parser;
//     parser.filepath = strdup("example.hta");
//     initProperties(&parser);
//     loadFile(&parser);
//     printProperties(&parser);
//     setProperty(&parser, "applicationname", "NewApp");
//     writeFile(&parser, "modified.hta");
//     freeParser(&parser);
//     return 0;
// }