mirror of
https://github.com/koush/scrypted.git
synced 2026-06-09 20:40:23 +01:00
fix(reolink): do not percent-encode RTMP credential params (#2058)
The Reolink RTMP server does not percent-decode query parameter values - it compares the raw bytes from the URL against the stored password. URLSearchParams.set() percent-encodes values when the URL is serialised (WHATWG application/x-www-form-urlencoded), which corrupts passwords containing characters such as '!' (-> '%21'), '#' (-> '%23'), '+' (-> '%2B'), space, etc.
Affected: users whose firmware causes getLoginParameters to return {user, password} (instead of a Login-API token) and whose password contains any of those characters. Symptom: rebroadcast prebuffer fails with 'Socket received FIN' immediately after 'Sending play command'.
Append the RTMP credential pairs as raw bytes instead of going through URLSearchParams. Token-only path is unaffected (hex tokens contain no characters that require encoding). Mirrors the rationale of #1509 for the HTTP API path.
Fixes #2057
Co-authored-by: thllxb <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -779,13 +779,21 @@ class ReolinkCamera extends RtspSmartCamera implements Camera, DeviceProvider, R
|
||||
if (url.protocol !== 'rtmp:') {
|
||||
url.username = this.storage.getItem('username');
|
||||
url.password = this.storage.getItem('password') || '';
|
||||
} else {
|
||||
const params = url.searchParams;
|
||||
for (const [k, v] of Object.entries(this.client.parameters)) {
|
||||
params.set(k, v);
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
return url.toString();
|
||||
// The Reolink RTMP server does not percent-decode query parameter
|
||||
// values - it compares the raw bytes from the URL against the stored
|
||||
// password. URLSearchParams.set() percent-encodes values when the URL
|
||||
// is serialised (WHATWG application/x-www-form-urlencoded), which
|
||||
// corrupts passwords containing characters such as '!', '#', '+',
|
||||
// space, etc. Append the credential parameters as raw bytes so the
|
||||
// password is delivered to the camera exactly as the user entered it.
|
||||
// See #1509 for the same class of issue on the HTTP API path.
|
||||
const sep = rtspUrl.includes('?') ? '&' : '?';
|
||||
const extras = Object.entries(this.client.parameters)
|
||||
.map(([k, v]) => `${k}=${v}`)
|
||||
.join('&');
|
||||
return rtspUrl + sep + extras;
|
||||
}
|
||||
|
||||
async createVideoStream(vso: UrlMediaStreamOptions): Promise<MediaObject> {
|
||||
|
||||
Reference in New Issue
Block a user