PHP and Progress 4GL

Posted by wsartorelli on 28-Jun-2018 08:57

Good Morning.
Please can anyone tell me if there is a difference between Progress's BASE64-ENCODE function and PHP's base_encode function?
Or BASE-DECODE of Progress and PHP_base_decode?

All Replies

Posted by on 29-Jun-2018 00:08

There is a difference.  Equivalent PHP, Javascript and Java functions all give the same result, Progress gives a different result.

E.g. Encoding the string "SomeStringOfText:1234"
PHP (encodeBase64): U29tZVN0cmluZ09mVGV4dDoxMjM0
Progress (BASE64-ENCODE): U29tZVN0cmluZ09mVGV4dDoxMjM0AA==

The "AA==" on the end of the Progress string is reasonably consistent but I couldn’t find any docs or logged issues to explain the difference.

Rather than risking it on a production system we went with a call to PHP to do the encoding.

Posted by bronco on 29-Jun-2018 01:54

The AA== stuff has undoubtedly to do with how string are terminated which it itself is not that interesting. If I decode your PHP encoded string in OpenEdge I get the exact same string as you inputted in PHP. The other way around works perfectly as well.

I'm 100% certain if you have the exact same byte sequence as input for your encode functions the results will be the same.

Posted by Stefan Drissen on 29-Jun-2018 02:40

def var mptr as memptr.

mptr = ( base64-decode( "AA==" ) ).

message get-size( mptr ) get-byte( mptr, 1 ).

So if you are ending with AA== then you are probably sizing your strings 1 byte too large resulting in a 0 terminator.

Posted by bronco on 29-Jun-2018 03:26

when you do:

SET-SIZE(mptr) = LENGTH(inputString) + 1.

PUT-STRING(mptr, 1) = inputString.

You have add 1 to the length or the string will not fit and then it's zero terminated. That's where the "AA==" is coming from. Instead of adding 1 to the size you can restrict the amount of bytes written to the memptr by:

SET-SIZE(mptr) = LENGTH(inputString).

PUT-STRING(mptr, 1, LENGTH(inputString, "RAW")) = inputString.

Then you get the same output as Java, PHP, etc...

note: the "RAW" parameter with the length function should be used when using multi-byte codepages (i.e. utf-8).

Posted by bronco on 29-Jun-2018 03:27

And of course the second SET-SIZE has to be LENGTH(inputString, "RAW") as well.

Posted by bronco on 29-Jun-2018 03:32

So, no need to use PHP. I fail to see why anyone would consider using PHP in 2018 anyway :-)

(flame alert).

Posted by wsartorelli on 29-Jun-2018 10:07

My template is made in PHP, which I did in Progress 4GL is returning a signature other than PHP.

Posted by wsartorelli on 29-Jun-2018 10:17

My code is:


DEF VAR stringtosign AS CHAR NO-UNDO.



ASSIGN apiid = "b4t5yug1q6du"

             apisecret = "UJe7NicGijgkTSKByC+/B86NDafeGYGDXsxJKiLKH8LE9ni5whmTdof6QgR6vGXonn0htVOLsRXRcpEg4QPWSA==".

ASSIGN dat_ref = 'x-csod-date:2018-06-28T13:37:35.000'.

ASSIGN httpMethod = 'POST'

      apiKey     = 'x-csod-api-key:' + apiId

      httpUrl    = '/services/api/sts/session'.

      stringToSign = httpMethod + "\n" + apiKey + "\n" + dat_ref + "\n" + httpUrl.

ASSIGN secretKey = base64-DECODE(apiSecret).

ASSIGN c_signature = BASE64-ENCODE (MESSAGE-DIGEST('SHA-512', stringToSign, secretKey)).

The result of the c_signature variable is different if I put the same code in PHP.

Why ?

Posted by Stefan Drissen on 29-Jun-2018 10:44

Your \n's look suspicious to me - they will result in line feeds (chr 10) on Linux and a literal \n on windows. If you use ~n it will be a line feed on both.

results in


Posted by wsartorelli on 29-Jun-2018 12:09

My friend, I put this "signature" in POSTMAN, and sent, the same error occurs, using the "\ n".

Posted by Peter Judge on 29-Jun-2018 16:42

In ABL you get a null-terminated string.

In the HTTP Client we have code that has to deal woith this. See for detail.

Posted by on 01-Jul-2018 21:41


Definition: The moment when you realise the vast dimensions of the blind spot previously applied when examining an issue.

Thank you.

Posted by on 01-Jul-2018 21:47

Have you tried this?

stringToSign = httpMethod + CHR(10) + apiKey + CHR(10) + dat_ref + CHR(10) + httpUrl.

Posted by bronco on 02-Jul-2018 00:42

[mention:9e4ee96fac634b8f91b580e1fb4f7e71:e9ed411860ed4f2ba0265705b8793d05] : any particular reason why you don't do

set-size(mShortCredentials) = iLength.

put-bytes(mShortCredentials, 1, iLength) = cCredentials.

straight away?

Posted by wsartorelli on 02-Jul-2018 15:01

Yes, I tried and the answer keeps returning differently, between PHP and Progress.

Posted by Peter Judge on 05-Jul-2018 11:09

You can't PUT-BYTES with a string as the source. And PUT-STRING requires a null trailing byte (the +1).

Posted by Brian K. Maher on 05-Jul-2018 11:18

PUT-STRING doesn’t need the +1 if you use the optional third parameter to specify how many bytes to write.  When doing stuff with encoding, encrypting, etc you probably want to use the third parameter and skip the +1 since every bit is important.
Brian Maher
Principal Engineer, Technical Support
14 Oak Park | Bedford, MA 01730 | USA
+1 781 280 3075

Posted by Peter Judge on 05-Jul-2018 12:18

Nice … one learns something new every day.

This thread is closed