Base64 UTF-8 Decode in RPGLE almost successful

Other open source tools published on ScottKlement.com
Post Reply
jjacobs207
Posts: 16
Joined: Mon Aug 07, 2023 5:59 pm

Base64 UTF-8 Decode in RPGLE almost successful

Post by jjacobs207 »

I'm trying to decode a Base64 string that was Base64 encoded from UTF-8, and it works except that the trailing blanks (x'40') are displaying as '@' signs. I know an '@' sign in UTF-8 is x'40', which is a blank in CCSID 37. I just don't know what to do about it.

For example, "Charlie Brown" encodes to "Q2hhcmxpZSBCcm93bg==", so decoding it should result in "Charlie Brown". It does. However, how do I avoid the x'40'-'@' sign issue?

Here's my code:
/IF DEFINED(*CRTBNDRPG)
h dftactgrp(*no) actgrp(*caller)
/ENDIF
h option(*srcstmt:*nodebugio)
h bnddir('BASE64/BASE64')

/copy base64_h

d regstr2 s a len(1000) varying ccsid(*utf8)
d b64str2 s a len(1000) varying
d retlen s 10i 0
* Max length is 52 for DSPLY
d wrkdsply s 52a

/free
b64str2 = 'Q2hhcmxpZSBCcm93bg==';
%len(regstr2) = %len(regstr2:*max);
retlen = base64_decode(%addr(b64str2:*data):%len(b64str2):
%addr(regstr2:*data):%len(regstr2:*max));

dsply 'Q2hhcmxpZSBCcm93bg== Base64 UTF-8 decoded:';
dsply 'Value S/B Charlie Brown';
eval wrkdsply = regstr2;
dsply wrkdsply;

* Displays "Charlie Brown@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"

*inlr = *on;
return;
/end-free
jjacobs207
Posts: 16
Joined: Mon Aug 07, 2023 5:59 pm

Re: Base64 UTF-8 Decode in RPGLE almost successful

Post by jjacobs207 »

I realized that variable retlen is being set to 13, the length of "Charlie Brown".

Either of the following statements fix the issue:
%len(regstr2) = retlen;
OR
regstr2 = %subst(regstr2:1:retlen);

If anyone has any other thoughts, I would welcome them.
Scott Klement
Site Admin
Posts: 799
Joined: Sun Jul 04, 2021 5:12 am

Re: Base64 UTF-8 Decode in RPGLE almost successful

Post by Scott Klement »

The way your example is coded (before you set the length in the subsequent message) you seemed to be assuming that base64_decode knew that regstr2 was a varchar field and was automatically setting its length for you. in reality, all you're passing is the address of the data portion of the variable, so it only knows that spot in memory nothing else. So its decoding to that spot in memory and returning the length of data that it placed there.

The @@@@ comes from the blanks that you already had in regstr2 before calling base64_decode -- since you were ignoring the returned length, any blanks that came after the decoded data were thought to also be part of the data

The correct fix (one of the ones you already arrived at) is to set the length of regstr2 to the length that base64_decode returns.

Code: Select all

%len(regstr2) = %len(regstr2:*max); 
retlen = base64_decode(%addr(b64str2:*data):%len(b64str2):
%addr(regstr2:*data):%len(regstr2:*max));
%len(regstr2) = retlen;  <---
The %substr version also works, i guess... but requires more work for the computer since it's not just setting a number, it's also copying the data.
jjacobs207
Posts: 16
Joined: Mon Aug 07, 2023 5:59 pm

Re: Base64 UTF-8 Decode in RPGLE almost successful

Post by jjacobs207 »

Thanks for the explanation, Scott!
Post Reply