Skip to content

QWK.NET ‐ QWKE Observations

Agent 57951 edited this page Jan 19, 2026 · 2 revisions

QWKE Observations

QWKE (QWK Extended) is an extension to the QWK format that adds enhanced features for offline mail readers and BBS doors. This page covers QWKE-specific files, long headers, and common real-world variations.

Purpose of QWKE Extensions

QWKE was developed to address limitations in the original QWK format:

  • Extended header fields - TO, FROM, and SUBJECT fields can exceed the 25-character QWK limit
  • Reader configuration - BBS can send preferences and filtering rules to offline readers
  • File attachments - Support for file uploads and downloads
  • Conference management - Subscribe/unsubscribe commands for conferences
  • Backward compatibility - QWKE packets remain readable by classic QWK readers

QWKE packets are identified by the presence of TOREADER.EXT or TODOOR.EXT files, though packets may mix classic QWK and QWKE features.

TOREADER.EXT

Purpose: Commands sent from the BBS to the offline reader.

Location: Root of QWK archive (same level as CONTROL.DAT)

Format: Plain text file, one command per line

Common Commands:

  • AREA <conference-number> - Select conference for area-specific filtering
  • KEYWORD <words> - Filter messages by keywords (space-separated list)
  • TWIT <usernames> - Block messages from specified users (space-separated list)
  • RESET - Reset read pointers (no parameters)

Example:

AREA 5
KEYWORD programming csharp dotnet
TWIT spammer1 spammer2
RESET

QWK.NET Handling:

  • Parses commands into structured ToReaderCommand objects
  • Preserves unknown commands verbatim (maintains RawLine property)
  • Skips empty or whitespace-only lines
  • Uses CP437 encoding for all text
  • Handles both Windows (CR+LF) and Unix (LF) line endings

Common Quirks:

  • Case variations - Command types may be uppercase, lowercase, or mixed case
  • Extra whitespace - Multiple spaces between command type and parameters
  • Unknown commands - Vendor-specific or custom commands not in specification
  • Missing parameters - Some commands may have empty parameter strings

TODOOR.EXT

Purpose: Commands sent from the offline reader to the BBS door.

Location: Root of QWK archive in REP (reply) packets

Format: Plain text file, one command per line

Common Commands:

  • ATTACH <filename> - Upload file attachment with message
  • REQUEST <filename> - Request file download from BBS
  • ADD <conference-number> - Subscribe to conference
  • DROP <conference-number> - Unsubscribe from conference

Example:

ATTACH screenshot.png
REQUEST latest.zip
ADD 10
DROP 5

QWK.NET Handling:

  • Parses commands into structured ToDoorCommand objects
  • Preserves unknown commands verbatim (maintains RawLine property)
  • Skips empty or whitespace-only lines
  • Uses CP437 encoding for all text
  • Handles both Windows (CR+LF) and Unix (LF) line endings

Common Quirks:

  • File path variations - Filenames may include paths, spaces, or special characters
  • Multiple attachments - Multiple ATTACH commands for one message
  • Case sensitivity - Command types and filenames may vary in case
  • Custom commands - Vendor-specific extensions beyond standard commands

Long Headers

QWKE allows TO, FROM, and SUBJECT fields to exceed the 25-character limit of standard QWK headers by using kludge lines at the beginning of message bodies.

How Long Headers Work

Standard QWK Limitation:

  • TO field: 25 characters (bytes 21-45 in header)
  • FROM field: 25 characters (bytes 46-70 in header)
  • SUBJECT field: 25 characters (bytes 71-95 in header)

QWKE Solution: When a field exceeds 25 characters:

  1. Header field is truncated to 25 characters (space-padded)
  2. Full value is placed as a kludge line at the start of the message body
  3. Format: To: extended recipient name (with colon separator)

Example:

Standard QWK header:

TO: "John Doe" <john.doe@exam
FROM: "Jane Smith" <jane.smith@ex
SUBJECT: Re: Very long subject line that

QWKE with long headers:

Header (truncated):
TO: "John Doe" <john.doe@exam
FROM: "Jane Smith" <jane.smith@ex
SUBJECT: Re: Very long subject line that

Body (with kludges):
To: "John Doe" <john.doe@example.com>
From: "Jane Smith" <jane.smith@example.com>
Subject: Re: Very long subject line that exceeds 25 characters

[Message body continues...]

Kludge Line Format

Structure:

  • Key: To, From, or Subject (case-insensitive)
  • Separator: Colon (:) followed by space
  • Value: Extended field content
  • Terminator: 0xE3 (QWK newline) or ASCII CR (13)

QWK.NET Handling:

  • Extracts kludges from message body during parsing
  • Stores kludges in Message.Kludges collection
  • Provides QwkeLongHeaderParser to extract extended headers
  • Case-insensitive key matching (To, TO, to all match)
  • Preserves raw kludge lines for round-trip fidelity

Differences from Standard QWK

Standard QWK:

  • Fixed 25-character limits enforced
  • No kludge support
  • Headers are complete in 128-byte record

QWKE:

  • 25-character header fields may be truncated
  • Kludge lines provide extended values
  • Headers and body work together for complete information
  • QWKE-aware readers use kludges, classic readers see truncated headers

Common Quirks and Deviations

Missing Extension Files

Issue: Packet may have QWKE features (long headers) but no TOREADER.EXT or TODOOR.EXT files.

Causes:

  • Partial QWKE implementation
  • Files omitted during packet creation
  • Archive extraction errors

QWK.NET Handling:

  • Missing extension files are not errors
  • Long headers still detected and parsed from message kludges
  • Packet treated as QWKE if long headers are present

Mixed QWK/QWKE Behaviour

Issue: Packet mixes classic QWK and QWKE features.

Examples:

  • Some messages have long headers, others don't
  • TOREADER.EXT present but no long headers in messages
  • Long headers present but no extension files

QWK.NET Handling:

  • Handles mixed behaviour gracefully
  • Each message parsed independently
  • Extension files parsed if present, ignored if absent

Kludge Line Variations

Common Variations:

  • Case differences - To:, TO:, to: all accepted
  • Whitespace - Extra spaces around colon or in value
  • Terminators - 0xE3 (QWK) or CR (QWKE) both accepted
  • Missing colons - Some implementations omit colon separator
  • Multiple values - Duplicate kludges (first one used)

QWK.NET Handling:

  • Case-insensitive key matching
  • Whitespace preserved in values
  • Both terminator types handled
  • Colon separator required for parsing
  • First matching kludge used if duplicates exist

Unknown Commands

Issue: Extension files contain commands not in the QWKE specification.

Causes:

  • Vendor-specific extensions
  • Custom BBS features
  • Future specification additions

QWK.NET Handling:

  • Unknown commands preserved verbatim
  • RawLine property contains original text
  • CommandType extracted from first word
  • Parameters contains remainder of line
  • No interpretation or validation of unknown commands

Line Ending Variations

Issue: Extension files may use different line endings.

Variations:

  • Windows: CR+LF (\r\n)
  • Unix: LF (\n)
  • Classic Mac: CR (\r)
  • Mixed line endings in same file

QWK.NET Handling:

  • Handles CR+LF and LF automatically
  • CR-only handled as line terminator
  • Mixed endings processed correctly
  • Original line endings preserved in RawLine

Encoding Issues

Issue: Extension files may contain extended ASCII characters.

Common Cases:

  • Accented characters in usernames
  • Special characters in filenames
  • Box-drawing characters in command output

QWK.NET Handling:

  • Uses CP437 encoding for all extension files
  • Extended ASCII characters preserved correctly
  • See Encoding and CP437 for details

How QWK.NET Handles QWKE Features

Parsing Strategy

Extension Files:

  • Parsed when present in archive
  • Missing files are not errors
  • Commands stored as structured objects
  • Raw lines preserved for fidelity

Long Headers:

  • Extracted during message body parsing
  • Stored in Message.Kludges collection
  • Accessible via QwkeLongHeaderParser
  • Original kludge lines preserved in RawLine

Backward Compatibility:

  • Classic QWK packets work without QWKE support
  • QWKE features detected automatically
  • No configuration required

Preservation

Byte Fidelity:

  • Raw command lines preserved in RawLine properties
  • Kludge lines preserved exactly as written
  • Encoding maintained (CP437)
  • Line endings preserved in raw text

Round-Trip Support:

  • QWKE → REP → QWK preserves all QWKE features
  • Extension files regenerated with original commands
  • Long headers written back as kludges
  • Unknown commands preserved verbatim

Validation

Extension Files:

  • No structural validation (files are optional)
  • Unknown commands accepted without warnings
  • Empty files are valid (no commands)

Long Headers:

  • Kludge parsing is permissive
  • Invalid kludge format doesn't prevent message parsing
  • Missing kludges don't cause errors
  • See Validation Modes for validation behaviour

When to Expect Warnings

Normal Behaviour (No Warnings)

  • Missing TOREADER.EXT or TODOOR.EXT files
  • Empty extension files
  • Unknown commands in extension files
  • Messages without long headers
  • Mixed QWK/QWKE packets

Potential Issues

  • Malformed kludge lines - May not be parsed correctly (no error, just ignored)
  • Encoding problems - Extended ASCII may display incorrectly if wrong encoding used
  • Line ending issues - Rare, but mixed endings may cause parsing problems

See Validation Modes for how validation modes handle QWKE-specific issues.

Best Practices

Reading QWKE Packets

  • Check for extension files - Use OptionalFiles.HasFile() to detect QWKE features
  • Extract long headers - Use QwkeLongHeaderParser for extended header fields
  • Preserve raw data - Access RawLine properties when byte fidelity is critical

Writing QWKE Packets

  • Generate extension files - Create TOREADER.EXT or TODOOR.EXT when needed
  • Use long headers - Add kludge lines for fields exceeding 25 characters
  • Preserve unknown commands - Include RawLine when regenerating extension files

Handling Variations

  • Case-insensitive matching - Don't rely on exact case for command types or kludge keys
  • Unknown commands - Preserve verbatim, don't attempt interpretation
  • Mixed packets - Handle both QWK and QWKE features in same packet

Further Reading

Clone this wiki locally