How to identify a Base64-encoded string

In my current project I’ve created a Web Service-consumer in NAV that maps payload-data flexible using the Data Exchange Definition. Unfortunately in REST- and SOAP-payloads, binary information (JPG, PDF etc.)  is delivered as a string. So, I’ve got a little task to find a way to differ between a string (like an address line) and binary information.

As all REST- and SOAP-Web Services, the payload of the Web Service I’m using, delivers the payload as a structured, but simple text-file. This means, all data is delivered in Text-format. But to be able, for example, to store price-information in the database and use it in mathematical calculations, it is necessary to transform the value from Text to Decimal. My Web Service-consumer is able to read the payload, to identify and to transform the DataTypes automatically. But as soon as binary information will be delivered in the payload, my consumer reaches a limit because the binary information would be stored as Text.

Luckily, all binary information of a REST- or SOAP-service will be encoded in Base64-format, so it is an easy task to identify whether it’s a regular text-value (like a company name or delivery instructions) or binary-information.

Encoded data will always have the following characteristic:

  • The length of a Base64-encoded string is always a multiple of 4
  • Only these characters are used by the encryption: “A” to “Z”, “a” to “z”, “0” to “9”, “+” and “/”
  • The end of a string can be padded up to two times using the “=”-character (this character is allowed in the end only)


Edit 23rd April 2021:

I have written this blog post based on my work in the ERP-application Microsoft Dynamics 365 Business Central which has a domain specific programming language (it is very old and resembles Pascal). But, some search engines decided to use this blog post as the #1 organice search result. If you current project is in Java, C++, JavaScript or Python, then please have a look in this Stackoverflow-thread that deals with this topic too: https://stackoverflow.com/questions/8571501/how-to-check-whether-a-string-is-base64-encoded-or-not

If you are interested in C/AL-code, please checkout the code below.


Identification of Base64 in C/AL

Based on this information it was possible to build a function that is able to identify the value of a string as Base64-encoded.

LOCAL PROCEDURE isBase64@1000000002(pVariant@1000000000 : Variant) : Boolean;
VAR
 i@1000000001 : Integer;
BEGIN
 // the length of a base64 is always a multiple of 4
 // allowed characters in a base64 are: 'A'..'Z', 'a'..'z', '0'..'9', '+', '/'
 // the end can be padded with up to 2 '='

 // check if the length is a multiple of 4
 IF (STRLEN(FORMAT(pVariant,0,9)) / 4 MOD 1) <> 0 THEN
   EXIT(FALSE);

 // check each character if allowed
 FOR i := 1 TO STRLEN(FORMAT(pVariant,0,9)) DO
 IF NOT (COPYSTR(FORMAT(pVariant,0,9),i,1) IN ['A'..'Z', 'a'..'z', '0'..'9', '+', '/']) THEN
   BEGIN
   // if not allowed character found, check if already at end of string (and check for '=')
     IF (i = STRLEN(FORMAT(pVariant,0,9))-1) OR
        (i = STRLEN(FORMAT(pVariant,0,9)))
     THEN
       BEGIN
         IF COPYSTR(FORMAT(pVariant,0,9),i,1) <> '=' THEN
           EXIT(FALSE);
       END
     ELSE
       EXIT(FALSE);
     END;

   EXIT(TRUE);
END;

Additionally, I’ve created a function that decodes the Base64-string and stores it in a BLOB-field.

[TryFunction]
LOCAL PROCEDURE TryToStoreVariantAsBLOB@1000000001(pVariant@1000000000 : Variant;VAR pTempBLOB@1000000001 : TEMPORARY Record 99008535);
VAR
 BlobWriter@1000000004 : OutStream;
 Convert@1000000003 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Convert";
 MemoryStream@1000000002 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.IO.MemoryStream";
BEGIN
 MemoryStream := MemoryStream.MemoryStream(Convert.FromBase64String(pVariant));
 pTempBLOB.Blob.CREATEOUTSTREAM(BlobWriter);
 MemoryStream.CopyTo(BlobWriter);
END;

I have compiled the two functions into a Codeunit (including an example) and published for download on mibuso.com.

More
articles

%d bloggers like this: