diff --git a/src/utils/anonymizer.js b/src/utils/anonymizer.js
new file mode 100644
index 0000000..b022699
--- /dev/null
+++ b/src/utils/anonymizer.js
@@ -0,0 +1,51 @@
+import urlparser from 'url-parse';
+
+const anonymize_url = (url) => {
+ let u = urlparser(url, true);
+
+ if (u.hostname !== 'localhost') {
+ return `${u.protocol}//[anonymized]`;
+ }
+
+ if (u.auth.length !== 0) {
+ u.username = '***';
+ u.password = '***';
+ }
+
+ if (u.protocol === 'rtmp:') {
+ if ('token' in u.query) {
+ u.query.token = '***';
+ }
+ } else if (u.protocol === 'srt') {
+ if ('streamid' in u.query) {
+ u.query.streamid = '***';
+ }
+
+ if ('passphrase' in u.query) {
+ u.query.passphrase = '***';
+ }
+ }
+
+ return u.toString();
+};
+
+const anonymize = (text) => {
+ const regex = /(?:([a-z0-9\\]+):)?\/[A-Za-z0-9-._~!$&'()*+,;=:@?/{}%\\]*/gm;
+
+ return text.replaceAll(regex, (match, scheme) => {
+ console.log('text', text, 'match', match, 'scheme', scheme);
+ if (scheme) {
+ match = match.replace(scheme, scheme.replaceAll('\\', ''));
+ return anonymize_url(match);
+ }
+
+ const pathElm = match.split('/').filter((p) => p.length !== 0);
+ if (pathElm.length < 2) {
+ return match;
+ }
+
+ return `/[anonymized]/${pathElm.pop()}`;
+ });
+};
+
+export { anonymize, anonymize_url };
diff --git a/src/utils/restreamer.js b/src/utils/restreamer.js
index cfc52ba..d64d81c 100644
--- a/src/utils/restreamer.js
+++ b/src/utils/restreamer.js
@@ -11,6 +11,7 @@ import * as M from './metadata';
import * as Storage from './storage';
import * as Version from '../version';
import API from './api';
+import { anonymize } from './anonymizer';
class Restreamer {
constructor(address) {
@@ -3030,51 +3031,35 @@ class Restreamer {
return null;
}
- const regex = /(?:([a-z]+):)?\/[^\s]*/gm;
- const replace = (s) => {
- return s.replaceAll(regex, (match, scheme) => {
- if (scheme) {
- return `${scheme}://[anonymized]`;
- }
-
- const pathElm = match.split('/').filter((p) => p.length !== 0);
- if (pathElm.length < 2) {
- return match;
- }
-
- return `/[anonymized]/${pathElm.pop()}`;
- });
- };
-
if (p.config) {
- p.config.options = p.config.options.map(replace);
+ p.config.options = p.config.options.map(anonymize);
for (let i in p.config.input) {
- p.config.input[i].address = replace(p.config.input[i].address);
- p.config.input[i].options = p.config.input[i].options.map(replace);
+ p.config.input[i].address = anonymize(p.config.input[i].address);
+ p.config.input[i].options = p.config.input[i].options.map(anonymize);
}
for (let i in p.config.output) {
- p.config.output[i].address = replace(p.config.output[i].address);
- p.config.output[i].options = p.config.output[i].options.map(replace);
+ p.config.output[i].address = anonymize(p.config.output[i].address);
+ p.config.output[i].options = p.config.output[i].options.map(anonymize);
}
}
if (p.state) {
for (let i in p.state.progress.inputs) {
- p.state.progress.inputs[i].address = replace(p.state.progress.inputs[i].address);
+ p.state.progress.inputs[i].address = anonymize(p.state.progress.inputs[i].address);
}
for (let i in p.state.progress.outputs) {
- p.state.progress.outputs[i].address = replace(p.state.progress.outputs[i].address);
+ p.state.progress.outputs[i].address = anonymize(p.state.progress.outputs[i].address);
}
if (!p.state.command) {
p.state.command = [];
}
- p.state.command = p.state.command.map(replace);
- p.state.last_logline = replace(p.state.last_logline);
+ p.state.command = p.state.command.map(anonymize);
+ p.state.last_logline = anonymize(p.state.last_logline);
}
if (p.report) {
@@ -3082,12 +3067,12 @@ class Restreamer {
p.report.prelude = [];
}
- p.report.prelude = p.report.prelude.map(replace);
- p.report.log = p.report.log.map((l) => [l[0], replace(l[1])]);
+ p.report.prelude = p.report.prelude.map(anonymize);
+ p.report.log = p.report.log.map((l) => [l[0], anonymize(l[1])]);
for (let i in p.report.history) {
- p.report.history[i].prelude = p.report.history[i].prelude.map(replace);
- p.report.history[i].log = p.report.history[i].log.map((l) => [l[0], replace(l[1])]);
+ p.report.history[i].prelude = p.report.history[i].prelude.map(anonymize);
+ p.report.history[i].log = p.report.history[i].log.map((l) => [l[0], anonymize(l[1])]);
}
}
@@ -3348,6 +3333,20 @@ class Restreamer {
config.storage.memory.auth.username = '[anonymized]';
config.storage.memory.auth.password = '[anonymized]';
+ config.storage.s3 = config.storage.s3.map((e) => {
+ return {
+ ...e,
+ auth: {
+ ...e.auth,
+ username: '[anonymized]',
+ password: '[anonymized]',
+ },
+ endpoint: '[anonymized]',
+ access_key_id: '[anonymized]',
+ secret_access_key: '[anonymized]',
+ };
+ });
+
if (config.storage.cors.origins.length !== 1 || config.storage.cors.origins[0] !== '*') {
config.storage.cors.origins = config.storage.cors.origins.map((e) => '[anonymized]');
}
@@ -3355,6 +3354,8 @@ class Restreamer {
config.rtmp.app = '[anonymized]';
config.rtmp.token = '[anonymized]';
+ config.ffmpeg.binary = anonymize(config.ffmpeg.binary);
+
config.service.token = '[anonymized]';
config.sessions.ip_ignorelist = config.sessions.ip_ignorelist.map((e) => '[anonymized]');
diff --git a/src/views/Main/index.js b/src/views/Main/index.js
index ed269b2..49c851b 100644
--- a/src/views/Main/index.js
+++ b/src/views/Main/index.js
@@ -11,6 +11,7 @@ import Typography from '@mui/material/Typography';
import WarningIcon from '@mui/icons-material/Warning';
import * as M from '../../utils/metadata';
+import { anonymize } from '../../utils/anonymizer';
import useInterval from '../../hooks/useInterval';
import ActionButton from '../../misc/ActionButton';
import CopyButton from '../../misc/CopyButton';
@@ -350,7 +351,7 @@ export default function Main(props) {
- Error: {$state.progress.error || 'unknown'}
+ Error: {anonymize($state.progress.error) || 'unknown'}