Changelog
All notable changes to BlackSwan Upload File from URL to Web Server are documented here.
v2.4.0 — 2026-05-03
Fixed
- FTP folder navigation — folder names and breadcrumb segments were using inline
onclickattributes. Clicks landing on the embedded SVG icon instead of the text didn’t reliably bubble to the span’s handler in all browsers. Replaced withdata-ftpnavattributes +addEventListenerdelegation attached after eachinnerHTMLrender. Both the file table and the breadcrumb bar use this pattern.
Added
- FTP Download-to Folder — new “Download-to Folder” input in the FTP connection form. The entered subfolder is passed as
_folderto every “Copy to Server” (_a=ftp_copy) call, so remote files land in a specific directory on this server instead of always the root. Saved and restored vialocalStorage.
Changed
- Layout max-width widened from 700 px to 1000 px.
- Direct Upload bulk mode now hides the “Destination Filename” field (it is unused when uploading multiple URLs).
- Version bumped to 2.4.0.
v2.3.0 — 2026-05-03
Added
- FTP bulk actions — checkboxes on every row in the FTP Browser, with a select-all toggle in the table header. A bulk action bar (hidden until at least one item is checked) exposes two actions: Copy URLs (collects all checked web URLs, applies strip prefix, copies to clipboard) and Delete Selected (single confirm dialog → serial delete of all checked items → list reload).
- Direct Upload bulk mode — a “Bulk” toggle button next to the URL field switches between single-URL input and a multi-URL textarea. Each URL is downloaded sequentially via the existing
_a=fetchAJAX endpoint. Status updates per item (queued → spinner → ✓ size + clickable local URL / ✗ error message), an animated progress bar, and a “X / N done” counter. Bulk mode preference is persisted inlocalStorage. - Configurable FTP path strip-prefix — new “Strip Path Prefix” input in the FTP connection form. The entered prefix (e.g.
/www) is stripped from the left of every remote path before building the Copy URL, so/www/1/file.mp4becomeshttps://dl.example.com/1/file.mp4. Saved and restored vialocalStorage. - Numeric (octal) permissions — both the local file browser and the FTP browser now display permissions as
symbolic octal(e.g.-rwxr-xr-x 755). Hovering shows a human-readable tooltip (Owner: read write exec · Group: read exec · Others: read exec).- PHP
perms_sym_to_octal()converts symbolic FTP rawlist strings to octal. - PHP
perms_int_to_sym()convertsfileperms()integers to symbolic strings for the local browser.
- PHP
- Self-update from GitHub — “Update” button in the header nav triggers
_a=check_update, which queries the GitHub Releases API for the latest version. If a newer release is found, a confirmation dialog offers to run_a=do_update: the newupload.phpis downloaded, itsAPP_VERis verified, the current file is backed up asupload.php.bak, and the script is replaced in-place. - New AJAX endpoints:
_a=check_update,_a=do_update.
Changed
ftpRender()rewritten to support checkboxes, bulk bar, strip prefix, and octal permissions.ajax_ls()(local file browser) now returnsperms_octalandperms_symfields alongside existing item data.parse_ftp_rawlist()now returnsperms_octalper item.- Version bumped to 2.2.0.
v2.1.0 — 2026-05-02
Added
- FTP Browser tab — third tab in the form alongside “Direct Upload” and “MITM Relay”. Connect to any FTP, FTPS (TLS), or SFTP server and browse its file tree without leaving the page.
- Connection form — host, port (default 21), username, password, protocol selector (FTP / FTPS / SFTP), and an optional Web Base URL field. All credentials are posted per-request; no session storage.
- File tree view — columns for Name, Size, Modified (human-readable), and Permissions. Directories are clickable; a breadcrumb bar shows the current path with click-to-navigate segments.
_a=ftp_lsAJAX endpoint — lists a remote directory. FTP/FTPS uses PHP nativeftp_rawlist(); SFTP usescurl sftp://with libssh2. Returns items sorted directories-first._a=ftp_delAJAX endpoint — deletes a remote file or directory. FTP/FTPS viaftp_delete()/ftp_rmdir(); SFTP via thessh2PHP extension if available, otherwise returns a clear unsupported message._a=ftp_copyAJAX endpoint — pulls a remote file down to the local server usingcurlwith anftp://,ftps://, orsftp://URL. Returns the resulting local HTTP URL.- Copy Path button — copies the bare remote path (e.g.
/backups/db.sql.gz) to the clipboard. - Copy URL button — combines the optional Web Base URL with the remote path to produce a full HTTP URL (e.g.
https://dl.example.com/backups/db.sql.gz). Disabled when no base URL is set. - Copy to Server button — transfers the remote file to the directory where
upload.phplives; shows the resulting local URL in the activity log. - Activity log panel — scrollable, monospace, timestamped entries (connect, list, delete, copy) below the file tree. Includes a Clear button.
- SSL/TLS acceptance — FTPS skips peer/host verification via PHP stream context; SFTP and FTP-over-curl use
CURLOPT_SSL_VERIFYPEER=0/CURLOPT_SSL_VERIFYHOST=0. Self-signed and unknown certs are accepted. - localStorage persistence — host, port, username, protocol, and Web Base URL are saved and restored on every tab switch and page reload. Password is never persisted.
Changed
- Version bumped to 2.1.0.
v2.0.0 — 2026-04-30
Added
- MITM relay mode — new “MITM Relay” tab in the form. Provide a MITM server URL (another server running
upload.php), the source URL, and a filename. The current server POSTs_a=fetchto the MITM server, waits for it to download the file, then downloads from the MITM server directly. Optionally auto-deletes from MITM when done. _a=fetchAJAX endpoint — acceptsurl,_name,_folder; downloads the URL to this server; returns JSON{ok, url, path, size, name, folder}. Used by the MITM caller._a=del_by_nameAJAX endpoint — accepts_name,_folder; deletes a file by name; returns JSON{ok, msg}. Used for MITM cleanup.- CLI
--mitm=<URL>— MITM relay mode from the terminal;--mitm-keepto skip MITM cleanup. - Phosphor SVG icons — all emoji in buttons and modal headers replaced with inline Phosphor SVG paths via a
ph()helper function. Zero external requests; icons are embedded directly in the PHP file. - Mode tab switcher — “Direct Upload” and “MITM Relay” tabs above the form, with selection persisted in
localStorage. - Wider content area —
.mainmax-width increased from 600 px to 700 px.
Changed
- Font sizes bumped ~6 % across the board (base
16px→17px; all rem values scaled). - Version bumped to 2.0.0.
Notes
- No ZIP extraction or WordPress installer in MITM mode by design.
- Both servers (caller and relay) must run upload.php v2.0.0+.
v1.9.2 — 2026-04-30
Added
- Dark theme — GitHub-dark-style color palette (
#0d1117background,#161b22cards, orange#f0883eaccent). Replaces the previous light design. - Top-bar progress line — 3 px fixed line at the top of the page fills left-to-right during download. Replaces the old body-background gradient approach.
- ETA display — progress area now shows percentage, bytes transferred / total, elapsed time, and estimated time remaining.
- File browser popup — AJAX-powered modal (
Filesbutton in header) to navigate the server filesystem: list dirs/files with human-readable sizes and modification dates, copy HTTP URL per file, delete with confirmation dialog, multi-select checkboxes with bulk “Delete Selected” and “Copy Selected URLs”. - PHP Info modal —
PHP Infobutton in header opens a dark, curated info panel as a popup instead of navigating away. Fullphpinfo()still opens in a new tab. - Help / CLI guide popup —
? Helpbutton opens a modal with PHP CLI usage and all web endpoint references. - PHP CLI mode — run
php upload.php --url=... --name=... [--folder=...] [--extract] [--wpinstall] [--delete] [--help]directly from the terminal with a progress bar in the console. - iOS-style pill buttons — all buttons use
border-radius: 980pxwith filled, system-color backgrounds. - Minified CSS/JS — all inline styles and scripts are minified; HTML whitespace is compressed.
Changed
- Some UI elements and colors updated for better contrast and a more modern look.
- Version scheme changed to semver (
v1.9.0) across all files. - Header redesigned: compact sticky bar with logo left, nav buttons right.
- Footer redesigned: minimal single-line with author and GitHub links.
PHP Infoaction is now a popup modal;?info=1query param is no longer used.- Progress container is pre-rendered in the page; no longer injected into
h1via JS. human_timingrefactored intohuman_timing2(seconds)+human_timing(start)wrapper.
Security
- File browser uses PHP filesystem permissions as the access boundary; the script itself cannot be deleted via the browser.
v1.8.0
Added
- Inline SVG BlackSwan icon — favicon and header logo served as a single
data:image/svg+xml,…URI. No external fetches; renders on air-gapped servers. - Delete-File action — completion screen offers a “Delete File” button (
?delete_file=…). Secured withrealpath()+ scope check. - Output-buffer padding —
flush_buffers(true)emits a 4 KB HTML comment ~once per 8 seconds to defeat proxy buffering. set_time_limit(0)— removes the PHP execution time cap.
Changed
- Self-destruction and file-deletion exit screens carry inline CSS so they render correctly before page styles load.
- Header logo moved to a CSS class instead of a duplicated inline
data:URI.
Security
?delete_file=strictly path-scopes deletions to__DIR__and refuses to delete the script itself.
v1.7.0 (unreleased — superseded by v1.8.0)
Added
- iOS-style toggles for opt-in features (default OFF).
- Universal archive extraction toggle —
.zip,.tar,.tar.gz,.tgz,.gz. - WordPress installer as a separate explicit toggle.
- WordPress installer keeps only the latest default theme, wipes default plugins, writes
robots.txtblocking all crawlers. - Copy buttons on the completion screen for source and destination URL.
- Toast notification (“Copied to clipboard”).
- PHP Info panel (
?info=1) — curated two-column view. - Full
phpinfo()view (?phpinfo=1). - Mobile-responsive layout.
Changed
- Download engine rewritten on cURL with
CURLOPT_PROGRESSFUNCTION— replaces the old dualfopen/freadpath. - Progress UI throttled to ~5 fps.
- Destination URL built from
dirname($_SERVER['PHP_SELF']).
Fixed
- Path traversal hardening on destination folder and filename inputs.
- URL validation via
filter_var(... FILTER_VALIDATE_URL). - File handles closed on cURL error path.
human_filesize()returns"0 B"for zero-byte input.
v1.6.0
- Added
?delete_file=action to remove the just-uploaded file. - Added
?force=1switch to force the cURL download path. - Replaced externally-hosted PNG favicon with inline SVG
data:URI. - Periodic output padding during download to keep buffered proxies from holding the response.
v1.5.0
- Internal refactors and stability improvements.
v1.4.0
- Added WordPress-Ready mode: extract WordPress ZIP and move contents to root.
- Added Self-Destruct link to the finish screen.
v1.3.0
- Added Self-Destruct feature.
v1.2.0
- New features and stability improvements.
v0.8.0
- Compatibility with non-SSL servers and DirectAdmin hosting (cURL fallback).
v0.7.0
- Auto file-name filler from URL.
- Back-to-Root button.
v0.6.0
- Timer display: elapsed and total time.
v0.5.0
- Stability improvements for large files.
v0.4.0
- Fixed file-size detection error.
v0.3.0
- Initial styling and visual pass.
v0.2.0
- Real-time progress bar while uploading.
v0.1.0
- Initial release — 2020-11-15 (1399-08-25).