Spaces:
Paused
Paused
Update server.js
Browse files
server.js
CHANGED
|
@@ -281,7 +281,7 @@ fileRouter.get('/deleteFile', async (req, res) => {
|
|
| 281 |
}
|
| 282 |
|
| 283 |
const absoluteRequestedPath = path.normalize(path.join(TELEGRAM_DATA_DIR, relativePath));
|
| 284 |
-
if (!absoluteRequestedPath.startsWith(path.resolve(TELEGRAM_DATA_DIR))) {
|
| 285 |
return res.status(403).json({ error: 'Forbidden: Path traversal attempt detected.' });
|
| 286 |
}
|
| 287 |
|
|
@@ -318,19 +318,20 @@ fileRouter.get('/:botToken/deleteById', async (req, res) => {
|
|
| 318 |
return res.status(404).json({ error: 'File not found or path not available via Telegram API (getFile).', details: fileInfo });
|
| 319 |
}
|
| 320 |
|
| 321 |
-
const
|
| 322 |
-
const
|
|
|
|
| 323 |
|
| 324 |
-
if (!
|
| 325 |
-
console.
|
| 326 |
-
return res.status(403).json({ error: 'Forbidden:
|
| 327 |
}
|
| 328 |
|
| 329 |
-
if (fssync.existsSync(
|
| 330 |
-
await fs.unlink(
|
| 331 |
-
res.json({ success: true, message: `File deleted successfully. Path: ${
|
| 332 |
} else {
|
| 333 |
-
res.status(404).json({ error: 'File not found on disk for the given file_id.', path_attempted:
|
| 334 |
}
|
| 335 |
} catch (error) {
|
| 336 |
console.error(`Error in /:botToken/deleteById for file_id ${file_id}:`, error);
|
|
@@ -361,9 +362,17 @@ fileRouter.get('/downloadEncrypted', async (req, res) => {
|
|
| 361 |
return res.status(404).json({ error: 'File not found or path not available via Telegram API.', details: fileInfo });
|
| 362 |
}
|
| 363 |
|
| 364 |
-
const filePathOnDisk =
|
| 365 |
-
|
| 366 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 367 |
if (err && !res.headersSent) res.status(500).send('Error sending file.');
|
| 368 |
});
|
| 369 |
} else {
|
|
@@ -394,8 +403,27 @@ fileRouter.get('/:botToken/getFile', async (req, res) => {
|
|
| 394 |
if (fileInfo.ok && fileInfo.result && fileInfo.result.file_path) {
|
| 395 |
const spaceHost = process.env.SPACE_HOST;
|
| 396 |
const publicSpaceUrl = spaceHost ? `https://${spaceHost}` : `http://localhost:${APP_PORT}`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 397 |
|
| 398 |
-
fileInfo.result.direct_download_link_by_path = `${publicSpaceUrl}/file/${fileInfo.result.file_path}`;
|
| 399 |
fileInfo.result.direct_download_link_by_id = `${publicSpaceUrl}/file/${botToken}/downloadFile?file_id=${file_id}`;
|
| 400 |
|
| 401 |
if (encryptionKeyBuffer) {
|
|
@@ -436,9 +464,17 @@ fileRouter.get('/:botToken/downloadFile', async (req, res) => {
|
|
| 436 |
return res.status(404).json({ error: 'File not found or path not available via Telegram API.', details: fileInfo });
|
| 437 |
}
|
| 438 |
|
| 439 |
-
const filePathOnDisk =
|
| 440 |
-
|
| 441 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 442 |
if (err && !res.headersSent) res.status(500).send('Error sending file.');
|
| 443 |
});
|
| 444 |
} else {
|
|
@@ -455,7 +491,9 @@ fileRouter.get('/:filepath(*)', (req, res) => {
|
|
| 455 |
if (!relativePath || relativePath.includes('..')) return res.status(400).send('Invalid file path.');
|
| 456 |
|
| 457 |
const absoluteRequestedPath = path.normalize(path.join(TELEGRAM_DATA_DIR, relativePath));
|
| 458 |
-
if (!absoluteRequestedPath.startsWith(path.resolve(TELEGRAM_DATA_DIR)))
|
|
|
|
|
|
|
| 459 |
|
| 460 |
if (fssync.existsSync(absoluteRequestedPath) && fssync.statSync(absoluteRequestedPath).isFile()) {
|
| 461 |
res.sendFile(absoluteRequestedPath, err => {
|
|
|
|
| 281 |
}
|
| 282 |
|
| 283 |
const absoluteRequestedPath = path.normalize(path.join(TELEGRAM_DATA_DIR, relativePath));
|
| 284 |
+
if (!path.resolve(absoluteRequestedPath).startsWith(path.resolve(TELEGRAM_DATA_DIR))) {
|
| 285 |
return res.status(403).json({ error: 'Forbidden: Path traversal attempt detected.' });
|
| 286 |
}
|
| 287 |
|
|
|
|
| 318 |
return res.status(404).json({ error: 'File not found or path not available via Telegram API (getFile).', details: fileInfo });
|
| 319 |
}
|
| 320 |
|
| 321 |
+
const filePathOnDisk = fileInfo.result.file_path;
|
| 322 |
+
const resolvedDataDir = path.resolve(TELEGRAM_DATA_DIR);
|
| 323 |
+
const resolvedFilePathOnDisk = path.resolve(filePathOnDisk);
|
| 324 |
|
| 325 |
+
if (!resolvedFilePathOnDisk.startsWith(resolvedDataDir)) {
|
| 326 |
+
console.error(`[Security] Attempt to delete file outside TELEGRAM_DATA_DIR. Requested: ${filePathOnDisk}, Allowed base: ${resolvedDataDir}`);
|
| 327 |
+
return res.status(403).json({ error: 'Forbidden: File path is outside allowed directory.' });
|
| 328 |
}
|
| 329 |
|
| 330 |
+
if (fssync.existsSync(resolvedFilePathOnDisk) && fssync.statSync(resolvedFilePathOnDisk).isFile()) {
|
| 331 |
+
await fs.unlink(resolvedFilePathOnDisk);
|
| 332 |
+
res.json({ success: true, message: `File deleted successfully. Path: ${filePathOnDisk}`, file_id: file_id });
|
| 333 |
} else {
|
| 334 |
+
res.status(404).json({ error: 'File not found on disk for the given file_id.', path_attempted: filePathOnDisk });
|
| 335 |
}
|
| 336 |
} catch (error) {
|
| 337 |
console.error(`Error in /:botToken/deleteById for file_id ${file_id}:`, error);
|
|
|
|
| 362 |
return res.status(404).json({ error: 'File not found or path not available via Telegram API.', details: fileInfo });
|
| 363 |
}
|
| 364 |
|
| 365 |
+
const filePathOnDisk = fileInfo.result.file_path;
|
| 366 |
+
const resolvedDataDir = path.resolve(TELEGRAM_DATA_DIR);
|
| 367 |
+
const resolvedFilePathOnDisk = path.resolve(filePathOnDisk);
|
| 368 |
+
|
| 369 |
+
if (!resolvedFilePathOnDisk.startsWith(resolvedDataDir)) {
|
| 370 |
+
console.error(`[Security] Attempt to access file outside TELEGRAM_DATA_DIR. Requested: ${filePathOnDisk}, Allowed base: ${resolvedDataDir}`);
|
| 371 |
+
return res.status(403).send('Forbidden: File path is outside allowed directory.');
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
if (fssync.existsSync(resolvedFilePathOnDisk) && fssync.statSync(resolvedFilePathOnDisk).isFile()) {
|
| 375 |
+
res.sendFile(resolvedFilePathOnDisk, { headers: { 'Content-Disposition': `attachment; filename="${path.basename(fileInfo.result.file_path)}"` } }, err => {
|
| 376 |
if (err && !res.headersSent) res.status(500).send('Error sending file.');
|
| 377 |
});
|
| 378 |
} else {
|
|
|
|
| 403 |
if (fileInfo.ok && fileInfo.result && fileInfo.result.file_path) {
|
| 404 |
const spaceHost = process.env.SPACE_HOST;
|
| 405 |
const publicSpaceUrl = spaceHost ? `https://${spaceHost}` : `http://localhost:${APP_PORT}`;
|
| 406 |
+
|
| 407 |
+
const apiFilePath = fileInfo.result.file_path;
|
| 408 |
+
let relativePathForLink = "";
|
| 409 |
+
|
| 410 |
+
const resolvedNormalizedDataDir = path.resolve(TELEGRAM_DATA_DIR);
|
| 411 |
+
const resolvedApiFilePath = path.resolve(apiFilePath);
|
| 412 |
+
|
| 413 |
+
if (resolvedApiFilePath.startsWith(resolvedNormalizedDataDir)) {
|
| 414 |
+
relativePathForLink = path.relative(resolvedNormalizedDataDir, resolvedApiFilePath);
|
| 415 |
+
} else {
|
| 416 |
+
console.warn(`[Warning] file_path from API (${apiFilePath}) does not seem to be inside TELEGRAM_DATA_DIR (${TELEGRAM_DATA_DIR}). Using file_path as is for link, which might be incorrect.`);
|
| 417 |
+
relativePathForLink = apiFilePath;
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
if (relativePathForLink.startsWith('..')) {
|
| 421 |
+
console.error(`[Security] Calculated relative path for link starts with '..': ${relativePathForLink}. Original API path: ${apiFilePath}`);
|
| 422 |
+
fileInfo.result.direct_download_link_by_path = "Error: could not construct safe relative path.";
|
| 423 |
+
} else {
|
| 424 |
+
fileInfo.result.direct_download_link_by_path = `${publicSpaceUrl}/file/${relativePathForLink.split(path.sep).join('/')}`;
|
| 425 |
+
}
|
| 426 |
|
|
|
|
| 427 |
fileInfo.result.direct_download_link_by_id = `${publicSpaceUrl}/file/${botToken}/downloadFile?file_id=${file_id}`;
|
| 428 |
|
| 429 |
if (encryptionKeyBuffer) {
|
|
|
|
| 464 |
return res.status(404).json({ error: 'File not found or path not available via Telegram API.', details: fileInfo });
|
| 465 |
}
|
| 466 |
|
| 467 |
+
const filePathOnDisk = fileInfo.result.file_path;
|
| 468 |
+
const resolvedDataDir = path.resolve(TELEGRAM_DATA_DIR);
|
| 469 |
+
const resolvedFilePathOnDisk = path.resolve(filePathOnDisk);
|
| 470 |
+
|
| 471 |
+
if (!resolvedFilePathOnDisk.startsWith(resolvedDataDir)) {
|
| 472 |
+
console.error(`[Security] Attempt to access file outside TELEGRAM_DATA_DIR. Requested: ${filePathOnDisk}, Allowed base: ${resolvedDataDir}`);
|
| 473 |
+
return res.status(403).send('Forbidden: File path is outside allowed directory.');
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
if (fssync.existsSync(resolvedFilePathOnDisk) && fssync.statSync(resolvedFilePathOnDisk).isFile()) {
|
| 477 |
+
res.sendFile(resolvedFilePathOnDisk, { headers: { 'Content-Disposition': `attachment; filename="${path.basename(fileInfo.result.file_path)}"` } }, err => {
|
| 478 |
if (err && !res.headersSent) res.status(500).send('Error sending file.');
|
| 479 |
});
|
| 480 |
} else {
|
|
|
|
| 491 |
if (!relativePath || relativePath.includes('..')) return res.status(400).send('Invalid file path.');
|
| 492 |
|
| 493 |
const absoluteRequestedPath = path.normalize(path.join(TELEGRAM_DATA_DIR, relativePath));
|
| 494 |
+
if (!path.resolve(absoluteRequestedPath).startsWith(path.resolve(TELEGRAM_DATA_DIR))) {
|
| 495 |
+
return res.status(403).send('Forbidden: Path traversal attempt detected.');
|
| 496 |
+
}
|
| 497 |
|
| 498 |
if (fssync.existsSync(absoluteRequestedPath) && fssync.statSync(absoluteRequestedPath).isFile()) {
|
| 499 |
res.sendFile(absoluteRequestedPath, err => {
|