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 number Diff line number Diff 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 number Diff line number Diff 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 Down Expand 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 Down Expand 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 number Diff line number Diff 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 Down Expand 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.
Resolved

interface ExecutionContext {
workspaceId: string
Expand Down Expand 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.
Resolved

return {
success: true,
Expand Down
Loading
Loading