From 39c5cc45d49b9f23116164164109ed4c45329154 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 26 May 2015 14:56:18 +0200 Subject: [PATCH 1/5] fix #2012 --- eth/main.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index a57928e72..4ac462d64 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -628,7 +628,7 @@ int main(int argc, char** argv) nodeMode == NodeMode::Full ? set{"eth"/*, "shh"*/} : set(), netPrefs, &nodesState); - + auto toNumber = [&](string const& s) -> unsigned { if (s == "latest") return web3.ethereum()->number(); @@ -693,15 +693,18 @@ int main(int argc, char** argv) } if (keyManager.exists()) - while (masterPassword.empty()) - { - masterPassword = getPassword("Please enter your MASTER password: "); - if (!keyManager.load(masterPassword)) + if (!masterPassword.empty()) + keyManager.load(masterPassword); + else + while (masterPassword.empty()) { - cout << "Password invalid. Try again." << endl; - masterPassword.clear(); + masterPassword = getPassword("Please enter your MASTER password: "); + if (!keyManager.load(masterPassword)) + { + cout << "Password invalid. Try again." << endl; + masterPassword.clear(); + } } - } else { while (masterPassword.empty()) From df3313046b1129aee39a62a6a50169c87f3071f4 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 28 May 2015 17:05:52 +0200 Subject: [PATCH 2/5] - add validation for input parameters. - ui bug fix. --- mix/qml.qrc | 1 + mix/qml/QIntTypeView.qml | 7 +++ mix/qml/TransactionDialog.qml | 23 ++++++- mix/qml/js/InputValidator.js | 112 ++++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 mix/qml/js/InputValidator.js diff --git a/mix/qml.qrc b/mix/qml.qrc index c47a7254f..784404270 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -63,5 +63,6 @@ qml/js/Printer.js qml/js/ansi2html.js qml/js/NetworkDeployment.js + qml/js/InputValidator.js diff --git a/mix/qml/QIntTypeView.qml b/mix/qml/QIntTypeView.qml index a3c67aafc..c42e65654 100644 --- a/mix/qml/QIntTypeView.qml +++ b/mix/qml/QIntTypeView.qml @@ -21,8 +21,15 @@ Item clip: true selectByMouse: true text: value + anchors.fill: parent font.pointSize: dbgStyle.general.basicFontSize color: dbgStyle.general.basicColor + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: textinput.forceActiveFocus() + } } } } diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index e7fe22e51..a4c896d3f 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -6,6 +6,7 @@ import QtQuick.Window 2.0 import QtQuick.Controls.Styles 1.3 import org.ethereum.qml.QEther 1.0 import "js/TransactionHelper.js" as TransactionHelper +import "js/InputValidator.js" as InputValidator import "." Dialog { @@ -503,10 +504,22 @@ Dialog { anchors.right: parent.right; Button { + text: qsTr("OK"); onClicked: { - close(); - accepted(); + var invalid = InputValidator.validate(paramsModel, paramValues); + if (invalid.length === 0) + { + close(); + accepted(); + } + else + { + errorDialog.text = qsTr("some parameters are invalid:\n"); + for (var k in invalid) + errorDialog.text += invalid[k].message + "\n"; + errorDialog.open(); + } } } @@ -514,6 +527,12 @@ Dialog { text: qsTr("Cancel"); onClicked: close(); } + + MessageDialog { + id: errorDialog + standardButtons: StandardButton.Ok + icon: StandardIcon.Critical + } } } } diff --git a/mix/qml/js/InputValidator.js b/mix/qml/js/InputValidator.js new file mode 100644 index 000000000..6e94dec6e --- /dev/null +++ b/mix/qml/js/InputValidator.js @@ -0,0 +1,112 @@ +var nbRegEx = new RegExp('^[0-9]+$'); +function validate(model, values) +{ + var inError = []; + for (var k in model) + { + if (values[model[k].name]) + { + var type = model[k].type.name; + var res; + if (type.indexOf("int") !== -1) + res = validateInt(type, values[model[k].name]); + else if (type.indexOf("bytes") !== -1) + res = validateBytes(type, values[model[k].name]); + else if (type.indexOf("bool") !== -1) + res = validateBool(type, values[model[k].name]); + else if (type.indexOf("address") !== -1) + res = validateAddress(type, values[model[k].name]); + else + res = validateAddress(type, values[model[k].name]); //we suppose that this is a ctr type. + if (!res.valid) + inError.push({ type: type, value: values, message: res.message }); + } + } + return inError; +} + +function validateInt(_type, _value) +{ + var ret = { valid: true, message: "" } + if (_value.indexOf("-") === 0) + { + _value = _value.substring(1); + if (_type.indexOf("uint") === -1) + { + ret.valid = false; + ret.message = "uint type cannot represent negative number"; + return false; + } + } + ret.valid = nbRegEx.test(_value); + if (!ret.valid) + ret.message = _value + " does not represent " + _type + " type."; + else + { + var t = _type.replace("uint", "").replace("int", ""); + var max = parseInt(t) / 4; + if (_value.length > max) + { + ret.valid = false; + ret.message = _type + " should not contains more than " + max + " digits"; + } + } + return ret; +} + +function validateAddress(_type, _value) +{ + var ret = { valid: true, message: "" } + if (_value.indexOf("<") === 0 && _value.indexOf(">") === _value.length - 1) + { + var v = _value.split(' - '); + console.log(JSON.stringify(v)); + if (v.length !== 2 || !nbRegEx.test(v[1].replace(">", ""))) // + { + ret.valid = false; + ret.message = _value + " is not a valid token for address type."; + } + } + else if (_value.indexOf("0x") !== 0) + { + ret.valid = false + ret.message = "Address type should start with 0x."; + } + else + { + _value = _value.substring(2); + if (_value.length !== 40) + { + ret.valid = false + ret.message = "Address type should contain 40 characters."; + } + } + return ret; +} + +function validateBytes(_type, _value) +{ + var ret = { valid: true, message: "" } + if (_value.length > parseInt(_type.replace("bytes", "")) ) + { + ret.valid = false; + ret.message = _type + " should not contains more than " + _type.replace("bytes", "") + " characters"; + } + return ret; +} + +function validateBool(_type, _value) +{ + var ret = { valid: true, message: "" } + if (_value !== "1" && _value !== "0") + { + ret.valid = false; + ret.message = _value + " is not in the correct bool format"; + } + return ret; +} + +function validateEnum(_type, _value) +{ +} + From 1482599e521d1406611969eceeb6e8c593a84544 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 29 May 2015 16:28:30 +0200 Subject: [PATCH 3/5] - Check uint, int input from c++. - Check address also by contract name. --- mix/QBigInt.cpp | 35 +++++++++++++++++++++++++++++++++++ mix/QBigInt.h | 3 +++ mix/qml/TransactionDialog.qml | 2 +- mix/qml/js/InputValidator.js | 29 +++++++++++++++++++++-------- 4 files changed, 60 insertions(+), 9 deletions(-) diff --git a/mix/QBigInt.cpp b/mix/QBigInt.cpp index 21d32a9c3..ee29cea43 100644 --- a/mix/QBigInt.cpp +++ b/mix/QBigInt.cpp @@ -57,3 +57,38 @@ QBigInt* QBigInt::divide(QBigInt* const& _value) const BigIntVariant toDivide = _value->internalValue(); return new QBigInt(boost::apply_visitor(mix::divide(), m_internalValue, toDivide)); } + +QVariantMap QBigInt::checkAgainst(QString const& _type) const +{ + QVariantMap ret; + QString type = _type; + QString capacity = type.replace("uint", "").replace("int", ""); + if (capacity.isEmpty()) + capacity = "256"; + bigint range = 256^(capacity.toInt() / 8); + bigint value = boost::get(this->internalValue()); + ret.insert("valid", true); + if (_type.startsWith("uint") && value > range - 1) + { + ret.insert("minValue", "0"); + std::ostringstream s; + s << range - 1; + ret.insert("maxValue", QString::fromStdString(s.str())); + if (value > range) + ret["valid"] = false; + } + else if (_type.startsWith("int")) + { + range = range / 2; + std::ostringstream s; + s << -range; + ret.insert("minValue", QString::fromStdString(s.str())); + s.str(""); + s.clear(); + s << range - 1; + ret.insert("maxValue", QString::fromStdString(s.str())); + if (-range > value || value > range - 1) + ret["valid"] = false; + } + return ret; +} diff --git a/mix/QBigInt.h b/mix/QBigInt.h index b549a16db..ccf487d2a 100644 --- a/mix/QBigInt.h +++ b/mix/QBigInt.h @@ -84,6 +84,7 @@ public: Q_INVOKABLE QString value() const; /// Set the value of the BigInteger used. Will use u256 type. Invokable from QML. Q_INVOKABLE void setValue(QString const& _value) { m_internalValue = dev::jsToU256(_value.toStdString()); } + Q_INVOKABLE void setBigInt(QString const& _value) { m_internalValue = bigint(_value.toStdString()); } /// Subtract by @a _value. Invokable from QML. Q_INVOKABLE QBigInt* subtract(QBigInt* const& _value) const; /// Add @a _value to the current big integer. Invokable from QML. @@ -92,6 +93,8 @@ public: Q_INVOKABLE QBigInt* multiply(QBigInt* const& _value) const; /// divide by @a _value. Invokable from QML. Q_INVOKABLE QBigInt* divide(QBigInt* const& _value) const; + /// check if the current value satisfy the given type + Q_INVOKABLE QVariantMap checkAgainst(QString const& _type) const; protected: BigIntVariant m_internalValue; diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index a4c896d3f..df5ad781b 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -515,7 +515,7 @@ Dialog { } else { - errorDialog.text = qsTr("some parameters are invalid:\n"); + errorDialog.text = qsTr("Some parameters are invalid:\n"); for (var k in invalid) errorDialog.text += invalid[k].message + "\n"; errorDialog.open(); diff --git a/mix/qml/js/InputValidator.js b/mix/qml/js/InputValidator.js index 6e94dec6e..37185b898 100644 --- a/mix/qml/js/InputValidator.js +++ b/mix/qml/js/InputValidator.js @@ -1,3 +1,5 @@ +Qt.include("QEtherHelper.js") + var nbRegEx = new RegExp('^[0-9]+$'); function validate(model, values) { @@ -8,7 +10,9 @@ function validate(model, values) { var type = model[k].type.name; var res; - if (type.indexOf("int") !== -1) + if (isContractType(type)) + res = validateAddress(type, values[model[k].name]); + else if (type.indexOf("int") !== -1) res = validateInt(type, values[model[k].name]); else if (type.indexOf("bytes") !== -1) res = validateBytes(type, values[model[k].name]); @@ -17,7 +21,7 @@ function validate(model, values) else if (type.indexOf("address") !== -1) res = validateAddress(type, values[model[k].name]); else - res = validateAddress(type, values[model[k].name]); //we suppose that this is a ctr type. + res.valid = true; if (!res.valid) inError.push({ type: type, value: values, message: res.message }); } @@ -25,6 +29,16 @@ function validate(model, values) return inError; } +function isContractType(_type) +{ + for (var k in Object.keys(codeModel.contracts)) + { + if ("contract " + Object.keys(codeModel.contracts)[k] === _type) + return true; + } + return false; +} + function validateInt(_type, _value) { var ret = { valid: true, message: "" } @@ -35,7 +49,6 @@ function validateInt(_type, _value) { ret.valid = false; ret.message = "uint type cannot represent negative number"; - return false; } } ret.valid = nbRegEx.test(_value); @@ -43,12 +56,13 @@ function validateInt(_type, _value) ret.message = _value + " does not represent " + _type + " type."; else { - var t = _type.replace("uint", "").replace("int", ""); - var max = parseInt(t) / 4; - if (_value.length > max) + var bigInt = createBigInt(_value); + bigInt.setBigInt(_value); + var result = bigInt.checkAgainst(_type); + if (!result.valid) { ret.valid = false; - ret.message = _type + " should not contains more than " + max + " digits"; + ret.message = _type + " should be between " + result.minValue + " and " + result.maxValue; } } return ret; @@ -60,7 +74,6 @@ function validateAddress(_type, _value) if (_value.indexOf("<") === 0 && _value.indexOf(">") === _value.length - 1) { var v = _value.split(' - '); - console.log(JSON.stringify(v)); if (v.length !== 2 || !nbRegEx.test(v[1].replace(">", ""))) // { ret.valid = false; From 74c46b8298a9c69327441c8fd4596f2d2566f6c6 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 29 May 2015 16:34:34 +0200 Subject: [PATCH 4/5] rollback --- eth/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/eth/main.cpp b/eth/main.cpp index 645465234..b7bdee78b 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -628,7 +628,6 @@ int main(int argc, char** argv) nodeMode == NodeMode::Full ? set{"eth"/*, "shh"*/} : set(), netPrefs, &nodesState); - auto toNumber = [&](string const& s) -> unsigned { if (s == "latest") return web3.ethereum()->number(); From 05c47db94769bac8afe7f18171c9c6a04f275f4a Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 29 May 2015 16:39:07 +0200 Subject: [PATCH 5/5] rollback --- eth/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/eth/main.cpp b/eth/main.cpp index b7bdee78b..645465234 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -628,6 +628,7 @@ int main(int argc, char** argv) nodeMode == NodeMode::Full ? set{"eth"/*, "shh"*/} : set(), netPrefs, &nodesState); + auto toNumber = [&](string const& s) -> unsigned { if (s == "latest") return web3.ethereum()->number();