'use strict';
// Desktop used to HTML-escape message content before turning image URLs into
//
, so Ferry's Discord CDN query strings (?ex=&is=&hm=) became
// & and the media proxy requested a URL Discord has never signed. Mobile
// never escapes the URL, which is why the same photo showed there and not on
// desktop. These tests lock the decode + filename regexes the client now uses.
const assert = require('node:assert/strict');
const test = require('node:test');
const { sniffImageType } = require('../src/mediaProxy');
function decodeHtmlEntities(str) {
return str
.replace(/'/g, "'")
.replace(/"/g, '"')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/&/g, '&');
}
const IMAGE_RE = /\.(jpg|jpeg|png|gif|webp)(\?[^"'<>]*)?$/i;
const LOCAL_UPLOAD_RE = /^\/uploads\/(?:[\w\-]+\/)?[\w\-.]+\.(jpg|jpeg|png|gif|webp|svg)$/i;
const OLD_LOCAL_RE = /^\/uploads\/[\w\-]+\.(jpg|jpeg|png|gif|webp|svg)$/i;
test('HTML-escaped Discord CDN query strings decode back to a fetchable URL', () => {
const raw = 'https://cdn.discordapp.com/attachments/1178/8830/photo.png?ex=68b0&is=68af&hm=abcd&';
const escaped = raw.replace(/&/g, '&');
assert.notEqual(escaped, raw);
assert.equal(decodeHtmlEntities(escaped), raw);
assert.match(decodeHtmlEntities(escaped), IMAGE_RE);
// encodeURIComponent of the escaped form is what used to 404 upstream.
assert.match(encodeURIComponent(escaped), /amp%3B/);
assert.doesNotMatch(encodeURIComponent(raw), /amp%3B/);
});
test('local upload regex allows dots in the basename and one extra path segment', () => {
assert.match('/uploads/1725-aabbccdd.jpg', LOCAL_UPLOAD_RE);
assert.match('/uploads/photo.edit.jpg', LOCAL_UPLOAD_RE);
assert.match('/uploads/images/cat.webp', LOCAL_UPLOAD_RE);
assert.match('/uploads/stickers/wave.png', LOCAL_UPLOAD_RE);
assert.doesNotMatch('/uploads/photo.edit.jpg', OLD_LOCAL_RE);
});
test('sniffImageType recognises raster magic bytes when the CDN lies about Content-Type', () => {
assert.equal(sniffImageType(Buffer.from([0xFF, 0xD8, 0xFF, 0xE0, 0, 0, 0, 0, 0, 0, 0, 0])), 'image/jpeg');
assert.equal(sniffImageType(Buffer.from([0x89, 0x50, 0x4E, 0x47, 0, 0, 0, 0, 0, 0, 0, 0])), 'image/png');
assert.equal(sniffImageType(Buffer.from('GIF89a......')), 'image/gif');
assert.equal(sniffImageType(Buffer.from('RIFF....WEBP')), 'image/webp');
assert.equal(sniffImageType(Buffer.from('not an image!!')), null);
});