Merge pull request #401 from hobostay/fix/bug-fixes-security-and-reliability
Fix security and reliability issues
This commit is contained in:
@@ -490,7 +490,24 @@ export function registerIpcHandlers(
|
||||
return { success: false, message: "No recorded video found" };
|
||||
}
|
||||
|
||||
const latestVideo = videoFiles.sort().reverse()[0];
|
||||
// Sort by most recently modified to reliably get the latest recording.
|
||||
// Lexicographic sort is unreliable (e.g. recording-9.webm > recording-10.webm).
|
||||
let latestVideo: string | null = null;
|
||||
let latestMtimeMs = 0;
|
||||
for (const file of videoFiles) {
|
||||
try {
|
||||
const stat = await fs.stat(path.join(RECORDINGS_DIR, file));
|
||||
if (stat.mtimeMs > latestMtimeMs) {
|
||||
latestMtimeMs = stat.mtimeMs;
|
||||
latestVideo = file;
|
||||
}
|
||||
} catch {
|
||||
// Skip inaccessible files.
|
||||
}
|
||||
}
|
||||
if (!latestVideo) {
|
||||
return { success: false, message: "No recorded video found" };
|
||||
}
|
||||
const videoPath = path.join(RECORDINGS_DIR, latestVideo);
|
||||
|
||||
return { success: true, path: videoPath };
|
||||
@@ -618,7 +635,19 @@ export function registerIpcHandlers(
|
||||
|
||||
ipcMain.handle("open-external-url", async (_, url: string) => {
|
||||
try {
|
||||
await shell.openExternal(url);
|
||||
const ALLOWED_SCHEMES = ["http:", "https:", "mailto:"];
|
||||
let parsed: URL;
|
||||
try {
|
||||
parsed = new URL(url);
|
||||
} catch {
|
||||
return { success: false, error: "Invalid URL" };
|
||||
}
|
||||
|
||||
if (!ALLOWED_SCHEMES.includes(parsed.protocol)) {
|
||||
return { success: false, error: `Unsupported URL scheme: ${parsed.protocol}` };
|
||||
}
|
||||
|
||||
await shell.openExternal(parsed.toString());
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error("Failed to open URL:", error);
|
||||
|
||||
@@ -499,7 +499,6 @@ export default function VideoEditor() {
|
||||
aspectRatio,
|
||||
webcamLayoutPreset,
|
||||
webcamMaskShape,
|
||||
webcamSizePreset,
|
||||
webcamPosition,
|
||||
exportQuality,
|
||||
exportFormat,
|
||||
|
||||
@@ -542,7 +542,10 @@ export class AudioProcessor {
|
||||
}
|
||||
|
||||
private cloneWithTimestamp(src: AudioData, newTimestamp: number): AudioData {
|
||||
const isPlanar = src.format?.includes("planar") ?? false;
|
||||
if (!src.format) {
|
||||
throw new Error("AudioData format is required for cloning");
|
||||
}
|
||||
const isPlanar = src.format.includes("planar");
|
||||
const numPlanes = isPlanar ? src.numberOfChannels : 1;
|
||||
|
||||
let totalSize = 0;
|
||||
@@ -559,7 +562,7 @@ export class AudioProcessor {
|
||||
}
|
||||
|
||||
return new AudioData({
|
||||
format: src.format!,
|
||||
format: src.format,
|
||||
sampleRate: src.sampleRate,
|
||||
numberOfFrames: src.numberOfFrames,
|
||||
numberOfChannels: src.numberOfChannels,
|
||||
|
||||
@@ -424,7 +424,7 @@ export class VideoExporter {
|
||||
})();
|
||||
|
||||
this.muxingPromises.push(muxingPromise);
|
||||
this.encodeQueue--;
|
||||
this.encodeQueue = Math.max(0, this.encodeQueue - 1);
|
||||
},
|
||||
error: (error) => {
|
||||
console.error("[VideoExporter] Encoder error:", error);
|
||||
|
||||
Reference in New Issue
Block a user