Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -312,29 +312,6 @@ io.on('connection', (socket) => {
reply(false, 'Invalid upload payload: nodes must be an array.');
return;
}
// Validate file content sizes BEFORE mutating the file system.
// This prevents stale/orphaned nodes if a file exceeds the limit.
if (fileContents && typeof fileContents === 'object') {
const MAX_FILE_SIZE = 1 * 1024 * 1024;
const MAX_ROOM_SIZE = 50 * 1024 * 1024;

let totalSize = Object.values(roomState[roomId].fileContents)
.reduce((acc, c) => acc + (typeof c === 'string' ? Buffer.byteLength(c) : 0), 0);

for (const [, content] of Object.entries(fileContents)) {
const size = typeof content === 'string' ? Buffer.byteLength(content) : 0;
if (size > MAX_FILE_SIZE) {
reply(false, 'File exceeds maximum size of 1MB.');
return;
}
totalSize += size;
if (totalSize > MAX_ROOM_SIZE) {
reply(false, 'Room storage exceeds maximum capacity.');
return;
}
}
}

for (const node of nodes) {
fs[node.id] = node;
if (fs[node.parentId]) {
Expand Down
36 changes: 12 additions & 24 deletions src/pages/EditorPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -621,37 +621,25 @@ const EditorPage = () => {
}
}

// Read content first so we can check its byte length against the server-side limit.
// Checking content.length (text/base64 string) aligns with the server's Buffer.byteLength
// validation, avoiding the ~33% mismatch that would occur when comparing file.size
// against the base64-encoded data URL size for images.
let content;
const fileId = uuid();
// Always add the node so binary files appear in the file tree
nodesToCreate.push({ id: fileId, name: file.name, type: 'file', parentId });

Comment on lines +624 to +627
// Handle image vs binary vs text reading
if (isImage(file.name)) {
try {
content = await readFileAsDataURL(file);
const content = await readFileAsDataURL(file);
return { fileId, content };
} catch (err) {
console.error("Failed to read image data URL for", file.name, err);
content = '';
return { fileId, content: '' };
}
} else if (isBinary(file.name)) {
// Non-image binary files: add node to tree without content
const fileId = uuid();
nodesToCreate.push({ id: fileId, name: file.name, type: 'file', parentId });
return null;
} else {
content = await readFileAsText(file);
}

// Align with server-side validation: check the byte length of the transmitted content
if (content && content.length > 1 * 1024 * 1024) {
toast.error(`${file.name} exceeds the 1MB size limit.`);
return null;
if (isBinary(file.name)) {
return null; // Skip content reading for non-image binary files
}

const fileId = uuid();
nodesToCreate.push({ id: fileId, name: file.name, type: 'file', parentId });

return { fileId, content: content || '' };
const content = await readFileAsText(file);
return { fileId, content };
});

const results = (await Promise.all(fileReadPromises)).filter(Boolean);
Expand Down