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
2 changes: 1 addition & 1 deletion apps/sim/app/(auth)/signup/signup-form.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -271,7 +271,7 @@ function SignupFormContent({ githubAvailable, googleAvailable, isProduction }: S
...(token ? { 'x-captcha-response': token } : {}),
},
onError: (ctx) => {
logger.error('Signup error:', ctx.error)
logger.warn('Signup error:', ctx.error)
const errorMessage: string[] = ['Failed to create account']

let errorCode = 'unknown'
Expand Down
44 changes: 44 additions & 0 deletions apps/sim/app/api/files/parse/route.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -69,6 +69,7 @@ vi.mock('@/app/api/files/authorization', () => ({
vi.mock('@/lib/uploads', () => ({
getStorageProvider: mockGetStorageProvider,
isUsingCloudStorage: mockIsUsingCloudStorage,
StorageService: storageServiceMock,
}))

vi.mock('@/lib/file-parsers', () => ({
Expand DownExpand Up@@ -172,6 +173,7 @@ describe('File Parse API Route', () => {

permissionsMockFns.mockGetUserEntityPermissions.mockResolvedValue({ canView: true })
storageServiceMockFns.mockHasCloudStorage.mockReturnValue(true)
storageServiceMockFns.mockDownloadFile.mockResolvedValue(Buffer.from('test file content'))
mockIsSupportedFileType.mockReturnValue(true)
mockParseFile.mockResolvedValue({
content: 'parsed content',
Expand DownExpand Up@@ -245,6 +247,48 @@ describe('File Parse API Route', () => {
}
})

it('should keep known binary extensions as binary even when the bytes are valid UTF-8', async () => {
setupFileApiMocks({
cloudEnabled: true,
storageProvider: 's3',
authenticated: true,
})
mockIsSupportedFileType.mockReturnValue(false)
storageServiceMockFns.mockDownloadFile.mockResolvedValue(Buffer.from('valid utf8 bytes'))

const req = createMockRequest('POST', {
filePath: '/api/files/serve/execution/workspace-1/workflow-1/execution-1/image.png',
})

const response = await POST(req)
const data = await response.json()

expect(response.status).toBe(200)
expect(data.success).toBe(true)
expect(data.output.content).toBe('[Binary PNG file - 16 bytes]')
})

it('should parse unknown extensions as text when the bytes look like UTF-8 text', async () => {
setupFileApiMocks({
cloudEnabled: true,
storageProvider: 's3',
authenticated: true,
})
mockIsSupportedFileType.mockReturnValue(false)
storageServiceMockFns.mockDownloadFile.mockResolvedValue(Buffer.from('plain text content'))

const req = createMockRequest('POST', {
filePath: '/api/files/serve/execution/workspace-1/workflow-1/execution-1/readme.customtext',
})

const response = await POST(req)
const data = await response.json()

expect(response.status).toBe(200)
expect(data.success).toBe(true)
expect(data.output.content).toBe('plain text content')
})

it('should handle multiple files', async () => {
setupFileApiMocks({
cloudEnabled: false,
Expand Down
16 changes: 11 additions & 5 deletions apps/sim/app/api/files/parse/route.ts
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
import { Buffer } from 'buffer'
import { Buffer, isUtf8 } from 'buffer'
import { createHash } from 'crypto'
import fsPromises, { readFile } from 'fs/promises'
import path from 'path'
Expand DownExpand Up@@ -39,6 +39,11 @@ const logger = createLogger('FilesParseAPI')

const MAX_DOWNLOAD_SIZE_BYTES = 100 * 1024 * 1024 // 100 MB
const DOWNLOAD_TIMEOUT_MS = 30000 // 30 seconds
const BINARY_EXTENSIONS = new Set<string>(binaryExtensionsList)

function isLikelyTextBuffer(fileBuffer: Buffer): boolean {
return isUtf8(fileBuffer) && !fileBuffer.includes(0)
}
Comment thread
icecrasher321 marked this conversation as resolved.

interface ExecutionContext {
workspaceId: string
Expand DownExpand Up@@ -863,10 +868,11 @@ function handleGenericBuffer(
extension: string,
fileType?: string
): ParseResult {
const isBinary = binaryExtensionsList.includes(extension)
const content = isBinary
? `[Binary ${extension.toUpperCase()} file - ${fileBuffer.length} bytes]`
: fileBuffer.toString('utf-8')
const normalizedExtension = extension.toLowerCase()
const content =
!BINARY_EXTENSIONS.has(normalizedExtension) && isLikelyTextBuffer(fileBuffer)
? fileBuffer.toString('utf-8')
: `[Binary ${normalizedExtension.toUpperCase()} file - ${fileBuffer.length} bytes]`
Comment thread
icecrasher321 marked this conversation as resolved.

return {
success: true,
Expand Down
Loading
Loading