Every Script in Matt’s Script Archive

Matt’s Script Archive contained 14 Perl CGI scripts, 2 C++ programs, and 2 third-party contributions. Here is the complete reference.

Archive Summary

  • Perl Scripts: 14
  • C++ Programs: 2
  • Third-Party: 2
  • Total: 18 programs
  • Active: 1995–2002
  • Site: worldwidemart.com/scripts/

Matt’s Script Archive (MSA) was one of the most influential sources of free CGI scripts on the early web. Distributed from worldwidemart.com/scripts/ beginning in 1995 and later mirrored at scriptarchive.com, the archive provided ready-to-use Perl programs that webmasters could install on any Unix server with a cgi-bin directory. Every script shipped as a .tar.gz or .zip archive containing the main Perl file, a README with configuration instructions, and in some cases sample HTML pages. By the late 1990s, FormMail alone had been downloaded more than two million times. The archive stopped receiving updates around 2002, but the scripts remain a landmark in web development history—they taught an entire generation how server-side programming worked.

This page documents every program that appeared in the archive: 14 original Perl scripts written by Matt Wright, 2 C++ ports of existing scripts, and 2 third-party contributions hosted alongside the core collection. For each entry you will find the version number, approximate release date, a technical summary, and a link to the full documentation page.

Complete Script Inventory

# Script Language Version Date Purpose
1 FormMail Perl 1.6 1997-05-02 Email form handler
2 Guestbook Perl 2.3.1 1995-10-29 Visitor guestbook
3 WWWBoard Perl 2.0A2.1 2000-01-07 Discussion forum
4 Counter Perl 1.1.1 1996-04-25 Graphical hit counter
5 Simple Search Perl 1.0 ~1997 Site search engine
6 TextCounter Perl 1.2 ~1996 Text-based hit counter
7 Random Link Perl 1.0 ~1996 Random URL redirector
8 Random Text Perl 1.0 ~1996 Random text display
9 TextClock Perl 1.0 ~1996 Date/time via SSI
10 HTTP Cookie Library Perl 2.1 1996-12-23 Cookie management library
11 Countdown Perl 1.0 ~1997 Date countdown timer
12 Free For All Links Perl 2.2 ~1996 Community link directory
13 Animation Perl 1.0 ~1996 Server-push animation
14 SSI Random Image Perl 1.2 ~1996 Random image via SSI
15 TextCounter C++ C++ 1.0 ~1996 C++ port of TextCounter
16 TextClock C++ C++ 1.0 ~1996 C++ port of TextClock
17 Credit Card Verifier Perl 1.0 ~1997 Luhn algorithm checker
18 Book ’em Dano Perl 1.0 ~1997 Perl utility collection

Rows 15–16 are C++ ports. Rows 17–18 are third-party contributions hosted alongside the main collection.

1. FormMail

Perl v1.6

FormMail was the most widely deployed CGI script in web history. It accepted any HTML form submission, parsed the fields, and emailed the results to a list of recipients via the server’s sendmail binary. Configuration happened entirely through hidden form fields—recipient, subject, redirect, required—which meant webmasters never had to edit the Perl source to add new forms.

The script read STDIN for POST data or $ENV{'QUERY_STRING'} for GET, decoded URL-encoded pairs, validated required fields, composed a MIME message, and piped it to /usr/lib/sendmail -t. A single configuration variable, @referers, was supposed to restrict which domains could use the script, but the check was trivially bypassed. FormMail v1.0 through 1.6 contained an email header injection flaw (CVE-2001-0357) that let attackers use any installation as an open mail relay. By 2002 it was the number-three attack vector tracked by SecurityFocus.

Despite the security issues, FormMail was historically significant because it gave millions of static HTML sites the ability to collect feedback without any server-side language knowledge. Modern equivalents include PHP’s mail() function, Formspree, Netlify Forms, or any backend API endpoint.

Read more →

2. Guestbook

Perl v2.3.1

The Guestbook script let visitors sign a public log on any website. Entries included the visitor’s name, email, URL, city, state, country, and a free-text comment. Each new entry was prepended to a flat HTML file so the most recent signatures appeared first. An optional email notification alerted the webmaster whenever someone signed.

Technically, the script wrote directly to an HTML file using Perl’s file I/O, inserting new entries at a marker comment. It used flock() for basic file locking to prevent concurrent-write corruption. Version 2.3.1 shipped as two files: guestbook.pl (the CGI handler) and addguest.pl (the form processor). Configuration variables at the top of each file controlled paths, colors, and field requirements.

Guestbooks were one of the defining features of personal home pages in the mid-1990s, predating comment systems. The concept evolved into WordPress comments, Disqus, and social media walls.

Read more →

3. WWWBoard

Perl v2.0A2.1

WWWBoard was a threaded discussion forum built entirely on flat HTML files. Each message was stored as its own .html file on disk, and the main board page listed topics with indented replies forming visible threads. Users could post new topics, reply to existing messages, and optionally follow threads via email notifications. An admin script (wwwadmin.pl) allowed the board operator to delete messages, ban words, and set a maximum message count.

The script generated static HTML pages on every post, reading a master index file and rewriting it with the new thread structure. This approach required no database, but it scaled poorly—boards with thousands of messages became slow because every post operation rewrote the index. File locking and sequential numbering ($meession) prevented most race conditions. Version 2.0 Alpha 2.1 (January 2000) was the final release, patching a password bypass in the admin interface.

WWWBoard is the ancestor of all forum software: phpBB, vBulletin, Discourse, and Reddit threads all descend from the same concept of nested discussion.

Read more →

4. Counter

Perl v1.1.1

Counter displayed a graphical hit counter on any web page. It read a count from a flat file, incremented it on each request, and dynamically composed a GIF image by stitching together individual digit images. The output was served as image/gif with a Content-type header, so webmasters embedded it using a standard <img> tag pointing at the CGI URL.

Each digit (0–9) was a separate GIF file in a configurable directory, allowing different visual styles—LED displays, odometer wheels, or simple block numbers. The script used flock() on the counter data file and supported multiple counters per site through a page identifier parameter. It could also be configured to ignore reloads from the same IP within a time window.

Graphical hit counters were ubiquitous on 1990s websites. They have been replaced by analytics platforms like Google Analytics, Plausible, and server-side log analysis tools.

Read more →

6. TextCounter

Perl v1.2

TextCounter was the lightweight alternative to the graphical Counter script. Instead of composing a GIF image, it output a plain text number via Server Side Includes (SSI). The webmaster placed an SSI <!--#exec cgi="..."--> directive in their HTML, and the server replaced it with the current visit count on each page load.

The script read a count from a flat file, incremented it, wrote the new value back, and printed the number to STDOUT. Because SSI directives are processed inline by the web server (Apache mod_include), the count appeared as part of the HTML without requiring an image or JavaScript. This made TextCounter faster and simpler than the graphical version, though it lacked visual flair.

Text-based counters disappeared along with SSI. Modern server-side rendering achieves the same result through template engines in PHP, Python, Ruby, or Node.js.

Read more →

8. Random Text

Perl v1.0

Random Text output a randomly selected text snippet via SSI, similar to how TextCounter worked. Webmasters stored quotes, tips, facts, or taglines in a flat file (one per line or separated by a delimiter), and the script picked one at random on each page load to display inline.

The implementation was minimal: read the data file into an array, pick a random element with $array[rand @array], and print it. Because SSI replaced the directive before the page reached the browser, the random text appeared as native HTML. The script supported HTML markup within entries, so bold text, links, or images could be included in the rotation.

The same functionality now lives in JavaScript widgets, WordPress plugins for rotating quotes, and server-side template logic in any modern framework.

Read more →

9. TextClock

Perl v1.0

TextClock displayed the current date and time on a web page through SSI. The output format was configurable—webmasters could choose from preset styles or define custom formats using tokens like %H, %M, %S for hours, minutes, and seconds. It supported both 12-hour and 24-hour clocks and could display the server’s local time or a specified timezone offset.

The script called Perl’s localtime() function, formatted the components according to configuration variables, and printed the result as plain text. Since it ran via SSI on every page request, the time was accurate to the moment of page generation (not real-time updating like a JavaScript clock). Some webmasters used it for “last updated” timestamps.

Client-side JavaScript’s Date object and the Intl.DateTimeFormat API have entirely replaced server-side date display for most use cases.

Read more →

11. Countdown

Perl v1.0

Countdown computed and displayed the time remaining until a specified future date. Output was rendered via SSI as plain text, for example: “32 days, 14 hours, 27 minutes until launch.” The target date was set in configuration variables at the top of the script, and the output format could be customized to show only days, or days and hours, or the full breakdown including seconds.

Internally the script converted both the target date and the current time to epoch seconds using Perl’s timelocal(), subtracted them, and divided the difference into days, hours, minutes, and seconds. If the target date had passed, it could either display zero or switch to counting up from the event.

Countdown timers are now implemented almost exclusively in client-side JavaScript, often with real-time updates. Libraries like countdown.js and CSS-based timers have replaced server-side solutions.

Read more →

13. Animation

Perl v1.0

The Animation script created rudimentary animations using Netscape’s server-push mechanism. It sent a series of images to the browser as a multipart/x-mixed-replace response, where each part replaced the previous one in the browser window. The effect was a flip-book animation that played without JavaScript, Java applets, or browser plugins.

The script set the Content-type to multipart/x-mixed-replace;boundary=ThisRandomString, then looped through a list of image files, sending each one with the appropriate MIME boundary and a configurable delay between frames (implemented via Perl’s sleep()). The animation could be set to loop indefinitely or stop after one pass.

Server-push animation was Netscape-specific and never worked reliably in Internet Explorer. It was superseded by animated GIFs, Flash, and ultimately CSS animations, the Web Animations API, and <video>/<canvas>.

Read more →

14. SSI Random Image

Perl v1.2

SSI Random Image displayed a randomly selected image on each page load. The script was called via an SSI directive and output an <img> HTML tag pointing to a randomly chosen file from a configured list of images. It was commonly used for rotating banner ads, random header graphics, or photo galleries.

The image list could be specified either as a configuration array in the script or by reading all files from a directory (filtering by extension). The script picked one with rand(), constructed the <img> tag with configurable width, height, alt, and optional link-wrap attributes, and printed it. Version 1.2 added support for linking each image to a different URL through a parallel array.

Random image rotation is now handled by JavaScript, CSS background cycling, or ad-serving platforms. Server-side implementations use template helpers in PHP, Django, Rails, or similar frameworks.

Read more →

C++ Programs

Matt Wright also distributed C++ versions of two SSI scripts. The C++ programs compiled to native binaries, which executed faster than Perl scripts on the same hardware. However, they required a C++ compiler on the server and were harder to configure, so they saw less adoption than their Perl counterparts.

15. TextCounter (C++)

C++ v1.0

The C++ version of TextCounter performed the same function as the Perl original: it incremented a counter stored in a flat file and printed the current count to STDOUT for SSI inclusion. The difference was performance—a compiled binary executed in microseconds without the overhead of loading the Perl interpreter, which mattered on heavily trafficked pages where SSI scripts ran on every request.

The source code was a single .cpp file that used standard C++ file I/O (fstream) and basic string formatting. Compilation required a simple g++ -o textcounter textcounter.cpp command, and the resulting binary was placed in the cgi-bin directory with execute permissions. Configuration was done through command-line arguments or by editing constants in the source before compiling.

Compiled CGI programs have been superseded by FastCGI, application servers, and interpreted languages with opcode caching (PHP OPcache, Python bytecode).

Read more →

16. TextClock (C++)

C++ v1.0

The C++ TextClock was a compiled equivalent of the Perl TextClock. It called the system time() and localtime() functions, formatted the result according to a configurable template, and printed it for SSI inclusion. The same format tokens as the Perl version were supported.

Like the C++ TextCounter, this program offered faster execution at the cost of requiring compilation. The source was a single .cpp file using <ctime> for time functions and <iostream> for output. Most webmasters stuck with the Perl version because shared hosting providers rarely offered compiler access.

Server-side date formatting is now a one-line operation in any language (date() in PHP, strftime in Python, Intl.DateTimeFormat in JavaScript).

Read more →

Third-Party Contributions

Two scripts written by other authors were hosted alongside the core collection on Matt’s Script Archive.

17. Credit Card Verifier

Perl v1.0 Third-Party

Written by an author known as Spider, the Credit Card Verifier implemented the Luhn algorithm (mod-10 check) to validate credit card numbers client-side form submissions before sending them to a payment processor. It accepted a card number, determined the card type (Visa, MasterCard, American Express, Discover) based on the prefix and length, and ran the checksum to verify that the number was mathematically valid.

The script parsed the card number from form input, stripped spaces and dashes, identified the issuer by matching the leading digits against known BIN ranges, and applied the Luhn formula. It returned either a validation success page or an error explaining what was wrong (bad checksum, unrecognized card type, wrong length). The script did not process payments or connect to any gateway—it was purely a format validator.

Luhn validation is now built into payment libraries (Stripe.js, Braintree), HTML5 pattern attributes, and server-side validation frameworks.

Read more →

18. Book ’em Dano

Perl v1.0 Third-Party

Book ’em Dano, written by Dan Oberlin, was a collection of Perl utility subroutines packaged as a library file. It provided common functions that CGI script authors needed but had to rewrite from scratch: form data parsing, HTML entity encoding, date formatting, file reading/writing, and basic string manipulation.

The library was distributed as a single .pl file that other scripts could include with require. Functions included &parse_form (similar to CGI.pm’s param()), &html_escape for encoding special characters, &read_file and &write_file for simplified file I/O, and &date_format for human-readable timestamps. It was designed as a lightweight alternative to the much larger CGI.pm module.

These utility functions are now standard library features in every web language: PHP’s htmlspecialchars(), Python’s html.escape(), Node.js template engines with auto-escaping.

Read more →

NMS Replacements

The Not Matt’s Scripts (NMS) project, started by the London Perl Mongers in 2001, produced security-audited, drop-in replacements for the most popular Matt’s Script Archive programs. NMS scripts were designed to be compatible with existing configurations while fixing the security vulnerabilities (especially the FormMail header injection flaw) that plagued the originals.

Original Script NMS Replacement NMS Version Key Fixes
FormMail 1.6 NMS FormMail 1.93 Header injection fix, taint mode, @postmaster
Guestbook 2.3.1 NMS Guestbook 1.22 Input sanitization, HTML encoding, spam prevention
WWWBoard 2.0A2.1 NMS WWWBoard 1.22 XSS prevention, secure admin password handling
Free For All Links 2.2 NMS Free For All Links 1.14 URL validation, anti-spam measures
Simple Search 1.0 NMS Simple Search 1.10 Path traversal fix, input validation
TextCounter 1.2 NMS TextCounter 1.10 File locking improvements, taint mode
Random Link 1.0 NMS Random Link 1.10 Input sanitization, header injection prevention
Random Text 1.0 NMS Random Text 1.10 HTML encoding, path validation
TextClock 1.0 NMS TextClock 1.10 Taint mode, input validation
SSI Random Image 1.2 NMS SSI Random Image 1.10 Path validation, output encoding
NMS Project: The complete NMS collection is available at nms-cgi.sourceforge.net. All NMS scripts run under Perl’s taint mode (-T) and pass use strict and use warnings.

Download All Scripts

The complete Matt’s Script Archive collection is available for download as a single package. This includes all 14 Perl scripts, both C++ programs, README files, sample HTML pages, and documentation.

Complete Archive Package

All scripts, documentation, and example files in one download. Includes original README files and configuration instructions.

Installation Basics

All Perl CGI scripts in the archive follow the same general installation procedure. These steps apply to any Unix/Linux server with Apache and Perl installed.

  1. Upload. Transfer the .pl file to your server’s cgi-bin directory using FTP or SCP. Upload in ASCII mode (not binary) to ensure line endings are correct for Unix.
  2. Set permissions. Make the script executable: chmod 755 script.pl. Data files that the script writes to need chmod 666 or chmod 777 for the directory.
  3. Configure. Open the script in a text editor and modify the configuration variables at the top. At minimum, set the path to Perl (#!/usr/bin/perl), your domain in @referers, and any output paths. Each script’s README lists every configurable variable.
  4. Test. Point your browser to https://yourdomain.com/cgi-bin/script.pl. If you see a 500 Internal Server Error, check the Apache error log (/var/log/httpd/error_log) for the Perl error message. Common issues: wrong Perl path on line 1, missing modules, or incorrect file permissions.
  5. Integrate. Add the script to your HTML pages. For form-based scripts (FormMail, Guestbook), set the form’s action attribute to the CGI URL. For SSI-based scripts (TextCounter, TextClock, Random Text), use <!--#exec cgi="/cgi-bin/script.pl"--> and ensure your server has SSI enabled (Options +Includes in Apache).

For detailed installation instructions, troubleshooting, and server configuration, see the Installation Help section.

Related Pages

Scripts Archive Index

Browse all scripts with download links, documentation, and working examples.

Script FAQ

Frequently asked questions for each script, covering installation, configuration, and common errors.

Download All Scripts

Get the complete archive in a single download. All Perl scripts, C++ programs, and documentation.

Installation Help

Step-by-step instructions for installing CGI scripts on Apache, Nginx, and other web servers.

Site History

The story of WorldWideMart.com and Matt’s Script Archive from 1995 to the present.

Community Add-ons

Third-party extensions, modifications, and utility scripts contributed by the MSA community.