-
Notifications
You must be signed in to change notification settings - Fork 0
QWK.NET ‐ QWK Format Observations
Practical notes about real-world QWK packets and how QWK.NET handles common deviations from the specification. This page focuses on quirks observed in historical BBS packets rather than restating the full specification.
Historical QWK packets were created by diverse BBS software implementations over several decades. Whilst the QWK specification exists, real-world packets often deviate due to:
- Implementation differences - Various mail door software interpreted the spec differently
- Evolution over time - Formats evolved before standards were fully established
- Storage media issues - Corruption from floppy disks, tape backups, or incomplete transfers
- Vendor extensions - BBS-specific additions that became common practice
QWK.NET handles these variations gracefully whilst preserving byte fidelity where possible.
Specification: MM-DD-YY,HH:MM:SS (hyphen-delimited, 2-digit year)
Real-World Variations:
-
MM/DD/YY,HH:MM:SS- Slash delimiters (very common, ~40-60% of packets) -
MM-DD-YYYY,HH:MM:SS- 4-digit year with hyphens (uncommon) -
MM/DD/YYYY,HH:MM:SS- 4-digit year with slashes (rare, e.g., mvt2.qwk)
QWK.NET Handling:
- Auto-detects delimiter type (hyphen or slash)
- Supports both 2-digit and 4-digit years
- Applies Y2K heuristic for 2-digit years (00-49 → 2000s, 50-99 → 1900s)
- Validates 4-digit years within 1980-2099 range
Validation Warnings:
- Lenient/Salvage: Invalid date formats log warnings, date set to
DateTime.MinValue - Strict: Throws exception on unparseable dates
Common Cases:
- Empty Qmail menu file (line 8) - Often just whitespace or empty string
- Missing optional files (WELCOME, NEWS, GOODBYE) - Not all BBSes provide these
- Whitespace-only BBS city/phone fields - Some implementations left these blank
QWK.NET Handling:
- Strict Mode: Rejects empty required fields (throws exception)
- Lenient Mode: Warns but continues with empty strings
- Salvage Mode: Best-effort recovery with sensible defaults
Validation Warnings:
- Missing required field: Error in Strict, warning in Lenient/Salvage
- Empty BBS ID: Warning + "UNKNOWN" default in Lenient/Salvage
Issue: ConferenceCountMinusOne (line 11) may not match actual conference definitions.
Examples:
- Claims 5 conferences but defines 6 pairs
- Claims 10 conferences but defines 8 pairs
- Off-by-one errors from counting mistakes
QWK.NET Handling:
- Parses exactly the claimed number of conference pairs
- Validation reports mismatches
- Salvage mode recovers remaining lines as raw data
Validation Warnings:
- Conference count mismatch: Warning logged, parsed count used
Issue: Specification implies sequential conference numbers, but many packets have gaps.
Example:
0 - Main Board
1 - General
5 - Off-Topic ← Gap: no conferences 2, 3, 4
10 - Tech ← Gap: no conferences 6-9
QWK.NET Handling:
- Supports non-sequential conference numbers
- Validates message references against available conferences
- No requirement for sequential numbering
Validation Warnings:
- Message references non-existent conference: Warning logged
Specification Limits:
- Conference names: 13 characters (classic QWK)
- QWKE allows: 255 characters
Real-World Behaviour:
- BBS names may exceed 60 characters
- Conference names often exceed 13-character limit
- Phone numbers vary widely (international formats, extensions)
QWK.NET Handling:
- No arbitrary length limits enforced
- Preserves content as-is
- Full CP437 support for extended characters
Validation Warnings:
- None - length variations are accepted
Issue: Box-drawing characters, accents, or symbols in supposedly ASCII-only fields.
Examples:
- BBS name with box-drawing borders:
─══ StarLink BBS ══─ - Sysop name with accents:
José Rodriguez - Phone with symbols:
☎ 555-1212
QWK.NET Handling:
- Full CP437 encoding support for all text fields
- Preserves extended characters without conversion
- No UTF-8 normalisation
Validation Warnings:
- None - CP437 characters are expected and preserved
Specification: MM-DD-YY (8 characters, hyphens at positions 2 and 5)
Real-World Variations:
-
MM/DD/YY- Slash delimiters (common variant) -
MM-DD-YYYY- 4-digit year with hyphens -
MM/DD/YYYY- 4-digit year with slashes
QWK.NET Handling:
- Accepts all observed formats
- Delimiters must be consistent (both hyphens OR both slashes)
- Validates date structure for header detection
Validation Warnings:
- Invalid date format: Warning logged, date parsing may fail
- Inconsistent delimiters: Warning logged
Issue: Messages may have missing body blocks or truncated headers.
Common Causes:
- Incomplete file transfers
- Corrupted archives
- Software bugs in packet generation
QWK.NET Handling:
- Lenient/Salvage: Logs warnings for missing blocks, returns partial data
- Strict: Throws exception on structural errors
Validation Warnings:
- Missing body block: Warning logged, parsing continues
- Incomplete body block: Warning logged with byte count
Issue: Blocks that don't match expected header structure.
QWK.NET Handling:
- Validates header structure before parsing
- Checks critical fields: status byte, date delimiters, time colon, alive flag
- Skips invalid blocks in Lenient/Salvage modes
Validation Warnings:
- Invalid header structure: Warning logged with diagnostic details
- Block skipped: Warning indicates offset and reason
Issue: Index files use Microsoft Binary Format floats, which may have edge cases.
QWK.NET Handling:
- Handles zero values (four zero bytes)
- Validates record offsets are non-negative
- Checks offsets don't exceed MESSAGES.DAT file size
Validation Warnings:
- Negative record offset: Warning logged, entry skipped
- Offset exceeds file size: Warning logged, entry skipped in Lenient/Salvage
- File size not multiple of 4: Error in Strict, warning in Lenient/Salvage
Issue: Index entries may point to invalid locations or have incorrect counts.
QWK.NET Handling:
- Validates each entry against MESSAGES.DAT size
- Skips invalid entries in Lenient/Salvage modes
- Maintains sequential message numbering even when entries are skipped
Validation Warnings:
- Invalid index entry: Warning logged with entry number and reason
Issue: Some archive formats or BBS implementations use inconsistent case for filenames.
QWK.NET Handling:
- Case-insensitive file matching for all QWK files
-
CONTROL.DAT,control.dat, andControl.Datall match - Preserves original case when reading
Validation Warnings:
- None - case variations are handled automatically
Issue: Optional files (WELCOME, NEWS, GOODBYE, DOOR.ID) may be absent.
QWK.NET Handling:
- Optional files are truly optional
-
OptionalFiles.HasFile()returns false for missing files - No errors logged for missing optional files
Validation Warnings:
- None - missing optional files are expected
Date Format Issues:
- Packets using slash delimiters instead of hyphens (very common)
- 4-digit years in older packets (rare but valid)
Field Issues:
- Empty Qmail menu file (common)
- Missing optional files (expected)
- Whitespace-only fields (occasional)
Structural Issues:
- Conference count mismatches (occasional)
- Non-sequential conference numbers (common)
- Index entries pointing beyond file (rare, indicates corruption)
Message Issues:
- Truncated messages (rare, indicates corruption)
- Malformed headers (rare, indicates corruption)
In Lenient mode (recommended default), warnings are expected and normal for:
- Packets using slash-delimited dates
- Packets with empty optional fields
- Packets with non-sequential conference numbers
- Packets with extended ASCII characters
These warnings indicate format variations, not errors. The packet is still fully usable.
Warnings that suggest actual problems:
- Index entries pointing beyond file boundaries
- Missing required message body blocks
- Malformed header structures
- Negative record offsets
These may indicate corruption or software bugs. Consider using Salvage mode for recovery.
QWK.NET prioritises preserving original packet bytes:
- CP437 encoding - No UTF-8 conversion, extended characters preserved
- MSBIN floats - Exact byte representation maintained in index files
- 128-byte records - Space padding preserved exactly
- 0xE3 line terminators - QWK-specific newlines maintained
- Round-trip fidelity - QWK → REP → QWK preserves all bytes
Even when handling format variations, the library preserves the original data structure.
- Validation Modes - How Strict, Lenient, and Salvage modes handle these variations
- Troubleshooting - Solutions for common problems
- Encoding and CP437 - Details on character encoding handling
- Index Files (.NDX) - Index file structure and MSBIN format details