From d19006670d905050ae771d1c45211163f6c7b7d9 Mon Sep 17 00:00:00 2001
From: xuty <xty50337@hotmail.com>
Date: Sun, 12 Dec 2021 23:44:30 +0800
Subject: [PATCH] Fix listObjects signing error when folder name includes space
 #34

---
 lib/src/minio_helpers.dart | 29 +++++++++++++++++++++++++++++
 lib/src/minio_sign.dart    |  4 ++--
 test/minio_test.dart       | 11 +++++++++++
 3 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/lib/src/minio_helpers.dart b/lib/src/minio_helpers.dart
index bebc4ff..b5cf6a3 100644
--- a/lib/src/minio_helpers.dart
+++ b/lib/src/minio_helpers.dart
@@ -270,3 +270,32 @@ String encodePath(Uri uri) {
   }
   return result.toString();
 }
+
+final _queryIgnoredChars = {
+  '-'.codeUnitAt(0),
+  '_'.codeUnitAt(0),
+  '.'.codeUnitAt(0),
+  '~'.codeUnitAt(0),
+};
+
+/// encode [uri].path to HTML hex escape sequence
+String encodeCanonicalQuery(String query) {
+  final result = StringBuffer();
+  for (var char in query.codeUnits) {
+    if (_A <= char && char <= _Z ||
+        _a <= char && char <= _z ||
+        _0 <= char && char <= _9) {
+      result.writeCharCode(char);
+      continue;
+    }
+
+    if (_queryIgnoredChars.contains(char)) {
+      result.writeCharCode(char);
+      continue;
+    }
+
+    result.write('%');
+    result.write(hex.encode([char]).toUpperCase());
+  }
+  return result.toString();
+}
diff --git a/lib/src/minio_sign.dart b/lib/src/minio_sign.dart
index 9f62262..c507ac1 100644
--- a/lib/src/minio_sign.dart
+++ b/lib/src/minio_sign.dart
@@ -54,8 +54,8 @@ String getCanonicalRequest(
   final requestQuery = queryKeys.map((key) {
     final value = request.url.queryParameters[key];
     final hasValue = value != null;
-    final valuePart = hasValue ? Uri.encodeQueryComponent(value!) : '';
-    return Uri.encodeQueryComponent(key) + '=' + valuePart;
+    final valuePart = hasValue ? encodeCanonicalQuery(value!) : '';
+    return encodeCanonicalQuery(key) + '=' + valuePart;
   }).join('&');
 
   final canonical = [];
diff --git a/test/minio_test.dart b/test/minio_test.dart
index 7faadbc..481220a 100644
--- a/test/minio_test.dart
+++ b/test/minio_test.dart
@@ -91,6 +91,17 @@ void testListBuckets() {
     await minio.removeBucket(bucketName2);
   });
 
+  test('listBuckets() can list buckets with spaces in name', () async {
+    final minio = getMinioClient();
+    final bucketName = uniqueName() + '  folder';
+    await minio.makeBucket(bucketName);
+
+    final buckets = await minio.listBuckets();
+    expect(buckets.any((b) => b.name == bucketName), isTrue);
+
+    await minio.removeBucket(bucketName);
+  });
+
   test('listBuckets() fails due to wrong access key', () async {
     final minio = getMinioClient(accessKey: 'incorrect-access-key');
 
-- 
GitLab