Skip to content

Commit 0575ca9

Browse files
authored
Handle binary data in Base64 to string conversion (#14) (#18)
1 parent 5194dd7 commit 0575ca9

4 files changed

Lines changed: 75 additions & 21 deletions

File tree

src/Convert/Public/ConvertFrom-Base64ToString.ps1

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,19 @@ function ConvertFrom-Base64ToString {
8585
$ptr = [ConvertCoreInterop]::base64_to_string($s, $Encoding)
8686

8787
if ($ptr -eq $nullPtr) {
88-
$errorMsg = GetRustError -DefaultMessage "Base64 decoding failed for encoding '$Encoding'"
89-
throw $errorMsg
88+
$rustError = GetRustError -DefaultMessage ''
89+
if ($rustError -match 'Invalid UTF-8|Invalid ASCII|Invalid UTF-16|Invalid UTF-32') {
90+
# Binary data - fall back to Latin-1 which can represent any byte
91+
$bytes = [System.Convert]::FromBase64String($s)
92+
[System.Text.Encoding]::GetEncoding('ISO-8859-1').GetString($bytes)
93+
} elseif ($rustError) {
94+
throw $rustError
95+
} else {
96+
throw "Base64 decoding failed for encoding '$Encoding'"
97+
}
98+
} else {
99+
ConvertPtrToString -Ptr $ptr
90100
}
91-
92-
ConvertPtrToString -Ptr $ptr
93101
} finally {
94102
if ($ptr -ne $nullPtr) {
95103
[ConvertCoreInterop]::free_string($ptr)

src/Convert/Public/ConvertTo-String.ps1

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -133,33 +133,38 @@ function ConvertTo-String {
133133
}
134134

135135
process {
136-
$splat = @{}
137136
switch ($PSCmdlet.ParameterSetName) {
138137
'Base64String' {
139-
$InputObject = $Base64EncodedString
140-
$Function = 'ConvertFrom-Base64ToString'
141-
$splat.Add('Encoding', $Encoding)
142-
if ($Decompress) {
143-
$splat.Add('Decompress', $true)
138+
foreach ($b64 in $Base64EncodedString) {
139+
try {
140+
if ($Decompress) {
141+
$b64 | ConvertFrom-Base64ToString -Encoding $Encoding -Decompress -ErrorAction Stop
142+
} else {
143+
try {
144+
ConvertFrom-Base64ToString -String $b64 -Encoding $Encoding -ErrorAction Stop
145+
} catch {
146+
if ($_.Exception.Message -match 'does not represent valid .+ text') {
147+
# Binary data - fall back to Latin-1 which can represent any byte
148+
$bytes = [System.Convert]::FromBase64String($b64)
149+
[System.Text.Encoding]::GetEncoding('ISO-8859-1').GetString($bytes)
150+
} else {
151+
throw
152+
}
153+
}
154+
}
155+
} catch {
156+
Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
157+
}
144158
}
145-
break
146159
}
147160

148161
'MemoryStream' {
149-
$InputObject = $MemoryStream
150-
$Function = 'ConvertFrom-MemoryStreamToString'
151-
break
162+
$MemoryStream | ConvertFrom-MemoryStreamToString -ErrorAction $userErrorActionPreference
152163
}
153164

154165
'Stream' {
155-
$InputObject = $Stream
156-
$Function = 'ConvertFrom-MemoryStreamToString'
157-
break
166+
$Stream | ConvertFrom-MemoryStreamToString -ErrorAction $userErrorActionPreference
158167
}
159168
}
160-
161-
if ($InputObject) {
162-
$InputObject | & $Function @splat -ErrorAction $userErrorActionPreference
163-
}
164169
}
165170
}

src/Tests/Unit/ConvertFrom-Base64ToString.Tests.ps1

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,26 @@ Describe -Name $function -Fixture {
9696
$base64 = 'SGVsbG8'
9797
{ ConvertFrom-Base64ToString -String $base64 -Encoding 'UTF8' -ErrorAction Stop } | Should -Throw
9898
}
99+
100+
It -Name 'Converts binary data (non-UTF8) without error' -Test {
101+
$binaryBytes = [byte[]](0xA1, 0x59, 0xC0, 0xA5, 0xE4, 0x94, 0xFF, 0x00, 0x80)
102+
$base64 = [System.Convert]::ToBase64String($binaryBytes)
103+
104+
$result = ConvertFrom-Base64ToString -String $base64
105+
106+
$result | Should -Not -BeNullOrEmpty
107+
$result | Should -BeOfType [string]
108+
}
109+
110+
It -Name 'Round-trips binary data through Latin-1 fallback' -Test {
111+
$binaryBytes = [byte[]](0xA1, 0x59, 0xC0, 0xA5, 0xE4, 0x94, 0xFF, 0x00, 0x80)
112+
$base64 = [System.Convert]::ToBase64String($binaryBytes)
113+
114+
$resultString = ConvertFrom-Base64ToString -String $base64
115+
$resultBytes = [System.Text.Encoding]::GetEncoding('ISO-8859-1').GetBytes($resultString)
116+
117+
$resultBytes | Should -Be $binaryBytes
118+
}
99119
}
100120

101121
Context -Name 'Error Handling' -Fixture {

src/Tests/Unit/ConvertTo-String.Tests.ps1

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,27 @@ Describe -Name $function -Fixture {
3636

3737
$assertion | Should -BeExactly $String
3838
}
39+
40+
It -Name 'Converts binary data (non-UTF8) without error' -Test {
41+
# Binary data that is not valid UTF-8 (e.g., certificate/image data)
42+
$binaryBytes = [byte[]](0xA1, 0x59, 0xC0, 0xA5, 0xE4, 0x94, 0xFF, 0x00, 0x80)
43+
$base64 = [System.Convert]::ToBase64String($binaryBytes)
44+
45+
$assertion = ConvertTo-String -Base64EncodedString $base64
46+
47+
$assertion | Should -Not -BeNullOrEmpty
48+
$assertion | Should -BeOfType [string]
49+
}
50+
51+
It -Name 'Round-trips binary data through Latin-1 fallback' -Test {
52+
$binaryBytes = [byte[]](0xA1, 0x59, 0xC0, 0xA5, 0xE4, 0x94, 0xFF, 0x00, 0x80)
53+
$base64 = [System.Convert]::ToBase64String($binaryBytes)
54+
55+
$resultString = ConvertTo-String -Base64EncodedString $base64
56+
$resultBytes = [System.Text.Encoding]::GetEncoding('ISO-8859-1').GetBytes($resultString)
57+
58+
$resultBytes | Should -Be $binaryBytes
59+
}
3960
}
4061

4162
Context -Name 'MemoryStream input' -Fixture {

0 commit comments

Comments
 (0)