Sanitize publication responses from server (#4230)

diff --git a/lib/src/http.dart b/lib/src/http.dart
index 74efc18..8ff7c77 100644
--- a/lib/src/http.dart
+++ b/lib/src/http.dart
@@ -222,7 +222,9 @@
       parsed['success']['message'] is! String) {
     invalidServerResponse(response);
   }
-  log.message(log.green(parsed['success']['message'] as String));
+  log.message(
+    'Message from server: ${log.green(sanitizeForTerminal(parsed['success']['message'] as String))}',
+  );
 }
 
 /// Handles an unsuccessful JSON-formatted response from pub.dev.
@@ -243,7 +245,9 @@
       error['message'] is! String) {
     invalidServerResponse(response);
   }
-  fail(log.red(error['message'] as String));
+  fail(
+    'Message from server: ${log.red(sanitizeForTerminal(error['message'] as String))}',
+  );
 }
 
 /// Handles an unsuccessful XML-formatted response from google cloud storage.
@@ -269,13 +273,13 @@
       // `Details` are not specified in the doc above, but have been observed in actual responses.
       final details = getTagText('Details');
       if (code != null) {
-        log.error('Server error code: $code');
+        log.error('Server error code: ${sanitizeForTerminal(code)}');
       }
       if (message != null) {
-        log.error('Server message: $message');
+        log.error('Server message: ${sanitizeForTerminal(message)}');
       }
       if (details != null) {
-        log.error('Server details: $details');
+        log.error('Server details: ${sanitizeForTerminal(details)}');
       }
     }
   }
diff --git a/test/lish/archives_and_uploads_a_package_test.dart b/test/lish/archives_and_uploads_a_package_test.dart
index e06253a..2c3f917 100644
--- a/test/lish/archives_and_uploads_a_package_test.dart
+++ b/test/lish/archives_and_uploads_a_package_test.dart
@@ -34,7 +34,10 @@
     });
 
     expect(pub.stdout, emits(startsWith('Uploading...')));
-    expect(pub.stdout, emits('Package test_pkg 1.0.0 uploaded!'));
+    expect(
+      pub.stdout,
+      emits('Message from server: Package test_pkg 1.0.0 uploaded!'),
+    );
     await pub.shouldExit(exit_codes.SUCCESS);
   });
 
@@ -62,7 +65,10 @@
     });
 
     expect(pub.stdout, emits(startsWith('Uploading...')));
-    expect(pub.stdout, emits('Package test_pkg 1.0.0 uploaded!'));
+    expect(
+      pub.stdout,
+      emits('Message from server: Package test_pkg 1.0.0 uploaded!'),
+    );
     await pub.shouldExit(exit_codes.SUCCESS);
   });
 
@@ -95,7 +101,10 @@
     });
 
     expect(pub.stdout, emits(startsWith('Uploading...')));
-    expect(pub.stdout, emits('Package test_pkg 1.0.0 uploaded!'));
+    expect(
+      pub.stdout,
+      emits('Message from server: Package test_pkg 1.0.0 uploaded!'),
+    );
     await pub.shouldExit(exit_codes.SUCCESS);
   });
 
@@ -134,13 +143,17 @@
     globalServer.expect('GET', '/create', (request) {
       return shelf.Response.ok(
         jsonEncode({
-          'success': {'message': 'Package test_pkg 1.0.0 uploaded!'},
+          'success': {'message': 'Package test_pkg 1.0.0\u0000uploaded!'},
+          // The \u0000 should be sanitized to a space.
         }),
       );
     });
 
     expect(pub.stdout, emits(startsWith('Uploading...')));
-    expect(pub.stdout, emits('Package test_pkg 1.0.0 uploaded!'));
+    expect(
+      pub.stdout,
+      emits('Message from server: Package test_pkg 1.0.0 uploaded!'),
+    );
     await pub.shouldExit(exit_codes.SUCCESS);
   });
 
diff --git a/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart b/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart
index cf05b23..7b0484e 100644
--- a/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart
+++ b/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart
@@ -31,6 +31,9 @@
     });
 
     await pub.shouldExit(exit_codes.SUCCESS);
-    expect(pub.stdout, emitsThrough('Package test_pkg 1.0.0 uploaded!'));
+    expect(
+      pub.stdout,
+      emitsThrough('Message from server: Package test_pkg 1.0.0 uploaded!'),
+    );
   });
 }
diff --git a/test/lish/force_publishes_if_there_are_warnings_test.dart b/test/lish/force_publishes_if_there_are_warnings_test.dart
index ca423f9..2e6a1fb 100644
--- a/test/lish/force_publishes_if_there_are_warnings_test.dart
+++ b/test/lish/force_publishes_if_there_are_warnings_test.dart
@@ -52,6 +52,9 @@
         ),
       ]),
     );
-    expect(pub.stdout, emitsThrough('Package test_pkg 1.0.0 uploaded!'));
+    expect(
+      pub.stdout,
+      emitsThrough('Message from server: Package test_pkg 1.0.0 uploaded!'),
+    );
   });
 }
diff --git a/test/lish/many_files_test.dart b/test/lish/many_files_test.dart
index 2d99c81..1897310 100644
--- a/test/lish/many_files_test.dart
+++ b/test/lish/many_files_test.dart
@@ -123,7 +123,10 @@
     });
 
     expect(pub.stdout, emits(startsWith('Uploading...')));
-    expect(pub.stdout, emits('Package test_pkg 1.0.0 uploaded!'));
+    expect(
+      pub.stdout,
+      emits('Message from server: Package test_pkg 1.0.0 uploaded!'),
+    );
     await pub.shouldExit(exit_codes.SUCCESS);
   });
 }
diff --git a/test/lish/package_creation_provides_an_error_test.dart b/test/lish/package_creation_provides_an_error_test.dart
index 9fd5e48..564aa42 100644
--- a/test/lish/package_creation_provides_an_error_test.dart
+++ b/test/lish/package_creation_provides_an_error_test.dart
@@ -30,7 +30,10 @@
       );
     });
 
-    expect(pub.stderr, emits('Your package was too boring.'));
+    expect(
+      pub.stderr,
+      emits('Message from server: Your package was too boring.'),
+    );
     await pub.shouldExit(1);
   });
 }
diff --git a/test/lish/package_validation_has_a_warning_and_continues_test.dart b/test/lish/package_validation_has_a_warning_and_continues_test.dart
index f1854d4..61c169a 100644
--- a/test/lish/package_validation_has_a_warning_and_continues_test.dart
+++ b/test/lish/package_validation_has_a_warning_and_continues_test.dart
@@ -38,6 +38,9 @@
     });
 
     await pub.shouldExit(exit_codes.SUCCESS);
-    expect(pub.stdout, emitsThrough('Package test_pkg 1.0.0 uploaded!'));
+    expect(
+      pub.stdout,
+      emitsThrough('Message from server: Package test_pkg 1.0.0 uploaded!'),
+    );
   });
 }
diff --git a/test/lish/publishing_to_and_from_archive_test.dart b/test/lish/publishing_to_and_from_archive_test.dart
index 8d3ee5c..9e2e6bf 100644
--- a/test/lish/publishing_to_and_from_archive_test.dart
+++ b/test/lish/publishing_to_and_from_archive_test.dart
@@ -49,7 +49,10 @@
     handleUpload(server);
 
     expect(pub.stdout, emitsThrough(startsWith('Uploading...')));
-    expect(pub.stdout, emits('Package test_pkg 1.0.0 uploaded!'));
+    expect(
+      pub.stdout,
+      emits('Message from server: Package test_pkg 1.0.0 uploaded!'),
+    );
     await pub.shouldExit(SUCCESS);
   });
 }
diff --git a/test/lish/unicode_file_names_test.dart b/test/lish/unicode_file_names_test.dart
index 64d9a09..a07e207 100644
--- a/test/lish/unicode_file_names_test.dart
+++ b/test/lish/unicode_file_names_test.dart
@@ -34,7 +34,10 @@
     });
 
     expect(pub.stdout, emits(startsWith('Uploading...')));
-    expect(pub.stdout, emits('Package test_pkg 1.0.0 uploaded!'));
+    expect(
+      pub.stdout,
+      emits('Message from server: Package test_pkg 1.0.0 uploaded!'),
+    );
     await pub.shouldExit(exit_codes.SUCCESS);
   });
 
diff --git a/test/lish/upload_form_provides_an_error_test.dart b/test/lish/upload_form_provides_an_error_test.dart
index fbbf129..f39e824 100644
--- a/test/lish/upload_form_provides_an_error_test.dart
+++ b/test/lish/upload_form_provides_an_error_test.dart
@@ -11,7 +11,7 @@
 import '../test_pub.dart';
 
 void main() {
-  test('upload form provides an error', () async {
+  test('upload form provides an error, that is sanitized', () async {
     await servePackages();
     await d.validPackage().create();
     await d.credentialsFile(globalServer, 'access-token').create();
@@ -22,12 +22,14 @@
     globalServer.expect('GET', '/api/packages/versions/new', (request) async {
       return shelf.Response.notFound(
         jsonEncode({
-          'error': {'message': 'your request sucked'},
+          'error': {
+            'message': 'your request\u0000sucked',
+          }, // The \u0000 should be sanitized to a space.
         }),
       );
     });
 
-    expect(pub.stderr, emits('your request sucked'));
+    expect(pub.stderr, emits('Message from server: your request sucked'));
     await pub.shouldExit(1);
   });
 }
diff --git a/test/testdata/goldens/lish/many_files_test/displays all files.txt b/test/testdata/goldens/lish/many_files_test/displays all files.txt
index c9c364c..b293ff6 100644
--- a/test/testdata/goldens/lish/many_files_test/displays all files.txt
+++ b/test/testdata/goldens/lish/many_files_test/displays all files.txt
@@ -39,4 +39,4 @@
 
 Do you want to publish test_pkg 1.0.0 to http://localhost:$PORT (y/N)?
 Uploading...
-Package test_pkg 1.0.0 uploaded!
\ No newline at end of file
+Message from server: Package test_pkg 1.0.0 uploaded!
\ No newline at end of file