Base64URL

There is a variation of Base64 called Base64URL that’s essentially Base64 with tweaks to allow encoded strings in URLs without conflict. The following code will easily let you encode and decode this:

Public Shared Function EncodeBase64URL(value As String) as String
  if value = "" then
    return ""
  end if
  
  dim result as string = EncodeBase64( value )
  
  result = ReplaceLineEndings( result, "" )
  result = result.ReplaceAllB( "+", "-" )
  result = result.ReplaceAllB( "/", "_" )
  result = result.ReplaceAllB( "=", "" )
  
  return result.DefineEncoding( Encodings.UTF8 )
End Function

Public Shared Function DecodeBase64URL(value As String) as String
  if value = "" then
    return ""
  end if
  
  value = value.ReplaceAllB( "-", "+" )
  value = value.ReplaceAllB( "_", "/" )
  
  //
  // The native decoder doesn't care about the padding ("=") so
  // we don't have to bother putting it back in
  //
  
  dim result as string = DecodeBase64( value )
  return result
End Function

Enjoy.

1 Like

Hi Kem,

Thank you for the sharing.

What about an URL in this format:

https://safr.kingfeatures.com/idn/ck3/content.php?file=

Nota: I removed the part after ?file= (this was an encoded string, useless here).

Also: I may have missed the point. If so, sorry.

If you want to include binary or even long text data in a url, it has to be encoded somehow. You can encode individual bytes (%01 for cntl-A or + for a space, for example), hex-encode the data, or use Base64URL. You can’t use regular Base64 because it 1) includes line breaks, and 2) may include characters that have special meaning in a url like “/”.

See

https://brockallen.com/2014/10/17/base64url-encoding/

Wouldn’t you just use the EncodeURLComponent() for your Base64 value?

Encoding URL information, to be used in either HTTP GET or POST requests, applies to the “value” of an argument, where that value may contain URL reserved characters like /, =, + and spaces. The encoding function shouldn’t care whether the value is a Base64 string or just some other string type value.

In JavaScript, there is a similar function called encodeURIComponent, which would be used like the following:

var url = 'http://example.com/redirectTo?target=' + encodeURIComponent('http://example.org/') 

It’s the value of “target” that needs to be URL encoded. Which would result in a value like http%3a%2f%2fexample.org%2f.

I’m sure constructing a URL “string” in Xojo to contain your Base64 information would be similar, except using the EncodeURLComponent() method of course. Something like:

Dim url As String = 'http://example.com/redirectTo?target=' + EncodeURLComponent(myBase64StringVar) 

Note: Base64 strings tend to be very long (depending on your content) and there are limits to how long a URL can be, before browsers, proxies or other network points will fail to handle the request.

The upper limit to the length of URL is difficult to gauge, because it depends on many factors, but I would put that limit at about 2,000 characters. Your mileage may vary.

I hope that helps, but my apologies if I misunderstood what you’re trying to do.

Edit: I realize you’re offering an alternative solution @Kem Tekinay, but I guess my first thought was about whether you’re controlling both ends of the URL (the sender and the recipient). Because both would require using your custom function. Whereas sending with an RFC standards compliant URL encoding method would allow the recipient to decode the value using the corresponding standards compliant method as well (where the recipient may be using a different platform than Xojo).

Base64URL is rfc compliant, used in, for example, a json web token. I merely offered code that will make dealing with it easier.

I should add, until just the other day, I hadn’t heard of it either. :slight_smile:

My bad, I didn’t read the link you gave later. I thought this was just about generic URL encoding.

Yes, you’re quite right Kem, JWT tokens are the exception case (RFC 4648). I didn’t get that part. My apologies.

In which case, nicely done. Thank you.

I forgot about the lineWrap parameter in EncodeBase64 so this code is better:

Public Shared Function EncodeBase64URL(value As String) as String
  if value = "" then
    return ""
  end if
  
  dim result as string = EncodeBase64( value, 0 )
  
  result = result.ReplaceAllB( "+", "-" )
  result = result.ReplaceAllB( "/", "_" )
  if result.RightB( 2 ) = "==" then
    result = result.LeftB( result.LenB - 2 )
  elseif result.RightB( 1 ) = "=" then
    result = result.LeftB( result.LenB - 1 )
  end if
  
  return result.DefineEncoding( Encodings.UTF8 )
End Function

@Kem_Tekinay did you happen to make a Base64URL for iOS? Is it as easy as taking this code and changing the Strings to Text and I assume how we handle the ReplaceLineEndings etc.?

This relies on EncodeBase64 which, if memory serves, does not exist in iOS (yet), but does live in my M_Text module.

It should be easy to adapt the code to Text through that.

You are correct sir but I do have declares for encode/decode64.

Thanks Kem!

I also have your M_Text module which has both as you know :wink:

Ill post my work on this in the iOS channel later on. Thanks @Kem_Tekinay