[Filesystem] Add support for ISO-8859-1 23/247923/2
authorJakub Skowron <j.skowron@samsung.com>
Tue, 23 Jan 2018 12:19:10 +0000 (13:19 +0100)
committerPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Wed, 18 Nov 2020 10:54:38 +0000 (11:54 +0100)
Latin-1 encoding in FileReadString and FileWriteString

Change-Id: I2cd7942481619989891c3019d3f7d4325b962892
Signed-off-by: Jakub Skowron <j.skowron@samsung.com>
src/filesystem/filesystem_instance.cc
src/filesystem/js/file_stream.js

index f7beef2..dc698bb 100644 (file)
@@ -175,6 +175,13 @@ static void decode_binary_from_string(const std::string& str, std::vector<std::u
   }
 }
 
+namespace latin1 {
+static auto to_utf8 = &encode_binary_in_string;
+/* It does not check if UTF-8 values are representable by ISO-8859-1. Make proper checks and
+ * substitute invalid characters in JavaScript before passing through crosswalk */
+static auto from_utf8 = &decode_binary_from_string;
+}
+
 static constexpr std::size_t NPOS = (std::size_t)(-1);
 /**
  * Returns a buffer. If length is NPOS, then it reads whole file, up to the end.
@@ -336,19 +343,25 @@ void FilesystemInstance::FileReadString(const picojson::value& args, picojson::o
   CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemRead, &out);
   CHECK_EXIST(args, "location", out)
   CHECK_EXIST(args, "offset", out)
-  CHECK_EXIST(args, "encoding", out)
 
   const std::string& location = args.get("location").get<std::string>();
   size_t offset = static_cast<size_t>(args.get("offset").get<double>());
   size_t length = args.contains("length") ? (size_t)args.get("length").get<double>() : NPOS;
+  const std::string& encoding =
+      args.contains("encoding") ? args.get("encoding").get<std::string>() : "utf-8";
 
   try {
-    std::vector<std::uint8_t> out_data = read_file(location, offset, length);
-    out_data.push_back('\0');
-    const char* str = (const char*)out_data.data();
+    std::vector<std::uint8_t> buf = read_file(location, offset, length);
 
-    // TODO: support iso-8859-1 (latin-1) encoding
-    ReportSuccess(picojson::value{str}, out);
+    if (encoding == "iso-8859-1") {
+      out["result"] = picojson::value(picojson::string_type, true);
+      latin1::to_utf8(buf, out["result"].get<std::string>());
+      ReportSuccess(out);
+    } else {  // default: UTF-8
+      buf.push_back('\0');
+      const char* str = (const char*)buf.data();
+      ReportSuccess(picojson::value{str}, out);
+    }
   } catch (std::runtime_error& e) {
     LoggerE("Cannot read file %s, cause: %s", location.c_str(), e.what());
     PrepareError(FilesystemError::Other, out);
@@ -385,15 +398,24 @@ void FilesystemInstance::FileWriteString(const picojson::value& args, picojson::
   CHECK_EXIST(args, "data", out)
   CHECK_EXIST(args, "offset", out)
   CHECK_EXIST(args, "rewrite", out)
-  CHECK_EXIST(args, "encoding", out)
 
   const std::string& location = args.get("location").get<std::string>();
   const std::string& str = args.get("data").get<std::string>();
   size_t offset = static_cast<size_t>(args.get("offset").get<double>());
   bool rewrite = static_cast<bool>(args.get("rewrite").get<bool>());
+  const std::string& encoding =
+      args.contains("encoding") ? args.get("encoding").get<std::string>() : "utf-8";
 
   try {
-    write_file((const std::uint8_t*)str.c_str(), str.length(), location, offset, rewrite);
+    if (encoding == "iso-8859-1") {
+      std::vector<std::uint8_t> data;
+      latin1::from_utf8(str, data);
+      write_file(data.data(), data.size(), location, offset, rewrite);
+    } else {  // default: UTF-8
+      const std::uint8_t* buf = (const std::uint8_t*)str.c_str();
+      std::size_t len = str.length();
+      write_file(buf, len, location, offset, rewrite);
+    }
   } catch (std::runtime_error& e) {
     LoggerE("Cannot write to file %s, cause: %s", location.c_str(), e.what());
     PrepareError(FilesystemError::Other, out);
index a81ead3..7703a88 100644 (file)
@@ -243,6 +243,18 @@ FileStream.prototype.readBase64 = function() {
     return base64_encode(readBytes.apply(this, arguments));
 };
 
+function check_characters_outside_latin1(str) {
+    var len = str.length;
+    for (var i = 0; i < len; ++i) {
+        if (str.charCodeAt(i) > 255) {
+            throw new WebAPIException(
+                WebAPIException.IO_ERR,
+                'Invalid character at ' + i + ': ' + str.charAt(i) + ' (not ISO-8859-1)'
+            );
+        }
+    }
+}
+
 function write() {
     var args = validator_.validateArgs(arguments, [
         {
@@ -269,6 +281,10 @@ function write() {
         rewrite: this._rewrite
     };
 
+    if (data.encoding == 'iso-8859-1') {
+        check_characters_outside_latin1(data.data);
+    }
+
     var result = native_.callSync('File_writeString', data);
 
     if (native_.isFailure(result)) {