Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Backport #6707, #6702 & #6701 #6713

Merged
merged 4 commits into from
Oct 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion js/src/api/util/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,13 @@ export function bytesToAscii (bytes) {
}

export function asciiToHex (string) {
return '0x' + string.split('').map((s) => s.charCodeAt(0).toString(16)).join('');
let result = '0x';

for (let i = 0; i < string.length; ++i) {
result += ('0' + string.charCodeAt(i).toString(16)).substr(-2);
}

return result;
}

export function padRight (input, length) {
Expand Down
8 changes: 8 additions & 0 deletions js/src/api/util/format.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ describe('api/util/format', () => {
it('correctly converts a non-empty string', () => {
expect(asciiToHex('abc')).to.equal('0x616263');
});

it('correctly converts where charCode < 0x10', () => {
expect(
asciiToHex(
[32, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0].map((v) => String.fromCharCode(v)).join('')
)
).to.equal('0x20100f0e0d0c0b0a09080706050403020100');
});
});

describe('hexToAscii', () => {
Expand Down
4 changes: 2 additions & 2 deletions js/src/ui/Form/InputAddressSelect/inputAddressSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ class InputAddressSelect extends Component {

const filteredContacts = nextAllowedValues
? pick(contacts, nextAllowedValues)
: accounts;
: contacts;

const filteredContracts = nextAllowedValues
? pick(contracts, nextAllowedValues)
: accounts;
: contracts;

return (
<AddressSelect
Expand Down
8 changes: 4 additions & 4 deletions js/src/views/Signer/components/SignRequest/signRequest.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
}

.signData {
background: rgba(255,255,255, 0.25);
border: 0.25em solid red;
margin-left: 2em;
padding: 0.5em;
font-size: 0.75em;
padding: 0.5rem;
overflow: auto;
max-height: 6em;
max-width: calc(100% - 2em);
max-height: 10em;
}

.signData > p {
Expand Down
70 changes: 46 additions & 24 deletions js/src/views/Signer/components/SignRequest/signRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import { observer } from 'mobx-react';
import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import ReactMarkdown from 'react-markdown';

import { hexToAscii } from '~/api/util/format';
import HardwareStore from '~/mobx/hardwareStore';

import Account from '../Account';
Expand All @@ -28,16 +30,39 @@ import RequestOrigin from '../RequestOrigin';
import styles from './signRequest.css';

function isAscii (data) {
for (var i = 2; i < data.length; i += 2) {
for (let i = 2; i < data.length; i += 2) {
let n = parseInt(data.substr(i, 2), 16);

if (n < 32 || n >= 128) {
return false;
}
}

return true;
}

function decodeMarkdown (data) {
return decodeURIComponent(escape(hexToAscii(data)));
}

export function isMarkdown (data) {
try {
const decoded = decodeMarkdown(data);

for (let i = 0; i < decoded.length; i++) {
const code = decoded.charCodeAt(i);

if (code < 32 && code !== 10) {
return false;
}
}

return decoded.indexOf('#') !== -1 || decoded.indexOf('*') !== -1;
} catch (error) {
return false;
}
}

@observer
class SignRequest extends Component {
static contextTypes = {
Expand Down Expand Up @@ -89,29 +114,26 @@ class SignRequest extends Component {
);
}

renderAsciiDetails (ascii) {
return (
<div className={ styles.signData }>
<p>{ascii}</p>
</div>
);
}
renderData (data) {
if (isAscii(data)) {
return hexToAscii(data);
}

if (isMarkdown(data)) {
return (
<ReactMarkdown source={ decodeMarkdown(data) } />
);
}

renderBinaryDetails (data) {
return (
<div className={ styles.signData }>
<p>
<FormattedMessage
id='signer.signRequest.unknownBinary'
defaultMessage='(Unknown binary data)'
/>
</p>
</div>
<FormattedMessage
id='signer.signRequest.unknownBinary'
defaultMessage='(Unknown binary data)'
/>
);
}

renderDetails () {
const { api } = this.context;
const { address, data, netVersion, origin, signerStore } = this.props;
const { balances, externalLink } = signerStore;

Expand All @@ -121,6 +143,8 @@ class SignRequest extends Component {
return <div />;
}

const hashToSign = this.context.api.util.sha3(data);

return (
<div className={ styles.signDetails }>
<div className={ styles.address }>
Expand All @@ -133,18 +157,16 @@ class SignRequest extends Component {
/>
<RequestOrigin origin={ origin } />
</div>
<div className={ styles.info } title={ api.util.sha3(data) }>
<div className={ styles.info } title={ hashToSign }>
<p>
<FormattedMessage
id='signer.signRequest.request'
defaultMessage='A request to sign data using your account:'
/>
</p>
{
isAscii(data)
? this.renderAsciiDetails(api.util.hexToAscii(data))
: this.renderBinaryDetails(data)
}
<div className={ styles.signData }>
<p>{ this.renderData(data) }</p>
</div>
<p>
<strong>
<FormattedMessage
Expand Down
24 changes: 23 additions & 1 deletion js/src/views/Signer/components/SignRequest/signRequest.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import { shallow } from 'enzyme';
import React from 'react';
import sinon from 'sinon';

import SignRequest from './';
import { asciiToHex } from '~/api/util/format';

import SignRequest, { isMarkdown } from './signRequest';

let component;
let reduxStore;
Expand Down Expand Up @@ -81,4 +83,24 @@ describe('views/Signer/components/SignRequest', () => {
it('renders', () => {
expect(component).to.be.ok;
});

describe('isMarkdown', () => {
it('returns true for markdown', () => {
const testMd = '# this is some\n\n*markdown*';
const encodedMd = asciiToHex(unescape(encodeURIComponent(testMd)));

expect(isMarkdown(encodedMd)).to.be.true;
});

it('return true with utf-8 markdown', () => {
const testMd = '# header\n\n(n) you are not a citizen of, or resident in, or located in, or incorporated or otherwise established in, the People\'s Republic of China 参与方并非中华人民共和国公民,或不常住中华人民共和国,或不位于中华人民共和国境内,或并非在中华人民共和国设立或以其他方式组建; and';
const encodedMd = asciiToHex(unescape(encodeURIComponent(testMd)));

expect(isMarkdown(encodedMd)).to.be.true;
});

it('returns false for randow data', () => {
expect(isMarkdown('0x1234')).to.be.false;
});
});
});