From 26fe1711e3ab829b9f94a05d79dad54a7feda004 Mon Sep 17 00:00:00 2001 From: Kamil Leszczuk Date: Mon, 26 May 2014 21:28:33 +0200 Subject: [PATCH] Bug 1003723: Support for UTF-16 encoded RTD_TEXT NDEF records --- apps/system/js/nfc_manager.js | 14 ++++----- apps/system/test/unit/nfc_manager_test.js | 6 ++-- apps/system/test/unit/nfc_utils_test.js | 18 +++++++++++ shared/js/nfc_utils.js | 37 ++++++++++++++++++++++- 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/apps/system/js/nfc_manager.js b/apps/system/js/nfc_manager.js index 8f01840b9239..cacba1e695c9 100644 --- a/apps/system/js/nfc_manager.js +++ b/apps/system/js/nfc_manager.js @@ -454,17 +454,17 @@ var NfcManager = { formatTextRecord: function nm_formatTextRecord(record) { var status = record.payload[0]; - var languageLength = status & NDEF.RTD_TEXT_IANA_LENGTH; + var langLen = status & NDEF.RTD_TEXT_IANA_LENGTH; var language = NfcUtils.toUTF8( - record.payload.subarray(1, languageLength + 1)); - var encoding = status & NDEF.RTD_TEXT_ENCODING; + record.payload.subarray(1, langLen + 1)); + var encoding = (status & NDEF.RTD_TEXT_ENCODING) !== 0 ? 1 : 0; var text; var encodingString; - if (encoding == NDEF.RTD_TEXT_UTF8) { - text = NfcUtils.toUTF8(record.payload.subarray(languageLength + 1)); + if (encoding === NDEF.RTD_TEXT_UTF8) { + text = NfcUtils.toUTF8(record.payload.subarray(langLen + 1)); encodingString = 'UTF-8'; - } else if (encoding == NDEF.RTD_TEXT_UTF16) { - text = NfcUtils.toUTF16(record.payload.subarray(languageLength + 2)); + } else if (encoding === NDEF.RTD_TEXT_UTF16) { + text = NfcUtils.UTF16BytesToString(record.payload.subarray(langLen + 1)); encodingString = 'UTF-16'; } diff --git a/apps/system/test/unit/nfc_manager_test.js b/apps/system/test/unit/nfc_manager_test.js index d50e0043db3e..da296e02c47c 100644 --- a/apps/system/test/unit/nfc_manager_test.js +++ b/apps/system/test/unit/nfc_manager_test.js @@ -192,7 +192,6 @@ suite('Nfc Manager Functions', function() { assert.equal(activityOptions.data.encoding, 'UTF-8'); }); - /* should be uncommented once Bug 1003723 will be fixed test('TNF well known rtd text utf 16', function() { var payload = Uint8Array([0x82, 0x65, 0x6E, 0xFF, 0xFE, 0x48, 0x00, 0x6F, @@ -207,12 +206,13 @@ suite('Nfc Manager Functions', function() { new Uint8Array(), payload)]; - var activityOptions = execCommonTest(dummyNdefMsg); + var activityOptions = execCommonTest(dummyNdefMsg, 'text'); + assert.equal(activityOptions.data.text, 'Ho! UTF-16 en'); assert.equal(activityOptions.data.rtd, NDEF.RTD_TEXT); assert.equal(activityOptions.data.language, 'en'); assert.equal(activityOptions.data.encoding, 'UTF-16'); - });*/ + }); test('TNF well known rtd uri', function() { var payload = new Uint8Array([0x04, 0x77, 0x69, 0x6B, diff --git a/apps/system/test/unit/nfc_utils_test.js b/apps/system/test/unit/nfc_utils_test.js index 2e424a234e49..5b4978465092 100644 --- a/apps/system/test/unit/nfc_utils_test.js +++ b/apps/system/test/unit/nfc_utils_test.js @@ -63,6 +63,24 @@ suite('NFC Utils', function() { assert.equal(nullStr, null); }); + suite('String <> byte conversions', function() { + test('UTF16BytesToString', function() { + assert.equal('©', NfcUtils.UTF16BytesToString([0xFE, 0xFF, 0x00, 0xA9])); + assert.equal('©', NfcUtils.UTF16BytesToString([0xFF, 0xFE, 0xA9, 0x00])); + assert.equal('ą', NfcUtils.UTF16BytesToString([0x01, 0x05])); + + var foxArr = [0x00, 0x42, 0x00, 0x69, 0x00, 0x67, 0x00, 0x20, 0x00, 0x62, + 0x00, 0x72, 0x00, 0x6F, 0x00, 0x77, 0x00, 0x6E, 0x00, 0x20, + 0x00, 0x66, 0x00, 0x6F, 0x00, 0x78, 0x00, 0x21, 0x00, 0x20, + 0x00, 0x44, 0x00, 0x75, 0x01, 0x7C, 0x00, 0x79, 0x00, 0x20, + 0x00, 0x62, 0x00, 0x72, 0x01, 0x05, 0x00, 0x7A, 0x00, 0x6F, + 0x00, 0x77, 0x00, 0x79, 0x00, 0x20, 0x00, 0x6C, 0x00, 0x69, + 0x00, 0x73, 0x00, 0x3F]; + var foxTxt = 'Big brown fox! Duży brązowy lis?'; + assert.equal(foxTxt, NfcUtils.UTF16BytesToString(foxArr)); + }); + }); + suite('NDEF Conversions', function() { var urlNDEF; // MozNDEFRecord var urlU8a; // Uint8Array diff --git a/shared/js/nfc_utils.js b/shared/js/nfc_utils.js index 4f36e25aaad5..19b89e59691b 100644 --- a/shared/js/nfc_utils.js +++ b/shared/js/nfc_utils.js @@ -100,7 +100,7 @@ const NDEF = { }, RTD_TEXT_IANA_LENGTH: 0x3F, - RTD_TEXT_ENCODING: 0x40, + RTD_TEXT_ENCODING: 0x80, RTD_TEXT_UTF8: 0, RTD_TEXT_UTF16: 1 }; @@ -232,6 +232,41 @@ NfcUtils = { return str; }, + /** + * Decodes UTF-16 bytes array into a String + * + * @param {Array} array containing UTF-16 encoded bytes + * @return {String} + */ + UTF16BytesToString: function UTF16BytesToString(array) { + // if BOM not present Big-endian should be used + // NFCForum-TS-RTD_Text_1.0 + var offset1 = 0, offset2 = 1, i = 0; + + if (array[0] === 0xFE && array[1] === 0xFF) { + i = 2; + } else if (array[0] === 0xFF && array[1] === 0xFE) { + i = 2; + offset1 = 1; + offset2 = 0; + } + + var str = ''; + for (var len = array.length; i < len; i += 2) { + var b1 = array[i + offset1]; + if (b1 < 0xD8 || b1 >= 0xE0) { + var b2 = array[i + offset2]; + var word = (b1 << 8) + b2; + str += String.fromCharCode(word); + } else { + i += 2; + // as for now we handle only BMP characters + } + } + + return str; + }, + /***************************************************************************** * createBuffer: returns a NfcBuffer helper object that makes it easier to * read from a Uint8Array.