Hobbes OS/2 Archive - v1.03 =========================== A flat-file PHP file sharing archive in the style of the original Hobbes OS/2 archive at hobbes.nmsu.edu. No database required. REQUIREMENTS ------------ - PHP 8.1+ (PHP 8.4 recommended) - Apache 2.4 with mod_rewrite enabled - PHP-FPM (shared hosting compatible) - Writable data/ directory INSTALLATION ------------ 1. Upload all files to your web root (htdocs/). 2. Ensure the data/ directory and all its subdirectories are writable by the web server. On most shared hosts: chmod -R 755 data/ 3. Visit http://yoursite.com/setup to create the admin account and seed the default category tree. The setup page is only reachable until the first user exists. 4. Delete setup.php and check.php from the server once setup is done. check.php is a diagnostic tool that reveals server information. 5. Configure your site name, tagline, color theme, and landing page text via Admin > Settings, Admin > CSS, and Admin > Landing Page. 6. (Optional) Place files in data/pool/ via FTP for batch import through the Pool approval interface. DIRECTORY STRUCTURE ------------------- htdocs/ index.php Single entry point and URL router config.php Paths, file size limits, allowed extensions, role list, OS/2 UA patterns, default settings check.php Diagnostic page (delete after setup) setup.php First-run wizard (self-disables after use) php.ini Upload/memory limits for PHP-FPM environments readme.txt This file changelog.txt Version history hobbes.txt Example hobbes.txt format reference (large batch) pmmail.txt Example pmmail.txt format reference (single entry) includes/ functions.php Utility functions: roles, CSRF, flash messages, pagination, date formatting, filename safety, OS/2 UA detection, category tree helpers, category path building, file icon map storage.php Atomic JSON read/write (temp + rename, no flock). CRUD helpers for users, files, categories, invites, pool listing, session management auth.php Custom PHP session save handler (no flock), current_user(), require_role(), can() checks search.php Inverted keyword index: index, remove, query, rebuild functions markdown.php Minimal Markdown-to-HTML parser (no infinite loops) pages/ One PHP file per route home.php Landing page (renders Markdown landing content) browse.php Category browser with file listing and DL counts file.php File detail page with download count file/edit.php Edit metadata / move to category (editor+); Delete file from disk and archive (admin only) download.php File streaming with download counter increment search.php Keyword search results with DL counts upload.php Web file upload form (contributor+) pool.php Approval queue: web uploads + FTP single files + FTP folder batch import (editor+) login.php Authentication form logout.php Session teardown register.php Account creation (open or invite-only) invite.php Invite code generation and listing profile.php User dashboard (upload history, invite codes) setup.php First-run account and category seeding admin/ index.php Admin dashboard (stats, quick links) settings.php Site name, tagline, open registration toggle css.php Color palette editor (26 colors, 4 presets) users.php User list, role changes, account management categories.php Category tree editor (add, rename, nest, delete) landing.php Landing page Markdown content editor splash.php Splash screen content editor (non-OS/2 visitors) meta_merge.php Bulk metadata import from hobbes.txt / pmmail.txt bulk_delete.php Bulk file deletion by category (admin only) templates/ header.php HTML head, inline CSS from palette, navigation, category sidebar, flash message rendering footer.php Page footer data/ All persistent state (never served directly) .htaccess Denies all HTTP access to data/ and subdirs settings/ settings.json Site settings and CSS palette categories/ categories.json Category tree (id, name, slug, parent, desc) users/ One .json file per registered user files/ One .json metadata record per uploaded file uploads/ Uploaded files organized by category slug path e.g. uploads/multimedia/images/icons/file.zip pool/ FTP staging folder for pending imports invites/ One .json file per invite code index/ search.json Inverted search index (keyword -> [file ids]) sessions/ PHP session files (custom handler, no flock) merges/ Temporary meta-merge sessions (auto-expire 2h) USER ROLES ---------- guest Visitors with an OS/2 User-Agent string are automatically recognized as guests. Full browse and download access. No account required. contributor Registered user. Can upload files (pending editor approval) and generate invite codes for new users. editor Can approve or reject uploads, edit any file's metadata (title, description, author, etc.), move files between categories, import from the FTP pool, and run Meta Merge. admin Full access. All editor capabilities plus: user management, site settings, CSS theming, bulk file deletion, and single-file deletion from the edit page. ACCESS CONTROL -------------- - OS/2 browser detection is based on the HTTP User-Agent string. Recognized patterns: OS/2, Warp, WebExplorer, Warpzilla, Lynx.*OS, SPRY, PMX. All browsers sending one of these strings receive guest browse/download access without a login. - Non-OS/2 visitors see the landing page and splash screen only. They must create an account (via invite or open registration) to browse or download. - Open registration can be toggled in Admin > Settings. When off, new accounts require an invite code. - Invite codes are generated by contributors and above. Each code sets the invited user's starting role. - CSRF tokens protect all state-changing POST requests. FILE UPLOADS ------------ Web uploads (contributor+): Upload via /upload. File is stored in data/uploads/ and marked pending. An editor or admin must approve it in the Pool. FTP single file import (editor+): Drop a file into data/pool/ via FTP. It appears in /pool with a metadata entry form. Supply title, description, author, and category, then click Import. A companion .meta.json file can pre-fill the form: { "title": "...", "desc": "...", "author": "...", "version": "..." } FTP folder batch import (editor+): Drop an entire directory tree into data/pool/. The folder and its subdirectories are mapped to a new (or existing) category hierarchy. Each file gets a title derived from its filename; required fields default to "Unknown" and can be edited after import. META MERGE (/admin/meta-merge) ------------------------------- Bulk import of metadata from plain-text files. Upload a .txt file in either supported format; the system parses it, matches entries to existing archive files by category path and filename, and presents a review page before writing any changes. Supported formats: hobbes.txt format — one or more blocks separated by dashed lines: ---------------------------------------- DIR: pub/multimedia/images/icons FILE: 1700ico2.zip DESC: Multi-line description of the file. ---------------------------------------- pmmail.txt format — labelled key: value fields: Archive Filename: pmmail-3-25-00-1993.wpi Short Description: Email client for OS/2. Long Description: PMMail is an enhanced TCP/IP email client... Proposed directory for placement: /pub/os2/apps/internet/mail/reader/pmm Your name: Neil Waldhauer Program URL: http://pmmail.os2voice.org/ Operating System/Version: OS/2, ArcaOS and eComStation Additional requirements: See the readme. Path matching: the DIR / Proposed directory value is stripped of leading pub/ or hobbes/pub/ prefixes, then each path segment is slugified and compared against the category path of each file in the archive. Merge behavior: by default, only empty or "Unknown" fields are updated. Tick "Overwrite existing fields" to replace all values from the txt. Unmatched entries offer: filename-only suggestions, manual file-ID entry, or Skip. A before/after diff is shown for every matched entry before anything is written. BULK DELETE (/admin/bulk-delete) --------------------------------- Admin-only tool for removing multiple files from a category at once. - Select a category from the dropdown; the page lists all files in that category (approved and pending). - Per-page options: 25 / 50 / 100 / All. A warning is shown if "All" is selected and the category contains more than 250 files. - "Select all on this page" toggles checkboxes for the current page. - "Select ALL N files in this category (all pages)" marks every file in the category for deletion, regardless of current pagination. - A JavaScript confirmation dialog shows the count before deletion. - Deletion removes the physical file, the metadata JSON, and all search index entries. Empty category directories are cleaned up. Single-file delete is also available to admins from the file edit page (/file/edit/{id}) via the Danger Zone section at the bottom of the form. FILE EDITING / RECATEGORISATION -------------------------------- Editors and admins can edit any approved file's metadata from the file detail page (Edit Metadata button) or directly at /file/edit/{id}. When the category is changed, the physical file is moved on disk and stored_name is updated. If a file with the same name already exists in the target category, the move is blocked and an error is shown. DOWNLOAD COUNTER ---------------- Every download increments a counter stored in the file's metadata JSON. The current count is displayed: - In the browse listing (DLs column, visible to all users) - In search results (DLs column) - On the file detail page (Downloads row) SEARCH ------ Keyword search uses an inverted index stored in data/index/search.json. The index is updated automatically when files are approved or their metadata is edited. To rebuild the full index from scratch, use Admin > Rebuild Search Index. Search behavior: - Queries are tokenized (3+ char, non-stop words, case-insensitive) - AND search first (all keywords must match) - Falls back to OR search if AND yields no results CSS CUSTOMISATION ----------------- The entire color scheme is controlled from Admin > CSS. There are 26 individually configurable colors covering backgrounds, text, links, navigation, panels, buttons, table headers, and status colors. Four built-in presets: OS/2 Classic — grey desktop with navy accents (default) Dark Mode — dark grey with blue highlights Green Terminal — black background with green-on-black text Hobbes OG — deep blue, echoing the original hobbes.nmsu.edu All colors are stored in settings.json and applied inline at render time; no external CSS files are required. ATOMIC WRITES AND SHARED HOSTING --------------------------------- All JSON writes use a temp file + atomic rename() pattern. flock() is never used. This is safe on NFS mounts and shared hosting filesystems where flock() can block indefinitely. The same pattern is used for: - All storage.php writes (settings, users, files, categories, invites) - The custom PHP session save handler in auth.php - Meta merge session files in data/merges/ The .htaccess in data/ denies direct HTTP access to all data files. If your host does not support .htaccess, move the data/ directory above the web root and update DATA_DIR in config.php. ALLOWED FILE TYPES ------------------ OS/2 programs: zip wpi exe cmd bat inf rpm tar gz bz2 lzh arj 7z cab img iso Media: jpg jpeg png gif bmp ico wav mp3 mid midi au aiff avi mov mp4 mpeg mpg Documents: txt nfo diz doc html htm pdf rtf me Maximum upload size: 200 MB (configurable in config.php and php.ini).