add sample realaudio, fix ragen
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
zefie_wtvp_minisrv/includes/ServiceVault/pnm/classicrom/WTVa.ra
Normal file
BIN
zefie_wtvp_minisrv/includes/ServiceVault/pnm/classicrom/WTVa.ra
Normal file
Binary file not shown.
Binary file not shown.
BIN
zefie_wtvp_minisrv/includes/ServiceVault/pnm/classicrom/karTV.ra
Normal file
BIN
zefie_wtvp_minisrv/includes/ServiceVault/pnm/classicrom/karTV.ra
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
zefie_wtvp_minisrv/includes/ServiceVault/pnm/classicrom/seqJ.ra
Normal file
BIN
zefie_wtvp_minisrv/includes/ServiceVault/pnm/classicrom/seqJ.ra
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -16,13 +16,58 @@ if (minisrv_config.config.ServiceVaults) {
|
||||
throw ("ERROR: No Service Vaults defined!");
|
||||
}
|
||||
|
||||
// Detect subdirectory structure of this catchall.js file and strip it from requests
|
||||
// e.g., if at /ServiceVault/wtv-music/ragen/catchall.js, extract "ragen"
|
||||
// if at /ServiceVault/wtv-music/ra/gen/catchall.js, extract "ra/gen"
|
||||
let subDirPath = '';
|
||||
const currentDir = path.dirname(__filename);
|
||||
const serviceVaultIdx = currentDir.indexOf('ServiceVault');
|
||||
console.log("DEBUG: currentDir =", currentDir, "serviceVaultIdx =", serviceVaultIdx);
|
||||
if (serviceVaultIdx !== -1) {
|
||||
const afterVault = currentDir.substring(serviceVaultIdx + 12); // 12 = length of 'ServiceVault'
|
||||
console.log("DEBUG: afterVault =", afterVault);
|
||||
const parts = afterVault.split(path.sep).filter(p => p);
|
||||
console.log("DEBUG: parts =", parts);
|
||||
if (parts.length > 1) {
|
||||
// parts[0] is the service name (e.g., 'wtv-music'), parts[1+] are the subdirs
|
||||
const subdirs = parts.slice(1);
|
||||
subDirPath = '/' + subdirs.join('/');
|
||||
}
|
||||
}
|
||||
console.log("DEBUG: Detected subDirPath =", subDirPath);
|
||||
|
||||
const url_path = request_headers.request_url.split('?')[0];
|
||||
const pathParts = url_path.split('/').filter(p => p);
|
||||
const serviceName = pathParts.length > 0 ? pathParts[0] : '';
|
||||
const remainingPath = '/' + pathParts.slice(1).join('/');
|
||||
const filename = remainingPath.split('/').pop().replace('.ram', '');
|
||||
const directory = remainingPath.endsWith('/') || !filename ? remainingPath.replace(/\/$/, '') : remainingPath.substring(0, remainingPath.lastIndexOf('/'));
|
||||
let remainingPath = '/' + pathParts.slice(1).join('/');
|
||||
const hadTrailingSlash = request_headers.request_url.endsWith('/');
|
||||
|
||||
console.log("DEBUG: Before stripping - subDirPath =", subDirPath, "remainingPath =", remainingPath);
|
||||
|
||||
let strippedSubDir = ''; // Store what was stripped for link rebuilding
|
||||
// Strip the subdirectory structure from the request path
|
||||
if (subDirPath) {
|
||||
if (remainingPath.startsWith(subDirPath + '/')) {
|
||||
// Has something after the subdirectory, e.g., /ragen/classicrom
|
||||
strippedSubDir = subDirPath;
|
||||
remainingPath = remainingPath.substring(subDirPath.length);
|
||||
} else if (remainingPath === subDirPath || remainingPath === subDirPath + '/') {
|
||||
// Just the subdirectory itself, e.g., /ragen or /ragen/
|
||||
strippedSubDir = subDirPath;
|
||||
remainingPath = '/';
|
||||
}
|
||||
}
|
||||
|
||||
console.log("DEBUG: After stripping - remainingPath =", remainingPath, "strippedSubDir =", strippedSubDir);
|
||||
|
||||
// Restore trailing slash if original URL had one
|
||||
if (hadTrailingSlash && !remainingPath.endsWith('/')) {
|
||||
remainingPath += '/';
|
||||
}
|
||||
|
||||
const filename = remainingPath.endsWith('/') ? '' : remainingPath.split('/').pop().replace('.ram', '');
|
||||
const directory = remainingPath.endsWith('/') ? remainingPath.replace(/\/$/, '') : remainingPath.substring(0, remainingPath.lastIndexOf('/'));
|
||||
console.log("DEBUG: Request for service", serviceName, "with filename", filename, "and directory", directory, "remainingPath", remainingPath);
|
||||
|
||||
let fileFound = false;
|
||||
const extensions = ['.ra', '.rm'];
|
||||
@@ -43,6 +88,8 @@ if (!filename || (request_headers.request_url.endsWith('/') && minisrv_config.se
|
||||
if (fs.statSync(fullPath).isFile() && (file.endsWith('.ra') || file.endsWith('.rm'))) {
|
||||
const baseFileName = file.substring(0, file.lastIndexOf('.'));
|
||||
allFiles.push(baseFileName + '.ram');
|
||||
} else if (fs.statSync(fullPath).isDirectory()) {
|
||||
allFiles.push(file + '/');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -51,7 +98,16 @@ if (!filename || (request_headers.request_url.endsWith('/') && minisrv_config.se
|
||||
if (allFiles.length > 0) {
|
||||
headers = `200 OK
|
||||
Content-type: text/html`;
|
||||
data = `<html><body><h1>RealAudio Files on this minisrv</h1><ul>${allFiles.map(f => `<li><a href="${f}">${f}</a></li>`).join('')}</ul></body></html>`;
|
||||
data = `<html>
|
||||
<body bgcolor="#110e1f" text="#44a1cc" link="36d5ff" vlink="36d5ff" vspace=0>
|
||||
<display nosave nosend>
|
||||
<title>RealAudio Files on this Service</title>
|
||||
<sidebar width=20%>
|
||||
<img src="wtv-tricks:/images/Realaudio_bg.gif">
|
||||
</sidebar>
|
||||
<br>
|
||||
<br>
|
||||
<h1>RealAudio Files on this Service</h1><ul>${(directory === "") ? "" : `<li><a href="../">../</a></li>\n`}${allFiles.map(f => `<li><a href="${(directory === "") ? f : `${strippedSubDir}${directory}/${f}`}">${f}</a></li>`).join("\n")}</ul></body></html>`;
|
||||
} else {
|
||||
headers = `404 Not Found
|
||||
Content-type: text/html`;
|
||||
@@ -61,7 +117,7 @@ Content-type: text/html`;
|
||||
// Original file search logic
|
||||
for (const pnmVault of pnmVaults) {
|
||||
for (const ext of extensions) {
|
||||
const filePath = path.join(pnmVault, filename + ext);
|
||||
const filePath = path.join(pnmVault, directory, filename + ext);
|
||||
console.log("DEBUG: Checking for file", filePath);
|
||||
if (fs.existsSync(filePath)) {
|
||||
fileFound = true;
|
||||
@@ -76,8 +132,11 @@ Content-type: text/html`;
|
||||
headers = `404 Not Found
|
||||
Content-type: text/html`;
|
||||
} else {
|
||||
const filePath = path.join(directory || '/', filename + path.extname(resolvedPath));
|
||||
const pnmURL = `pnm://${minisrv_config.config.service_ip}:${minisrv_config.services['pnm'].port}${filePath.replace(/\\/g, '/')}`;
|
||||
console.log("DEBUG: File found at", resolvedPath, "serving as", pnmURL);
|
||||
headers = `200 OK
|
||||
Content-type: audio/x-pn-realaudio`
|
||||
data = `pnm://${minisrv_config.config.service_ip}:${minisrv_config.services['pnm'].port}/${filename + path.extname(resolvedPath)}`;
|
||||
data = pnmURL;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -352,14 +352,35 @@ class WTVPNM {
|
||||
socket.write(headers + body, () => socket.end());
|
||||
}
|
||||
|
||||
normalizeRequestedMediaPath(value) {
|
||||
if (value === null || value === undefined) return null;
|
||||
|
||||
let raw = String(value).replace(/\x00+$/g, '').trim();
|
||||
if (!raw) return null;
|
||||
|
||||
// Trim query/fragment and normalize separators to URL-style slashes.
|
||||
raw = raw.split(/[?#]/)[0].replace(/\\+/g, '/');
|
||||
|
||||
// Drop common URI scheme prefixes if present.
|
||||
raw = raw.replace(/^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/]*\/?/, '');
|
||||
raw = raw.replace(/^[A-Za-z][A-Za-z0-9+.-]*:\/*/, '');
|
||||
|
||||
// Keep only a safe relative path under the service vault.
|
||||
const parts = raw.split('/').filter((part) => part && part !== '.' && part !== '..');
|
||||
if (parts.length === 0) return null;
|
||||
|
||||
return parts.join('/');
|
||||
}
|
||||
|
||||
getRequestedMediaName(fields, rawData) {
|
||||
if (!Array.isArray(fields) || fields.length === 0) return this.scanRawForMediaName(rawData);
|
||||
|
||||
// Field 0x52 (82) carries the requested file name in observed captures.
|
||||
const fileField = fields.find((f) => f && f.id === 82 && f.len > 0);
|
||||
if (fileField) {
|
||||
const raw = fileField.value.toString('latin1').replace(/\x00+$/g, '').trim();
|
||||
if (raw) return path.basename(raw);
|
||||
const raw = fileField.value.toString('latin1');
|
||||
const normalized = this.normalizeRequestedMediaPath(raw);
|
||||
if (normalized) return normalized;
|
||||
}
|
||||
|
||||
// Some clients may carry filename in another TLV field; scan all text values.
|
||||
@@ -368,7 +389,8 @@ class WTVPNM {
|
||||
const raw = field.value.toString('latin1').replace(/\x00+/g, ' ').trim();
|
||||
const match = raw.match(/([A-Za-z0-9_\-\.\/]+\.(?:ra|ray|rm|ram))/i);
|
||||
if (match) {
|
||||
return path.basename(match[1]);
|
||||
const normalized = this.normalizeRequestedMediaPath(match[1]);
|
||||
if (normalized) return normalized;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,8 +401,8 @@ class WTVPNM {
|
||||
scanRawForMediaName(rawData) {
|
||||
if (!Buffer.isBuffer(rawData)) return null;
|
||||
const str = rawData.toString('latin1');
|
||||
const match = str.match(/([A-Za-z0-9_\-\.]+\.(?:ra|ray|rm|ram))(?:[^A-Za-z0-9]|$)/i);
|
||||
return match ? path.basename(match[1]) : null;
|
||||
const match = str.match(/([A-Za-z0-9_\-\.\/]+\.(?:ra|ray|rm|ram))(?:[^A-Za-z0-9]|$)/i);
|
||||
return match ? this.normalizeRequestedMediaPath(match[1]) : null;
|
||||
}
|
||||
|
||||
getClientChallenge(fields) {
|
||||
@@ -423,6 +445,7 @@ class WTVPNM {
|
||||
const base = this.wtvshared.getAbsolutePath(serviceVaultDir, vault);
|
||||
for (const variant of extensionVariants) {
|
||||
const candidate = this.wtvshared.makeSafePath(base, variant);
|
||||
this.debugLog('testing media candidate', candidate);
|
||||
if (candidate && fs.existsSync(candidate) && fs.lstatSync(candidate).isFile()) {
|
||||
if (this.service_config.debug) {
|
||||
this.debugLog('media file found', variant, '->', candidate);
|
||||
@@ -438,12 +461,12 @@ class WTVPNM {
|
||||
}
|
||||
|
||||
getMediaNameVariants(requestedMedia) {
|
||||
const base = path.basename(requestedMedia || '').trim();
|
||||
if (!base) return [];
|
||||
const requestedPath = this.normalizeRequestedMediaPath(requestedMedia);
|
||||
if (!requestedPath) return [];
|
||||
|
||||
const ext = path.extname(base).toLowerCase();
|
||||
const stem = ext.length > 0 ? base.slice(0, -ext.length) : base;
|
||||
const variants = [base];
|
||||
const ext = path.posix.extname(requestedPath).toLowerCase();
|
||||
const stem = ext.length > 0 ? requestedPath.slice(0, -ext.length) : requestedPath;
|
||||
const variants = [requestedPath];
|
||||
|
||||
if (ext === '.ray') variants.push(`${stem}.ra`);
|
||||
if (ext === '.ram') variants.push(`${stem}.ra`);
|
||||
@@ -1147,7 +1170,12 @@ class WTVPNM {
|
||||
const serverChallenge = session?.serverChallenge || 0;
|
||||
const challengeBuf = Buffer.from(challenge, 'latin1');
|
||||
const requestedMedia = session?.requestedMedia || '';
|
||||
const resolvedMedia = session?.mediaPath ? path.basename(session.mediaPath) : '';
|
||||
const requestedMediaPath = this.normalizeRequestedMediaPath(requestedMedia);
|
||||
const resolvedBase = session?.mediaPath ? path.basename(session.mediaPath) : '';
|
||||
const requestedDir = requestedMediaPath ? path.posix.dirname(requestedMediaPath) : '';
|
||||
const resolvedMedia = resolvedBase
|
||||
? (requestedDir && requestedDir !== '.' ? `${requestedDir}/${resolvedBase}` : resolvedBase)
|
||||
: requestedMediaPath;
|
||||
const responseSource = resolvedMedia || requestedMedia || challenge;
|
||||
const respSrcBuf = Buffer.from(responseSource, 'latin1');
|
||||
const timestamp = this.getClientTimestamp(session?.pnaFields) ?? Math.floor(Date.now() / 1000);
|
||||
@@ -1159,7 +1187,8 @@ class WTVPNM {
|
||||
|
||||
this.debugLog('session token seed', session?.id || '?',
|
||||
`clientChallenge=${challenge}`,
|
||||
`requestedMedia=${requestedMedia || '(fallback:clientChallenge)'}`,
|
||||
`requestedMedia=${requestedMedia}`,
|
||||
`responseSource=${responseSource}`,
|
||||
`serverChallenge=${serverChallenge.toString(16)}`,
|
||||
`v12=${v12}`,
|
||||
`resp1=${resp1}`, `initMD5=${initMD5}`);
|
||||
|
||||
@@ -401,7 +401,7 @@
|
||||
"protocol_handler": "pnm",
|
||||
"descriptor_after_hello_ms": 85,
|
||||
"burst_prestart_ms": 5000,
|
||||
"debug": false,
|
||||
"debug": true,
|
||||
"allow_indexing": true
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user