sync/src/camo.js
Calvin Montgomery 22a9acfc90 Support proxying chat images via camo
Camo: https://github.com/atmos/camo.  This has a couple advantages over
just allowing images to be dumped as-is:

  - Prevents mixed-content warnings by allowing the server to proxy HTTP
    images to an HTTPS camo instance
  - Protects users' privacy by not exposing their browser directly to
    the image host
  - Allows the camo proxy to intercept and reject bad image sources
    (URLs that are not actually images, gigapixel-sized images likely to
    DoS users' browsers, etc.)

Whitelisting specific domains is supported for cases where the source is
known to be trustworthy.
2017-05-28 19:38:43 -07:00

43 lines
1.5 KiB
JavaScript

// @flow
import crypto from 'crypto';
import { LoggerFactory } from '@calzoneman/jsli';
import * as urlparse from 'url';
import { CamoConfig } from './configuration/camoconfig';
const LOGGER = LoggerFactory.getLogger('camo');
function isWhitelisted(camoConfig: CamoConfig, url: string): boolean {
const whitelistedDomains = camoConfig.getWhitelistedDomains();
const parsed = urlparse.parse(url);
return whitelistedDomains.includes(parsed.hostname);
}
export function camoify(camoConfig: CamoConfig, url: string): string {
if (typeof url !== 'string') {
throw new TypeError(`camoify expected a string, not [${url}]`);
}
if (isWhitelisted(camoConfig, url)) {
return url.replace(/^http:/, 'https:');
}
const hmac = crypto.createHmac('sha1', camoConfig.getKey());
hmac.update(url);
const digest = hmac.digest('hex');
const hexUrl = Buffer.from(url, 'utf8').toString('hex');
return `${camoConfig.getServer()}/${digest}/${hexUrl}`;
}
export function transformImgTags(camoConfig: CamoConfig, tagName: string, attribs: Object) {
if (typeof attribs.src === 'string') {
try {
const oldSrc = attribs.src;
attribs.src = camoify(camoConfig, attribs.src);
LOGGER.debug('Camoified "%s" to "%s"', oldSrc, attribs.src);
} catch (error) {
LOGGER.error(`Failed to generate camo URL for "${attribs.src}": ${error}`);
}
}
return { tagName, attribs };
}