Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions bin/plugins/checkPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,56 @@ log4js.configure({
'Translation files help with Etherpad accessibility.');
}

// Check template files for absolute `/static/plugins/...` asset paths.
// Those break any Etherpad instance hosted behind a reverse proxy at a
// sub-path (e.g. https://example.com/etherpad/pad) because the browser
// resolves them against the domain root instead of the proxy prefix.
// See #5203, and ep_embedmedia#4 for the original fix this check is modelled on.
//
// Autofix only rewrites paths in `templates/` (rendered under `/p/<pad>/...`
// where `../static/plugins/...` is correct). Files under `static/` are
// served from `/static/plugins/<plugin>/static/...` and need a different
// relative prefix that depends on the file's depth, so we only warn.
const STATIC_ABS = /(?<![./:\w])\/static\/plugins\//g;
const scanDir = async (dir: 'templates' | 'static') => {
const abs = `${pluginPath}/${dir}`;
if (!files.includes(dir)) return;
const scanFiles: string[] = [];
const walk = async (d: string) => {
for (const entry of await fsp.readdir(d, {withFileTypes: true})) {
const full = `${d}/${entry.name}`;
if (entry.isDirectory()) {
if (entry.name === 'node_modules' || entry.name === '.git') continue;
await walk(full);
} else if (/\.(ejs|html)$/.test(entry.name)) {
scanFiles.push(full);
}
}
};
await walk(abs);
for (const fp of scanFiles) {
const src = await fsp.readFile(fp, 'utf8');
if (!STATIC_ABS.test(src)) continue;
STATIC_ABS.lastIndex = 0;
const rel = path.relative(pluginPath, fp);
if (dir === 'templates') {
logger.warn(`${rel} contains absolute '/static/plugins/...' asset paths; ` +
'these break reverse-proxied Etherpad deployments. Use ' +
"'../static/plugins/...' instead.");
if (autoFix) {
logger.info(`Autofixing absolute /static/plugins/ paths in ${rel}`);
await fsp.writeFile(fp, src.replace(STATIC_ABS, '../static/plugins/'));
}
} else {
logger.warn(`${rel} contains absolute '/static/plugins/...' asset paths; ` +
'these break reverse-proxied Etherpad deployments. Use a path ' +
"relative to this file's location under 'static/' (no leading '/').");
}
}
};
await scanDir('templates');
await scanDir('static');


if (files.includes('.ep_initialized')) {
logger.warn(
Expand Down
Loading