From 9bd8c5f723abef25b8864457df7207eb361be8e3 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 6 Mar 2017 15:03:49 -0800 Subject: [PATCH] Render personal_sign messages as utf-8 text Calls to `personal_sign` are now: - When hex encoded, preserved as hex encoded, but displayed as utf-8 text. - When not hex encoded, decoded as utf-8 text as hex for signing. - The messages proposed for signing are displayed as UTF-8 text. - When the message cannot be rendered as UTF-8 text, it is displayed as hexadecimal. Fixes #1173 --- app/scripts/lib/personal-message-manager.js | 22 ++++++---- test/unit/components/binary-renderer-test.js | 25 +++++++++++ test/unit/personal-message-manager-test.js | 23 +++++++++- ui/app/components/binary-renderer.js | 43 +++++++++++++++++++ .../pending-personal-msg-details.js | 15 ++----- 5 files changed, 107 insertions(+), 21 deletions(-) create mode 100644 test/unit/components/binary-renderer-test.js create mode 100644 ui/app/components/binary-renderer.js diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 3b8510767..04dba4a90 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -2,6 +2,7 @@ const EventEmitter = require('events') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const createId = require('./random-id') +const hexRe = /^[0-9A-Fa-f]+$/g module.exports = class PersonalMessageManager extends EventEmitter{ @@ -24,7 +25,8 @@ module.exports = class PersonalMessageManager extends EventEmitter{ } addUnapprovedMessage (msgParams) { - msgParams.data = normalizeMsgData(msgParams.data) + log.debug(`PersonalMessageManager addUnapprovedMessage: ${JSON.stringify(msgParams)}`) + msgParams.data = this.normalizeMsgData(msgParams.data) // create txData obj with parameters and meta data var time = (new Date()).getTime() var msgId = createId() @@ -106,14 +108,18 @@ module.exports = class PersonalMessageManager extends EventEmitter{ this.emit('updateBadge') } -} + normalizeMsgData(data) { + try { + const stripped = ethUtil.stripHexPrefix(data) + if (stripped.match(hexRe)) { + return stripped + } + } catch (e) { + log.debug(`Message was not hex encoded, interpreting as utf8.`) + } -function normalizeMsgData(data) { - if (data.slice(0, 2) === '0x') { - // data is already hex - return data - } else { - // data is unicode, convert to hex return ethUtil.bufferToHex(new Buffer(data, 'utf8')) } + } + diff --git a/test/unit/components/binary-renderer-test.js b/test/unit/components/binary-renderer-test.js new file mode 100644 index 000000000..3264faddc --- /dev/null +++ b/test/unit/components/binary-renderer-test.js @@ -0,0 +1,25 @@ +var assert = require('assert') +var BinaryRenderer = require('../../../ui/app/components/binary-renderer') + +describe('BinaryRenderer', function() { + + let binaryRenderer + const message = 'Hello, world!' + const buffer = new Buffer(message, 'utf8') + const hex = buffer.toString('hex') + + beforeEach(function() { + binaryRenderer = new BinaryRenderer() + }) + + it('recovers message', function() { + const result = binaryRenderer.hexToText(hex) + assert.equal(result, message) + }) + + + it('recovers message with hex prefix', function() { + const result = binaryRenderer.hexToText('0x' + hex) + assert.equal(result, message) + }) +}) diff --git a/test/unit/personal-message-manager-test.js b/test/unit/personal-message-manager-test.js index 657d5e675..69d373ed3 100644 --- a/test/unit/personal-message-manager-test.js +++ b/test/unit/personal-message-manager-test.js @@ -4,7 +4,7 @@ const EventEmitter = require('events') const PersonalMessageManager = require('../../app/scripts/lib/personal-message-manager') -describe('Transaction Manager', function() { +describe('Personal Message Manager', function() { let messageManager beforeEach(function() { @@ -86,4 +86,25 @@ describe('Transaction Manager', function() { assert.equal(messageManager.getMsg('2').status, 'approved') }) }) + + describe('#normalizeMsgData', function() { + it('converts text to a utf8 buffer', function() { + var input = 'hello' + var output = messageManager.normalizeMsgdata(input) + assert.equal(output, '68656c6c6f', 'predictably hex encoded') + }) + + it('tolerates a hex prefix', function() { + var input = '0x12' + var output = messageManager.normalizeMsgdata(input) + assert.equal(output, '12', 'prefix stripped') + }) + + it('tolerates normal hex', function() { + var input = '12' + var output = messageManager.normalizeMsgdata(input) + assert.equal(output, '12', 'not modified') + }) + }) + }) diff --git a/ui/app/components/binary-renderer.js b/ui/app/components/binary-renderer.js new file mode 100644 index 000000000..a9d49b128 --- /dev/null +++ b/ui/app/components/binary-renderer.js @@ -0,0 +1,43 @@ +const Component = require('react').Component +const h = require('react-hyperscript') +const inherits = require('util').inherits +const ethUtil = require('ethereumjs-util') + +module.exports = BinaryRenderer + +inherits(BinaryRenderer, Component) +function BinaryRenderer () { + Component.call(this) +} + +BinaryRenderer.prototype.render = function () { + const props = this.props + const { value } = props + const text = this.hexToText(value) + + return ( + h('textarea.font-small', { + readOnly: true, + style: { + width: '315px', + maxHeight: '210px', + resize: 'none', + border: 'none', + background: 'white', + padding: '3px', + }, + defaultValue: text, + }) + ) +} + +BinaryRenderer.prototype.hexToText = function (hex) { + try { + const stripped = ethUtil.stripHexPrefix(hex) + const buff = Buffer.from(stripped, 'hex') + return buff.toString('utf8') + } catch (e) { + return hex + } +} + diff --git a/ui/app/components/pending-personal-msg-details.js b/ui/app/components/pending-personal-msg-details.js index ffd11ca0b..afd04fc51 100644 --- a/ui/app/components/pending-personal-msg-details.js +++ b/ui/app/components/pending-personal-msg-details.js @@ -3,6 +3,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const AccountPanel = require('./account-panel') +const BinaryRenderer = require('./binary-renderer') module.exports = PendingMsgDetails @@ -21,6 +22,7 @@ PendingMsgDetails.prototype.render = function () { var account = state.accounts[address] || { address: address } var { data } = msgParams + console.dir({ msgParams }) return ( h('div', { @@ -41,18 +43,7 @@ PendingMsgDetails.prototype.render = function () { // message data h('div', [ h('label.font-small', { style: { display: 'block' } }, 'MESSAGE'), - h('textarea.font-small', { - readOnly: true, - style: { - width: '315px', - maxHeight: '210px', - resize: 'none', - border: 'none', - background: 'white', - padding: '3px', - }, - defaultValue: data, - }), + h(BinaryRenderer, { value: data }), ]), ])