diff --git a/ui-ngx/src/app/core/utils.ts b/ui-ngx/src/app/core/utils.ts index 7f13f08ba6..466652040f 100644 --- a/ui-ngx/src/app/core/utils.ts +++ b/ui-ngx/src/app/core/utils.ts @@ -226,8 +226,20 @@ export function objToBase64(obj: any): string { })); } +const textDecoderUtf8 = new TextDecoder('utf-8', { fatal: true }); +const textDecoderLatin1 = new TextDecoder('iso-8859-1'); + export function base64toString(b64Encoded: string): string { - return decodeURIComponent(atob(b64Encoded).split('').map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')); + const binary = atob(b64Encoded); + const bytes = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i); + } + try { + return textDecoderUtf8.decode(bytes); + } catch { + return textDecoderLatin1.decode(bytes); + } } export function objToBase64URI(obj: any): string { @@ -235,8 +247,7 @@ export function objToBase64URI(obj: any): string { } export function base64toObj(b64Encoded: string): any { - const json = decodeURIComponent(atob(b64Encoded).split('').map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')); - return JSON.parse(json); + return JSON.parse(base64toString(b64Encoded)); } export function stringToBase64(value: string): string { diff --git a/ui-ngx/src/app/shared/components/file-input.component.ts b/ui-ngx/src/app/shared/components/file-input.component.ts index 727b1628dc..5b09c30c25 100644 --- a/ui-ngx/src/app/shared/components/file-input.component.ts +++ b/ui-ngx/src/app/shared/components/file-input.component.ts @@ -239,7 +239,18 @@ export class FileInputComponent extends PageComponent implements AfterViewInit, if (this.readAsBinary) { reader.readAsBinaryString(file.file); } else { - reader.readAsText(file.file); + file.file.arrayBuffer().then(buf => { + const bytes = new Uint8Array(buf); + let text: string; + try { + text = new TextDecoder('utf-8', {fatal: true}).decode(bytes); + } catch { + text = new TextDecoder('iso-8859-1').decode(bytes); + } + Object.defineProperty(reader, 'readyState', {value: FileReader.DONE, configurable: true}); + Object.defineProperty(reader, 'result', {value: text, configurable: true}); + reader.onload(new ProgressEvent('load') as ProgressEvent); + }).catch(() => reader.onerror(new ProgressEvent('error') as ProgressEvent)); } }); }