convert icon indicating copy to clipboard operation
convert copied to clipboard

Can't decode a base64 string with newlines. Is this the intended behavior?

Open fujidaiti opened this issue 1 year ago • 0 comments

Base64Decoder cannot convert a base64 string that is split to blocks of a certain length by newlines, like:

PGEgaHJlZj0iaHR0cHM6Ly9mbHV0dGVyLmRldi8iPgogIDxoMSBhbGlnbj0i
Y2VudGVyIj4KICAgIDxwaWN0dXJlPgogICAgICA8c291cmNlIG1lZGlhPSIo
cHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIiBzcmNzZXQ9Imh0dHBzOi8v

Is this the intended behavior? The base64 command can decode it, but I don't know which behavior is the way it should be.

# This shell command works fine.
$ echo "PGEgaHJlZj0iaHR0cHM6Ly9mbHV0dGVyLmRldi8iPgogIDxoMSBhbGlnbj0i
Y2VudGVyIj4KICAgIDxwaWN0dXJlPgogICAgICA8c291cmNlIG1lZGlhPSIo
cHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIiBzcmNzZXQ9Imh0dHBzOi8v" | base64 --decode

<a href="https://flutter.dev/">
  <h1 align="center">
    <picture>
      <source media="(prefers-color-scheme: dark)" srcset="https://%                                         

Background

I found this when trying to get the README of a GitHub repository using the REST API. It returns the README file as a base64 encoded string that is split into blocks of a certain length by newlines. I tried to convert this to a String, but always failed while decoding the baase64 string to Unit8List.

// Dart 3.0.5
// http: ^1.1.0

import 'dart:convert';

import 'package:http/http.dart' as http;

// GitHub API:
// https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#get-a-repository-readme
void main() async {
  const owner = "flutter";
  const repo = "flutter";
  final url = Uri.https(
    "api.github.com",
    "repos/$owner/$repo/readme",
  );
  final response = await http.get(
    url,
    headers: {
      "accept": "application/vnd.github+json",
    },
  );
  final json = jsonDecode(response.body);
  // This ↓ line causes "FormatException: Invalid character"
  final content = base64.decode(json["content"]);
  final readme = String.fromCharCodes(content);
  print(readme);
}

Then it throws:

Unhandled exception:
FormatException: Invalid character (at character 61)
PGEgaHJlZj0iaHR0cHM6Ly9mbHV0dGVyLmRldi8iPgogIDxoMSBhbGlnbj0i
                                                            ^

#0      _Base64Decoder.decodeChunk (dart:convert/base64.dart:705:7)
#1      _Base64Decoder.decode (dart:convert/base64.dart:629:14)
#2      Base64Decoder.convert (dart:convert/base64.dart:509:26)
#3      Base64Codec.decode (dart:convert/base64.dart:83:47)
<asynchronous suspension>

Removing the all newlines will fix this problem.

final content = base64.decode(json["content"].replaceAll("\n", ""));

You can see the returned json from the API as follows:

curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/flutter/flutter/readme

fujidaiti avatar Jul 04 '23 02:07 fujidaiti