Merge branch 'master' into auth-round
This commit is contained in:
commit
12125dcfee
@ -136,7 +136,6 @@ linux-armv7:
|
||||
stage: build
|
||||
image: ethcore/rust-armv7:latest
|
||||
only:
|
||||
- master
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
@ -176,7 +175,6 @@ linux-arm:
|
||||
stage: build
|
||||
image: ethcore/rust-arm:latest
|
||||
only:
|
||||
- master
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
@ -248,7 +246,6 @@ linux-aarch64:
|
||||
stage: build
|
||||
image: ethcore/rust-aarch64:latest
|
||||
only:
|
||||
- master
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
@ -287,7 +284,6 @@ linux-aarch64:
|
||||
darwin:
|
||||
stage: build
|
||||
only:
|
||||
- master
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
@ -308,7 +304,6 @@ darwin:
|
||||
windows:
|
||||
stage: build
|
||||
only:
|
||||
- master
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
@ -322,6 +317,8 @@ windows:
|
||||
- curl -sL --url "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -o nsis\SimpleFC.dll
|
||||
- curl -sL --url "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -o nsis\vc_redist.x64.exe
|
||||
- signtool sign /f %keyfile% /p %certpass% target\release\parity.exe
|
||||
- msbuild windows\ptray\ptray.vcxproj /p:Platform=x86 /p:Configuration=Release
|
||||
- signtool sign /f %keyfile% /p %certpass% windows\ptray\release\ptray.exe
|
||||
- cd nsis
|
||||
- makensis.exe installer.nsi
|
||||
- copy installer.exe InstallParity.exe
|
||||
@ -393,30 +390,14 @@ js-release:
|
||||
- ./js/scripts/release.sh
|
||||
tags:
|
||||
- javascript
|
||||
js-lint:
|
||||
js-tests:
|
||||
stage: build
|
||||
image: ethcore/javascript:latest
|
||||
before_script:
|
||||
- ./js/scripts/install-deps.sh
|
||||
script:
|
||||
- ./js/scripts/lint.sh
|
||||
tags:
|
||||
- javascript-test
|
||||
js-test:
|
||||
stage: build
|
||||
image: ethcore/javascript:latest
|
||||
before_script:
|
||||
- ./js/scripts/install-deps.sh
|
||||
script:
|
||||
- ./js/scripts/test.sh
|
||||
tags:
|
||||
- javascript-test
|
||||
js-pack:
|
||||
stage: build
|
||||
image: ethcore/javascript:latest
|
||||
before_script:
|
||||
- ./js/scripts/install-deps.sh
|
||||
script:
|
||||
- ./js/scripts/build.sh
|
||||
tags:
|
||||
- javascript-test
|
||||
|
101
Cargo.lock
generated
101
Cargo.lock
generated
@ -185,7 +185,7 @@ version = "1.1.1"
|
||||
source = "git+https://github.com/ethcore/rust-ctrlc.git#f4927770f89eca80ec250911eea3adcbf579ac48"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -194,7 +194,7 @@ name = "daemonize"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -244,7 +244,7 @@ source = "git+https://github.com/ethcore/rust-secp256k1#a9a0b1be1f39560ca86e8fc8
|
||||
dependencies = [
|
||||
"arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -352,6 +352,7 @@ dependencies = [
|
||||
"serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"zip 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -370,7 +371,7 @@ version = "1.4.0"
|
||||
dependencies = [
|
||||
"crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.0 (git+https://github.com/carllerche/mio)",
|
||||
"mio 0.6.1 (git+https://github.com/carllerche/mio)",
|
||||
"parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -458,9 +459,9 @@ dependencies = [
|
||||
"ethcrypto 0.1.0",
|
||||
"ethkey 0.2.0",
|
||||
"igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.0 (git+https://github.com/carllerche/mio)",
|
||||
"mio 0.6.1 (git+https://github.com/carllerche/mio)",
|
||||
"parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.1.0",
|
||||
@ -554,7 +555,7 @@ dependencies = [
|
||||
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -618,7 +619,7 @@ dependencies = [
|
||||
"ethkey 0.2.0",
|
||||
"itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -663,7 +664,7 @@ dependencies = [
|
||||
name = "fdlimit"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -681,7 +682,7 @@ name = "flate2"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -802,7 +803,7 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -894,7 +895,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -930,7 +931,7 @@ name = "memchr"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -958,7 +959,7 @@ version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -967,7 +968,7 @@ version = "0.5.1"
|
||||
source = "git+https://github.com/ethcore/mio?branch=v0.5.x#3842d3b250ffd7bd9b16f9586b875ddcbac2b0dd"
|
||||
dependencies = [
|
||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -983,7 +984,7 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -999,7 +1000,7 @@ version = "0.6.0-dev"
|
||||
source = "git+https://github.com/ethcore/mio?branch=timer-fix#31eccc40ece3d47abaefaf23bb2114033175b972"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1010,16 +1011,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/carllerche/mio#9f17b70d6fecbf912168267ea74cf536f2cba705"
|
||||
version = "0.6.1"
|
||||
source = "git+https://github.com/carllerche/mio#56f8663510196fdca04bdf7c5f4d60b24297826f"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1050,7 +1051,7 @@ name = "nanomsg"
|
||||
version = "0.5.1"
|
||||
source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00"
|
||||
dependencies = [
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nanomsg-sys 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||
]
|
||||
|
||||
@ -1060,7 +1061,7 @@ version = "0.5.0"
|
||||
source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00"
|
||||
dependencies = [
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1070,7 +1071,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1081,7 +1082,7 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1091,7 +1092,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1181,7 +1195,7 @@ name = "num_cpus"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1235,7 +1249,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "parity-ui-precompiled"
|
||||
version = "1.4.0"
|
||||
source = "git+https://github.com/ethcore/js-precompiled.git#10a57a7df153360b4abeddff99e5b8f34a85ff53"
|
||||
source = "git+https://github.com/ethcore/js-precompiled.git#f8bd7fa67e91daea3ac698ebcc447fae494802cb"
|
||||
dependencies = [
|
||||
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1246,7 +1260,7 @@ version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1266,7 +1280,7 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1405,7 +1419,7 @@ name = "rand"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1459,7 +1473,7 @@ name = "rocksdb"
|
||||
version = "0.4.5"
|
||||
source = "git+https://github.com/ethcore/rust-rocksdb#64c63ccbe1f62c2e2b39262486f9ba813793af58"
|
||||
dependencies = [
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)",
|
||||
]
|
||||
|
||||
@ -1469,7 +1483,7 @@ version = "0.3.0"
|
||||
source = "git+https://github.com/ethcore/rust-rocksdb#64c63ccbe1f62c2e2b39262486f9ba813793af58"
|
||||
dependencies = [
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1489,7 +1503,7 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1500,7 +1514,7 @@ version = "0.2.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1671,7 +1685,7 @@ name = "syntex_errors"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1693,7 +1707,7 @@ version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1706,7 +1720,7 @@ version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1747,7 +1761,7 @@ name = "termios"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1756,7 +1770,7 @@ version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1773,7 +1787,7 @@ version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -2012,7 +2026,7 @@ dependencies = [
|
||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
|
||||
"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b"
|
||||
"checksum libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "23e3757828fa702a20072c37ff47938e9dd331b92fac6e223d26d4b7a55f7ee2"
|
||||
"checksum libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "408014cace30ee0f767b1c4517980646a573ec61a57957aeeabcac8ac0a02e8d"
|
||||
"checksum linked-hash-map 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bda158e0dabeb97ee8a401f4d17e479d6b891a14de0bba79d5cc2d4d325b5e48"
|
||||
"checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
|
||||
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
|
||||
@ -2024,8 +2038,8 @@ dependencies = [
|
||||
"checksum miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d1f4d337a01c32e1f2122510fed46393d53ca35a7f429cb0450abaedfa3ed54"
|
||||
"checksum mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)" = "<none>"
|
||||
"checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e"
|
||||
"checksum mio 0.6.0 (git+https://github.com/carllerche/mio)" = "<none>"
|
||||
"checksum mio 0.6.0-dev (git+https://github.com/ethcore/mio?branch=timer-fix)" = "<none>"
|
||||
"checksum mio 0.6.1 (git+https://github.com/carllerche/mio)" = "<none>"
|
||||
"checksum miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bfc6782530ac8ace97af10a540054a37126b63b0702ddaaa243b73b5745b9a"
|
||||
"checksum msdos_time 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04b68cc63a8480fb2550343695f7be72effdec953a9d4508161c3e69041c7d8"
|
||||
"checksum nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)" = "<none>"
|
||||
@ -2033,6 +2047,7 @@ dependencies = [
|
||||
"checksum net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a816012ca11cb47009693c1e0c6130e26d39e4d97ee2a13c50e868ec83e3204"
|
||||
"checksum nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f05c2fc965fc1cd6b73fa57fa7b89f288178737f2f3ce9e63e4a6a141189000e"
|
||||
"checksum nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2"
|
||||
"checksum nix 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b"
|
||||
"checksum nodrop 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4d9a22dbcebdeef7bf275cbf444d6521d4e7a2fee187b72d80dba0817120dd8f"
|
||||
"checksum nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6caab12c5f97aa316cb249725aa32115118e1522b445e26c257dd77cad5ffd4e"
|
||||
"checksum num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "c04bd954dbf96f76bab6e5bd6cef6f1ce1262d15268ce4f926d2b5b778fa7af2"
|
||||
|
@ -38,6 +38,8 @@ after_test:
|
||||
- cargo build --verbose --release
|
||||
- ps: if($env:cert) { Start-FileDownload $env:cert -FileName $env:keyfile }
|
||||
- ps: if($env:cert) { signtool sign /f $env:keyfile /p $env:certpass target\release\parity.exe }
|
||||
- msbuild windows\ptray\ptray.vcxproj /p:Platform=x86 /p:Configuration=Release
|
||||
- ps: if($env:cert) { signtool sign /f $env:keyfile /p $env:certpass windows\ptray\release\ptray.exe }
|
||||
- makensis.exe nsis\installer.nsi
|
||||
- ps: if($env:cert) { signtool sign /f $env:keyfile /p $env:certpass nsis\installer.exe }
|
||||
|
||||
|
@ -24,6 +24,7 @@ ethabi = "0.2.2"
|
||||
linked-hash-map = "0.3"
|
||||
parity-dapps-glue = "1.4"
|
||||
mime = "0.2"
|
||||
time = "0.1.35"
|
||||
serde_macros = { version = "0.8", optional = true }
|
||||
zip = { version = "0.1", default-features = false }
|
||||
ethcore-devtools = { path = "../devtools" }
|
||||
|
@ -32,14 +32,15 @@ use random_filename;
|
||||
use SyncStatus;
|
||||
use util::{Mutex, H256};
|
||||
use util::sha3::sha3;
|
||||
use page::LocalPageEndpoint;
|
||||
use page::{LocalPageEndpoint, PageCache};
|
||||
use handlers::{ContentHandler, ContentFetcherHandler, ContentValidator};
|
||||
use endpoint::{Endpoint, EndpointPath, Handler};
|
||||
use apps::cache::{ContentCache, ContentStatus};
|
||||
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest};
|
||||
use apps::urlhint::{URLHintContract, URLHint, URLHintResult};
|
||||
|
||||
const MAX_CACHED_DAPPS: usize = 10;
|
||||
/// Limit of cached dapps/content
|
||||
const MAX_CACHED_DAPPS: usize = 20;
|
||||
|
||||
pub struct ContentFetcher<R: URLHint = URLHintContract> {
|
||||
dapps_path: PathBuf,
|
||||
@ -71,12 +72,13 @@ impl<R: URLHint> ContentFetcher<R> {
|
||||
}
|
||||
}
|
||||
|
||||
fn still_syncing() -> Box<Handler> {
|
||||
fn still_syncing(port: Option<u16>) -> Box<Handler> {
|
||||
Box::new(ContentHandler::error(
|
||||
StatusCode::ServiceUnavailable,
|
||||
"Sync In Progress",
|
||||
"Your node is still syncing. We cannot resolve any content before it's fully synced.",
|
||||
Some("<a href=\"javascript:window.location.reload()\">Refresh</a>")
|
||||
Some("<a href=\"javascript:window.location.reload()\">Refresh</a>"),
|
||||
port,
|
||||
))
|
||||
}
|
||||
|
||||
@ -143,19 +145,19 @@ impl<R: URLHint> ContentFetcher<R> {
|
||||
match content {
|
||||
// Don't serve dapps if we are still syncing (but serve content)
|
||||
Some(URLHintResult::Dapp(_)) if self.sync.is_major_importing() => {
|
||||
(None, Self::still_syncing())
|
||||
(None, Self::still_syncing(self.embeddable_at))
|
||||
},
|
||||
Some(URLHintResult::Dapp(dapp)) => {
|
||||
let (handler, fetch_control) = ContentFetcherHandler::new(
|
||||
dapp.url(),
|
||||
control,
|
||||
path.using_dapps_domains,
|
||||
DappInstaller {
|
||||
id: content_id.clone(),
|
||||
dapps_path: self.dapps_path.clone(),
|
||||
on_done: Box::new(on_done),
|
||||
embeddable_at: self.embeddable_at,
|
||||
}
|
||||
},
|
||||
self.embeddable_at,
|
||||
);
|
||||
|
||||
(Some(ContentStatus::Fetching(fetch_control)), Box::new(handler) as Box<Handler>)
|
||||
@ -164,19 +166,19 @@ impl<R: URLHint> ContentFetcher<R> {
|
||||
let (handler, fetch_control) = ContentFetcherHandler::new(
|
||||
content.url,
|
||||
control,
|
||||
path.using_dapps_domains,
|
||||
ContentInstaller {
|
||||
id: content_id.clone(),
|
||||
mime: content.mime,
|
||||
content_path: self.dapps_path.clone(),
|
||||
on_done: Box::new(on_done),
|
||||
}
|
||||
},
|
||||
self.embeddable_at,
|
||||
);
|
||||
|
||||
(Some(ContentStatus::Fetching(fetch_control)), Box::new(handler) as Box<Handler>)
|
||||
},
|
||||
None if self.sync.is_major_importing() => {
|
||||
(None, Self::still_syncing())
|
||||
(None, Self::still_syncing(self.embeddable_at))
|
||||
},
|
||||
None => {
|
||||
// This may happen when sync status changes in between
|
||||
@ -185,7 +187,8 @@ impl<R: URLHint> ContentFetcher<R> {
|
||||
StatusCode::NotFound,
|
||||
"Resource Not Found",
|
||||
"Requested resource was not found.",
|
||||
None
|
||||
None,
|
||||
self.embeddable_at,
|
||||
)) as Box<Handler>)
|
||||
},
|
||||
}
|
||||
@ -255,6 +258,17 @@ impl ContentValidator for ContentInstaller {
|
||||
// Create dir
|
||||
try!(fs::create_dir_all(&self.content_path));
|
||||
|
||||
// Validate hash
|
||||
let mut file_reader = io::BufReader::new(try!(fs::File::open(&path)));
|
||||
let hash = try!(sha3(&mut file_reader));
|
||||
let id = try!(self.id.as_str().parse().map_err(|_| ValidationError::InvalidContentId));
|
||||
if id != hash {
|
||||
return Err(ValidationError::HashMismatch {
|
||||
expected: id,
|
||||
got: hash,
|
||||
});
|
||||
}
|
||||
|
||||
// And prepare path for a file
|
||||
let filename = path.file_name().expect("We always fetch a file.");
|
||||
let mut content_path = self.content_path.clone();
|
||||
@ -266,7 +280,7 @@ impl ContentValidator for ContentInstaller {
|
||||
|
||||
try!(fs::copy(&path, &content_path));
|
||||
|
||||
Ok((self.id.clone(), LocalPageEndpoint::single_file(content_path, self.mime.clone())))
|
||||
Ok((self.id.clone(), LocalPageEndpoint::single_file(content_path, self.mime.clone(), PageCache::Enabled)))
|
||||
}
|
||||
|
||||
fn done(&self, endpoint: Option<LocalPageEndpoint>) {
|
||||
@ -372,7 +386,7 @@ impl ContentValidator for DappInstaller {
|
||||
try!(manifest_file.write_all(manifest_str.as_bytes()));
|
||||
|
||||
// Create endpoint
|
||||
let app = LocalPageEndpoint::new(target, manifest.clone().into(), self.embeddable_at);
|
||||
let app = LocalPageEndpoint::new(target, manifest.clone().into(), PageCache::Enabled, self.embeddable_at);
|
||||
|
||||
// Return modified app manifest
|
||||
Ok((manifest.id.clone(), app))
|
||||
@ -412,7 +426,7 @@ mod tests {
|
||||
version: "".into(),
|
||||
author: "".into(),
|
||||
icon_url: "".into(),
|
||||
}, None);
|
||||
}, Default::default(), None);
|
||||
|
||||
// when
|
||||
fetcher.set_status("test", ContentStatus::Ready(handler));
|
||||
|
@ -18,7 +18,7 @@ use std::io;
|
||||
use std::io::Read;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use page::LocalPageEndpoint;
|
||||
use page::{LocalPageEndpoint, PageCache};
|
||||
use endpoint::{Endpoints, EndpointInfo};
|
||||
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest};
|
||||
|
||||
@ -102,7 +102,7 @@ pub fn local_endpoints(dapps_path: String, signer_port: Option<u16>) -> Endpoint
|
||||
for dapp in local_dapps(dapps_path) {
|
||||
pages.insert(
|
||||
dapp.id,
|
||||
Box::new(LocalPageEndpoint::new(dapp.path, dapp.info, signer_port))
|
||||
Box::new(LocalPageEndpoint::new(dapp.path, dapp.info, PageCache::Disabled, signer_port))
|
||||
);
|
||||
}
|
||||
pages
|
||||
|
@ -33,14 +33,6 @@ pub const RPC_PATH : &'static str = "rpc";
|
||||
pub const API_PATH : &'static str = "api";
|
||||
pub const UTILS_PATH : &'static str = "parity-utils";
|
||||
|
||||
pub fn redirection_address(using_dapps_domains: bool, app_id: &str) -> String {
|
||||
if using_dapps_domains {
|
||||
format!("http://{}{}/", app_id, DAPPS_DOMAIN)
|
||||
} else {
|
||||
format!("/{}/", app_id)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn utils() -> Box<Endpoint> {
|
||||
Box::new(PageEndpoint::with_prefix(parity_ui::App::default(), UTILS_PATH.to_owned()))
|
||||
}
|
||||
|
@ -48,11 +48,7 @@ impl ContentHandler {
|
||||
Self::new_embeddable(code, content, mime!(Text/Html), embeddable_at)
|
||||
}
|
||||
|
||||
pub fn error(code: StatusCode, title: &str, message: &str, details: Option<&str>) -> Self {
|
||||
Self::error_embeddable(code, title, message, details, None)
|
||||
}
|
||||
|
||||
pub fn error_embeddable(code: StatusCode, title: &str, message: &str, details: Option<&str>, embeddable_at: Option<u16>) -> Self {
|
||||
pub fn error(code: StatusCode, title: &str, message: &str, details: Option<&str>, embeddable_at: Option<u16>) -> Self {
|
||||
Self::html(code, format!(
|
||||
include_str!("../error_tpl.html"),
|
||||
title=title,
|
||||
|
@ -22,14 +22,14 @@ use std::sync::{mpsc, Arc};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::time::{Instant, Duration};
|
||||
use util::Mutex;
|
||||
use url::Url;
|
||||
use fetch::{Client, Fetch, FetchResult};
|
||||
|
||||
use hyper::{server, Decoder, Encoder, Next, Method, Control};
|
||||
use hyper::net::HttpStream;
|
||||
use hyper::status::StatusCode;
|
||||
|
||||
use handlers::{ContentHandler, Redirection};
|
||||
use apps::redirection_address;
|
||||
use handlers::{ContentHandler, Redirection, extract_url};
|
||||
use page::LocalPageEndpoint;
|
||||
|
||||
const FETCH_TIMEOUT: u64 = 30;
|
||||
@ -136,8 +136,9 @@ pub struct ContentFetcherHandler<H: ContentValidator> {
|
||||
control: Option<Control>,
|
||||
status: FetchState,
|
||||
client: Option<Client>,
|
||||
using_dapps_domains: bool,
|
||||
installer: H,
|
||||
request_url: Option<Url>,
|
||||
embeddable_at: Option<u16>,
|
||||
}
|
||||
|
||||
impl<H: ContentValidator> Drop for ContentFetcherHandler<H> {
|
||||
@ -155,8 +156,9 @@ impl<H: ContentValidator> ContentFetcherHandler<H> {
|
||||
pub fn new(
|
||||
url: String,
|
||||
control: Control,
|
||||
using_dapps_domains: bool,
|
||||
handler: H) -> (Self, Arc<FetchControl>) {
|
||||
handler: H,
|
||||
embeddable_at: Option<u16>,
|
||||
) -> (Self, Arc<FetchControl>) {
|
||||
|
||||
let fetch_control = Arc::new(FetchControl::default());
|
||||
let client = Client::default();
|
||||
@ -165,8 +167,9 @@ impl<H: ContentValidator> ContentFetcherHandler<H> {
|
||||
control: Some(control),
|
||||
client: Some(client),
|
||||
status: FetchState::NotStarted(url),
|
||||
using_dapps_domains: using_dapps_domains,
|
||||
installer: handler,
|
||||
request_url: None,
|
||||
embeddable_at: embeddable_at,
|
||||
};
|
||||
|
||||
(handler, fetch_control)
|
||||
@ -189,6 +192,7 @@ impl<H: ContentValidator> ContentFetcherHandler<H> {
|
||||
|
||||
impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<H> {
|
||||
fn on_request(&mut self, request: server::Request<HttpStream>) -> Next {
|
||||
self.request_url = extract_url(&request);
|
||||
let status = if let FetchState::NotStarted(ref url) = self.status {
|
||||
Some(match *request.method() {
|
||||
// Start fetching content
|
||||
@ -204,6 +208,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
||||
"Unable To Start Dapp Download",
|
||||
"Could not initialize download of the dapp. It might be a problem with the remote server.",
|
||||
Some(&format!("{}", e)),
|
||||
self.embeddable_at,
|
||||
)),
|
||||
}
|
||||
},
|
||||
@ -213,6 +218,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
||||
"Method Not Allowed",
|
||||
"Only <code>GET</code> requests are allowed.",
|
||||
None,
|
||||
self.embeddable_at,
|
||||
)),
|
||||
})
|
||||
} else { None };
|
||||
@ -234,7 +240,8 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
||||
StatusCode::GatewayTimeout,
|
||||
"Download Timeout",
|
||||
&format!("Could not fetch content within {} seconds.", FETCH_TIMEOUT),
|
||||
None
|
||||
None,
|
||||
self.embeddable_at,
|
||||
);
|
||||
Self::close_client(&mut self.client);
|
||||
(Some(FetchState::Error(timeout)), Next::write())
|
||||
@ -255,12 +262,15 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
||||
StatusCode::BadGateway,
|
||||
"Invalid Dapp",
|
||||
"Downloaded bundle does not contain a valid content.",
|
||||
Some(&format!("{:?}", e))
|
||||
Some(&format!("{:?}", e)),
|
||||
self.embeddable_at,
|
||||
))
|
||||
},
|
||||
Ok((id, result)) => {
|
||||
let address = redirection_address(self.using_dapps_domains, &id);
|
||||
FetchState::Done(id, result, Redirection::new(&address))
|
||||
let url: String = self.request_url.take()
|
||||
.map(|url| url.raw.into_string())
|
||||
.expect("Request URL always read in on_request; qed");
|
||||
FetchState::Done(id, result, Redirection::new(&url))
|
||||
},
|
||||
};
|
||||
// Remove temporary zip file
|
||||
@ -274,6 +284,7 @@ impl<H: ContentValidator> server::Handler<HttpStream> for ContentFetcherHandler<
|
||||
"Download Error",
|
||||
"There was an error when fetching the content.",
|
||||
Some(&format!("{:?}", e)),
|
||||
self.embeddable_at,
|
||||
);
|
||||
(Some(FetchState::Error(error)), Next::write())
|
||||
},
|
||||
|
@ -44,6 +44,7 @@
|
||||
#![cfg_attr(feature="nightly", plugin(clippy))]
|
||||
|
||||
extern crate hyper;
|
||||
extern crate time;
|
||||
extern crate url as url_lib;
|
||||
extern crate unicase;
|
||||
extern crate serde;
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use page::handler;
|
||||
use page::{handler, PageCache};
|
||||
use std::sync::Arc;
|
||||
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler};
|
||||
use parity_dapps::{WebApp, File, Info};
|
||||
@ -80,6 +80,7 @@ impl<T: WebApp> Endpoint for PageEndpoint<T> {
|
||||
prefix: self.prefix.clone(),
|
||||
path: path,
|
||||
file: handler::ServedFile::new(self.safe_to_embed_at_port.clone()),
|
||||
cache: PageCache::Disabled,
|
||||
safe_to_embed_at_port: self.safe_to_embed_at_port.clone(),
|
||||
})
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::io::Write;
|
||||
use time::{self, Duration};
|
||||
|
||||
use hyper::header;
|
||||
use hyper::server;
|
||||
use hyper::uri::RequestUri;
|
||||
@ -59,7 +61,7 @@ pub enum ServedFile<T: Dapp> {
|
||||
|
||||
impl<T: Dapp> ServedFile<T> {
|
||||
pub fn new(embeddable_at: Option<u16>) -> Self {
|
||||
ServedFile::Error(ContentHandler::error_embeddable(
|
||||
ServedFile::Error(ContentHandler::error(
|
||||
StatusCode::NotFound,
|
||||
"404 Not Found",
|
||||
"Requested dapp resource was not found.",
|
||||
@ -69,6 +71,19 @@ impl<T: Dapp> ServedFile<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines what cache headers should be appended to returned resources.
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum PageCache {
|
||||
Enabled,
|
||||
Disabled,
|
||||
}
|
||||
|
||||
impl Default for PageCache {
|
||||
fn default() -> Self {
|
||||
PageCache::Disabled
|
||||
}
|
||||
}
|
||||
|
||||
/// A handler for a single webapp.
|
||||
/// Resolves correct paths and serves as a plumbing code between
|
||||
/// hyper server and dapp.
|
||||
@ -83,6 +98,8 @@ pub struct PageHandler<T: Dapp> {
|
||||
pub path: EndpointPath,
|
||||
/// Flag indicating if the file can be safely embeded (put in iframe).
|
||||
pub safe_to_embed_at_port: Option<u16>,
|
||||
/// Cache settings for this page.
|
||||
pub cache: PageCache,
|
||||
}
|
||||
|
||||
impl<T: Dapp> PageHandler<T> {
|
||||
@ -129,9 +146,19 @@ impl<T: Dapp> server::Handler<HttpStream> for PageHandler<T> {
|
||||
ServedFile::File(ref f) => {
|
||||
res.set_status(StatusCode::Ok);
|
||||
|
||||
if let PageCache::Enabled = self.cache {
|
||||
let mut headers = res.headers_mut();
|
||||
let validity = Duration::days(365);
|
||||
headers.set(header::CacheControl(vec![
|
||||
header::CacheDirective::Public,
|
||||
header::CacheDirective::MaxAge(validity.num_seconds() as u32),
|
||||
]));
|
||||
headers.set(header::Expires(header::HttpDate(time::now() + validity)));
|
||||
}
|
||||
|
||||
match f.content_type().parse() {
|
||||
Ok(mime) => res.headers_mut().set(header::ContentType(mime)),
|
||||
Err(()) => debug!(target: "page_handler", "invalid MIME type: {}", f.content_type()),
|
||||
Err(()) => debug!(target: "dapps", "invalid MIME type: {}", f.content_type()),
|
||||
}
|
||||
|
||||
// Security headers:
|
||||
@ -218,6 +245,7 @@ fn should_extract_path_with_appid() {
|
||||
using_dapps_domains: true,
|
||||
},
|
||||
file: ServedFile::new(None),
|
||||
cache: Default::default(),
|
||||
safe_to_embed_at_port: None,
|
||||
};
|
||||
|
||||
|
@ -18,7 +18,7 @@ use mime_guess;
|
||||
use std::io::{Seek, Read, SeekFrom};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use page::handler;
|
||||
use page::handler::{self, PageCache};
|
||||
use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -26,24 +26,27 @@ pub struct LocalPageEndpoint {
|
||||
path: PathBuf,
|
||||
mime: Option<String>,
|
||||
info: Option<EndpointInfo>,
|
||||
cache: PageCache,
|
||||
embeddable_at: Option<u16>,
|
||||
}
|
||||
|
||||
impl LocalPageEndpoint {
|
||||
pub fn new(path: PathBuf, info: EndpointInfo, embeddable_at: Option<u16>) -> Self {
|
||||
pub fn new(path: PathBuf, info: EndpointInfo, cache: PageCache, embeddable_at: Option<u16>) -> Self {
|
||||
LocalPageEndpoint {
|
||||
path: path,
|
||||
mime: None,
|
||||
info: Some(info),
|
||||
cache: cache,
|
||||
embeddable_at: embeddable_at,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn single_file(path: PathBuf, mime: String) -> Self {
|
||||
pub fn single_file(path: PathBuf, mime: String, cache: PageCache) -> Self {
|
||||
LocalPageEndpoint {
|
||||
path: path,
|
||||
mime: Some(mime),
|
||||
info: None,
|
||||
cache: cache,
|
||||
embeddable_at: None,
|
||||
}
|
||||
}
|
||||
@ -66,6 +69,7 @@ impl Endpoint for LocalPageEndpoint {
|
||||
path: path,
|
||||
file: handler::ServedFile::new(None),
|
||||
safe_to_embed_at_port: self.embeddable_at,
|
||||
cache: self.cache,
|
||||
})
|
||||
} else {
|
||||
Box::new(handler::PageHandler {
|
||||
@ -74,6 +78,7 @@ impl Endpoint for LocalPageEndpoint {
|
||||
path: path,
|
||||
file: handler::ServedFile::new(None),
|
||||
safe_to_embed_at_port: self.embeddable_at,
|
||||
cache: self.cache,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -21,4 +21,5 @@ mod handler;
|
||||
|
||||
pub use self::local::LocalPageEndpoint;
|
||||
pub use self::builtin::PageEndpoint;
|
||||
pub use self::handler::PageCache;
|
||||
|
||||
|
@ -59,7 +59,8 @@ impl Authorization for HttpBasicAuth {
|
||||
status::StatusCode::Unauthorized,
|
||||
"Unauthorized",
|
||||
"You need to provide valid credentials to access this page.",
|
||||
None
|
||||
None,
|
||||
None,
|
||||
)))
|
||||
},
|
||||
Access::AuthRequired => {
|
||||
|
@ -41,6 +41,7 @@ pub fn host_invalid_response() -> Box<server::Handler<HttpStream> + Send> {
|
||||
Box::new(ContentHandler::error(StatusCode::Forbidden,
|
||||
"Current Host Is Disallowed",
|
||||
"You are trying to access your node using incorrect address.",
|
||||
Some("Use allowed URL or specify different <code>hosts</code> CLI options.")
|
||||
Some("Use allowed URL or specify different <code>hosts</code> CLI options."),
|
||||
None,
|
||||
))
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ impl<A: Authorization + 'static> server::Handler<HttpStream> for Router<A> {
|
||||
"404 Not Found",
|
||||
"Requested content was not found.",
|
||||
None,
|
||||
self.signer_port,
|
||||
))
|
||||
},
|
||||
// Redirect any other GET request to signer.
|
||||
@ -131,6 +132,7 @@ impl<A: Authorization + 'static> server::Handler<HttpStream> for Router<A> {
|
||||
"404 Not Found",
|
||||
"Your homepage is not available when Trusted Signer is disabled.",
|
||||
Some("You can still access dapps by writing a correct address, though. Re-enabled Signer to get your homepage back."),
|
||||
self.signer_port,
|
||||
))
|
||||
}
|
||||
},
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use tests::helpers::{serve_with_registrar, serve_with_registrar_and_sync, request, assert_security_headers};
|
||||
use tests::helpers::{serve_with_registrar, serve_with_registrar_and_sync, request, assert_security_headers_for_embed};
|
||||
|
||||
#[test]
|
||||
fn should_resolve_dapp() {
|
||||
@ -34,7 +34,7 @@ fn should_resolve_dapp() {
|
||||
// then
|
||||
assert_eq!(response.status, "HTTP/1.1 404 Not Found".to_owned());
|
||||
assert_eq!(registrar.calls.lock().len(), 2);
|
||||
assert_security_headers(&response.headers);
|
||||
assert_security_headers_for_embed(&response.headers);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -63,5 +63,5 @@ fn should_return_503_when_syncing_but_should_make_the_calls() {
|
||||
// then
|
||||
assert_eq!(response.status, "HTTP/1.1 503 Service Unavailable".to_owned());
|
||||
assert_eq!(registrar.calls.lock().len(), 4);
|
||||
assert_security_headers(&response.headers);
|
||||
assert_security_headers_for_embed(&response.headers);
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use tests::helpers::{serve, request, assert_security_headers};
|
||||
use tests::helpers::{serve, request, assert_security_headers, assert_security_headers_for_embed};
|
||||
|
||||
#[test]
|
||||
fn should_redirect_to_home() {
|
||||
@ -93,7 +93,7 @@ fn should_display_404_on_invalid_dapp() {
|
||||
|
||||
// then
|
||||
assert_eq!(response.status, "HTTP/1.1 404 Not Found".to_owned());
|
||||
assert_security_headers(&response.headers);
|
||||
assert_security_headers_for_embed(&response.headers);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -113,7 +113,7 @@ fn should_display_404_on_invalid_dapp_with_domain() {
|
||||
|
||||
// then
|
||||
assert_eq!(response.status, "HTTP/1.1 404 Not Found".to_owned());
|
||||
assert_security_headers(&response.headers);
|
||||
assert_security_headers_for_embed(&response.headers);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "parity.js",
|
||||
"version": "0.1.37",
|
||||
"version": "0.1.47",
|
||||
"main": "release/index.js",
|
||||
"jsnext:main": "src/index.js",
|
||||
"author": "Parity Team <admin@parity.io>",
|
||||
|
@ -58,6 +58,11 @@ export default class Ethcore {
|
||||
.execute('ethcore_dropNonReservedPeers');
|
||||
}
|
||||
|
||||
enode () {
|
||||
return this._transport
|
||||
.execute('ethcore_enode');
|
||||
}
|
||||
|
||||
extraData () {
|
||||
return this._transport
|
||||
.execute('ethcore_extraData');
|
||||
|
@ -80,7 +80,9 @@ export default class RegisterAction extends Component {
|
||||
modal={ sending || complete }
|
||||
className={ styles.dialog }
|
||||
onRequestClose={ this.onClose }
|
||||
actions={ this.renderActions() } >
|
||||
actions={ this.renderActions() }
|
||||
autoScrollBodyContent
|
||||
>
|
||||
{ this.renderContent() }
|
||||
</Dialog>
|
||||
);
|
||||
|
@ -85,6 +85,15 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
enode: {
|
||||
desc: 'Returns the node enode URI',
|
||||
params: [],
|
||||
returns: {
|
||||
type: String,
|
||||
desc: 'Enode URI'
|
||||
}
|
||||
},
|
||||
|
||||
extraData: {
|
||||
desc: 'Returns currently set extra data',
|
||||
params: [],
|
||||
|
@ -136,6 +136,7 @@ export default class AddAddress extends Component {
|
||||
api.personal.setAccountName(address, name),
|
||||
api.personal.setAccountMeta(address, {
|
||||
description,
|
||||
timestamp: Date.now(),
|
||||
deleted: false
|
||||
})
|
||||
]).catch((error) => {
|
||||
|
@ -145,6 +145,7 @@ export default class AddContract extends Component {
|
||||
api.personal.setAccountMeta(address, {
|
||||
contract: true,
|
||||
deleted: false,
|
||||
timestamp: Date.now(),
|
||||
abi: abiParsed,
|
||||
description
|
||||
})
|
||||
|
@ -214,7 +214,10 @@ export default class CreateAccount extends Component {
|
||||
this.setState({ address });
|
||||
return api.personal
|
||||
.setAccountName(address, this.state.name)
|
||||
.then(() => api.personal.setAccountMeta(address, { passwordHint: this.state.passwordHint }));
|
||||
.then(() => api.personal.setAccountMeta(address, {
|
||||
timestamp: Date.now(),
|
||||
passwordHint: this.state.passwordHint
|
||||
}));
|
||||
})
|
||||
.then(() => {
|
||||
this.onNext();
|
||||
@ -236,7 +239,10 @@ export default class CreateAccount extends Component {
|
||||
this.setState({ address });
|
||||
return api.personal
|
||||
.setAccountName(address, this.state.name)
|
||||
.then(() => api.personal.setAccountMeta(address, { passwordHint: this.state.passwordHint }));
|
||||
.then(() => api.personal.setAccountMeta(address, {
|
||||
timestamp: Date.now(),
|
||||
passwordHint: this.state.passwordHint
|
||||
}));
|
||||
})
|
||||
.then(() => {
|
||||
this.onNext();
|
||||
@ -285,7 +291,10 @@ export default class CreateAccount extends Component {
|
||||
|
||||
return api.personal
|
||||
.setAccountName(address, this.state.name)
|
||||
.then(() => api.personal.setAccountMeta(address, { passwordHint: this.state.passwordHint }));
|
||||
.then(() => api.personal.setAccountMeta(address, {
|
||||
timestamp: Date.now(),
|
||||
passwordHint: this.state.passwordHint
|
||||
}));
|
||||
})
|
||||
.then(() => {
|
||||
this.onNext();
|
||||
|
@ -216,6 +216,7 @@ export default class DeployContract extends Component {
|
||||
api.personal.setAccountMeta(address, {
|
||||
abi: abiParsed,
|
||||
contract: true,
|
||||
timestamp: Date.now(),
|
||||
deleted: false,
|
||||
description
|
||||
})
|
||||
|
@ -19,7 +19,7 @@ import ActionDoneAll from 'material-ui/svg-icons/action/done-all';
|
||||
import ContentClear from 'material-ui/svg-icons/content/clear';
|
||||
|
||||
import { BusyStep, CompletedStep, Button, IdentityIcon, Modal, TxHash } from '../../ui';
|
||||
import { validateAddress } from '../../util/validation';
|
||||
import { validateAddress, validateUint } from '../../util/validation';
|
||||
|
||||
import DetailsStep from './DetailsStep';
|
||||
|
||||
@ -41,6 +41,7 @@ export default class ExecuteContract extends Component {
|
||||
state = {
|
||||
amount: '0',
|
||||
amountError: null,
|
||||
fromAddressError: null,
|
||||
func: null,
|
||||
funcError: null,
|
||||
values: [],
|
||||
@ -77,7 +78,8 @@ export default class ExecuteContract extends Component {
|
||||
|
||||
renderDialogActions () {
|
||||
const { onClose, fromAddress } = this.props;
|
||||
const { sending, step } = this.state;
|
||||
const { sending, step, fromAddressError, valuesError } = this.state;
|
||||
const hasError = fromAddressError || valuesError.find((error) => error);
|
||||
const cancelBtn = (
|
||||
<Button
|
||||
key='cancel'
|
||||
@ -92,7 +94,7 @@ export default class ExecuteContract extends Component {
|
||||
<Button
|
||||
key='postTransaction'
|
||||
label='post transaction'
|
||||
disabled={ sending }
|
||||
disabled={ sending || hasError }
|
||||
icon={ <IdentityIcon address={ fromAddress } button /> }
|
||||
onClick={ this.postTransaction } />
|
||||
];
|
||||
@ -177,12 +179,16 @@ export default class ExecuteContract extends Component {
|
||||
let valueError = null;
|
||||
|
||||
switch (input.kind.type) {
|
||||
case 'address':
|
||||
valueError = validateAddress(_value).addressError;
|
||||
break;
|
||||
|
||||
case 'bool':
|
||||
value = _value === 'true';
|
||||
break;
|
||||
|
||||
case 'address':
|
||||
valueError = validateAddress(_value).addressError;
|
||||
case 'uint':
|
||||
valueError = validateUint(_value).valueError;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -190,8 +196,8 @@ export default class ExecuteContract extends Component {
|
||||
valuesError[index] = valueError;
|
||||
|
||||
this.setState({
|
||||
values,
|
||||
valuesError
|
||||
values: [].concat(values),
|
||||
valuesError: [].concat(valuesError)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,20 @@ export default class Status {
|
||||
this._pollPing();
|
||||
this._pollStatus();
|
||||
this._pollLogs();
|
||||
this._fetchEnode();
|
||||
}
|
||||
|
||||
_fetchEnode () {
|
||||
this._api
|
||||
.ethcore.enode()
|
||||
.then((enode) => {
|
||||
this._store.dispatch(statusCollection({ enode }));
|
||||
})
|
||||
.catch(() => {
|
||||
window.setTimeout(() => {
|
||||
this._fetchEnode();
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
_subscribeBlockNumber () {
|
||||
@ -68,11 +82,17 @@ export default class Status {
|
||||
|
||||
_pollStatus = () => {
|
||||
const { secureToken, isConnected, isConnecting, needsToken } = this._api;
|
||||
|
||||
const nextTimeout = (timeout = 1000) => {
|
||||
setTimeout(this._pollStatus, timeout);
|
||||
};
|
||||
|
||||
if (isConnected !== this._store.getState().nodeStatus.isConnected) {
|
||||
this._fetchEnode();
|
||||
}
|
||||
|
||||
this._store.dispatch(statusCollection({ isConnected, isConnecting, needsToken, secureToken }));
|
||||
|
||||
if (!isConnected) {
|
||||
nextTimeout(250);
|
||||
return;
|
||||
|
@ -25,6 +25,7 @@ const initialState = {
|
||||
clientVersion: '',
|
||||
coinbase: '',
|
||||
defaultExtraData: '',
|
||||
enode: '',
|
||||
extraData: '',
|
||||
gasFloorTarget: new BigNumber(0),
|
||||
hashrate: new BigNumber(0),
|
||||
|
@ -27,14 +27,23 @@ import styles from './sort.css';
|
||||
export default class ActionbarSort extends Component {
|
||||
static propTypes = {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
order: PropTypes.string
|
||||
order: PropTypes.string,
|
||||
showDefault: PropTypes.bool,
|
||||
metas: PropTypes.array
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
metas: [],
|
||||
showDefault: true
|
||||
}
|
||||
|
||||
state = {
|
||||
menuOpen: false
|
||||
}
|
||||
|
||||
render () {
|
||||
const { showDefault } = this.props;
|
||||
|
||||
return (
|
||||
<IconMenu
|
||||
iconButtonElement={
|
||||
@ -50,14 +59,56 @@ export default class ActionbarSort extends Component {
|
||||
onItemTouchTap={ this.handleSortChange }
|
||||
targetOrigin={ { horizontal: 'right', vertical: 'top' } }
|
||||
anchorOrigin={ { horizontal: 'right', vertical: 'top' } }
|
||||
touchTapCloseDelay={ 0 }
|
||||
>
|
||||
<MenuItem value='' primaryText='Default' />
|
||||
<MenuItem value='tags' primaryText='Sort by tags' />
|
||||
<MenuItem value='name' primaryText='Sort by name' />
|
||||
{
|
||||
showDefault
|
||||
? this.renderMenuItem('', 'Default')
|
||||
: null
|
||||
}
|
||||
{ this.renderMenuItem('tags', 'Sort by tags') }
|
||||
{ this.renderMenuItem('name', 'Sort by name') }
|
||||
{ this.renderMenuItem('eth', 'Sort by ETH') }
|
||||
|
||||
{ this.renderSortByMetas() }
|
||||
</IconMenu>
|
||||
);
|
||||
}
|
||||
|
||||
renderSortByMetas () {
|
||||
const { metas } = this.props;
|
||||
|
||||
return metas
|
||||
.map((meta, index) => {
|
||||
return this
|
||||
.renderMenuItem(meta.key, `Sort by ${meta.label}`, index);
|
||||
});
|
||||
}
|
||||
|
||||
renderMenuItem (value, label, key = null) {
|
||||
const { order } = this.props;
|
||||
|
||||
const props = {};
|
||||
|
||||
if (key !== null) {
|
||||
props.key = key;
|
||||
}
|
||||
|
||||
const checked = order === value;
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
checked={ checked }
|
||||
value={ value }
|
||||
primaryText={ label }
|
||||
innerDivStyle={ {
|
||||
paddingLeft: checked ? 50 : 16
|
||||
} }
|
||||
{ ...props }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
handleSortChange = (event, child) => {
|
||||
const order = child.props.value;
|
||||
this.props.onChange(order);
|
||||
|
@ -18,6 +18,7 @@
|
||||
flex: 1;
|
||||
padding: 0em;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.compact,
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { MenuItem } from 'material-ui';
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
import AutoComplete from '../AutoComplete';
|
||||
import IdentityIcon from '../../IdentityIcon';
|
||||
@ -24,57 +25,82 @@ import IdentityName from '../../IdentityName';
|
||||
import styles from './addressSelect.css';
|
||||
|
||||
export default class AddressSelect extends Component {
|
||||
static contextTypes = {
|
||||
api: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
disabled: PropTypes.bool,
|
||||
accounts: PropTypes.object,
|
||||
contacts: PropTypes.object,
|
||||
contracts: PropTypes.object,
|
||||
label: PropTypes.string,
|
||||
hint: PropTypes.string,
|
||||
error: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
tokens: PropTypes.object,
|
||||
onChange: PropTypes.func.isRequired
|
||||
onChange: PropTypes.func.isRequired,
|
||||
allowInput: PropTypes.bool
|
||||
}
|
||||
|
||||
state = {
|
||||
entries: {},
|
||||
addresses: [],
|
||||
value: ''
|
||||
}
|
||||
|
||||
entriesFromProps (props = this.props) {
|
||||
const { accounts, contacts, contracts } = props;
|
||||
const entries = Object.assign({}, accounts || {}, contacts || {}, contracts || {});
|
||||
return entries;
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
const { accounts, contacts, value } = this.props;
|
||||
const entries = Object.assign({}, accounts || {}, contacts || {});
|
||||
this.setState({ entries, value });
|
||||
const { value } = this.props;
|
||||
const entries = this.entriesFromProps();
|
||||
const addresses = Object.keys(entries).sort();
|
||||
|
||||
this.setState({ entries, addresses, value });
|
||||
}
|
||||
|
||||
componentWillReceiveProps (newProps) {
|
||||
const { accounts, contacts } = newProps;
|
||||
const entries = Object.assign({}, accounts || {}, contacts || {});
|
||||
this.setState({ entries });
|
||||
const entries = this.entriesFromProps();
|
||||
const addresses = Object.keys(entries).sort();
|
||||
|
||||
if (!isEqual(addresses, this.state.addresses)) {
|
||||
this.setState({ entries, addresses });
|
||||
}
|
||||
|
||||
if (newProps.value !== this.props.value) {
|
||||
this.setState({ value: newProps.value });
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const { disabled, error, hint, label } = this.props;
|
||||
const { entries } = this.state;
|
||||
const value = this.getSearchText();
|
||||
const { allowInput, disabled, error, hint, label } = this.props;
|
||||
const { entries, value } = this.state;
|
||||
|
||||
const searchText = this.getSearchText();
|
||||
const icon = this.renderIdentityIcon(value);
|
||||
|
||||
return (
|
||||
<div className={ styles.container }>
|
||||
<AutoComplete
|
||||
className={ (error || !value) ? '' : styles.paddedInput }
|
||||
className={ !icon ? '' : styles.paddedInput }
|
||||
disabled={ disabled }
|
||||
label={ label }
|
||||
hint={ hint ? `search for ${hint}` : 'search for an address' }
|
||||
error={ error }
|
||||
onChange={ this.onChange }
|
||||
value={ value }
|
||||
onBlur={ this.onBlur }
|
||||
onUpdateInput={ allowInput && this.onUpdateInput }
|
||||
value={ searchText }
|
||||
filter={ this.handleFilter }
|
||||
entries={ entries }
|
||||
entry={ this.getEntry() || {} }
|
||||
renderItem={ this.renderItem }
|
||||
/>
|
||||
|
||||
{ this.renderIdentityIcon(value) }
|
||||
{ icon }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -82,7 +108,7 @@ export default class AddressSelect extends Component {
|
||||
renderIdentityIcon (inputValue) {
|
||||
const { error, value } = this.props;
|
||||
|
||||
if (error || !inputValue) {
|
||||
if (error || !inputValue || value.length !== 42) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -96,8 +122,9 @@ export default class AddressSelect extends Component {
|
||||
|
||||
renderItem = (entry) => {
|
||||
return {
|
||||
text: entry.address,
|
||||
value: this.renderSelectEntry(entry)
|
||||
text: entry.name && entry.name.toUpperCase() || entry.address,
|
||||
value: this.renderSelectEntry(entry),
|
||||
address: entry.address
|
||||
};
|
||||
}
|
||||
|
||||
@ -127,20 +154,20 @@ export default class AddressSelect extends Component {
|
||||
|
||||
getSearchText () {
|
||||
const entry = this.getEntry();
|
||||
if (!entry) return '';
|
||||
const { value } = this.state;
|
||||
|
||||
return entry.name ? entry.name.toUpperCase() : '';
|
||||
return entry && entry.name
|
||||
? entry.name.toUpperCase()
|
||||
: value;
|
||||
}
|
||||
|
||||
getEntry () {
|
||||
const { value } = this.props;
|
||||
if (!value) return '';
|
||||
|
||||
const { entries } = this.state;
|
||||
return entries[value];
|
||||
const { entries, value } = this.state;
|
||||
return value ? entries[value] : null;
|
||||
}
|
||||
|
||||
handleFilter = (searchText, address) => {
|
||||
handleFilter = (searchText, name, item) => {
|
||||
const { address } = item;
|
||||
const entry = this.state.entries[address];
|
||||
const lowCaseSearch = searchText.toLowerCase();
|
||||
|
||||
@ -149,10 +176,26 @@ export default class AddressSelect extends Component {
|
||||
}
|
||||
|
||||
onChange = (entry, empty) => {
|
||||
const { allowInput } = this.props;
|
||||
const { value } = this.state;
|
||||
|
||||
const address = entry && entry.address
|
||||
? entry.address
|
||||
: (empty ? '' : this.state.value);
|
||||
: ((empty && !allowInput) ? '' : value);
|
||||
|
||||
this.props.onChange(null, address);
|
||||
}
|
||||
|
||||
onUpdateInput = (query, choices) => {
|
||||
const { api } = this.context;
|
||||
|
||||
const address = query.trim();
|
||||
|
||||
if (!/^0x/.test(address) && api.util.isAddressValid(`0x${address}`)) {
|
||||
const checksumed = api.util.toChecksumAddress(`0x${address}`);
|
||||
return this.props.onChange(null, checksumed);
|
||||
}
|
||||
|
||||
this.props.onChange(null, address);
|
||||
};
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import { PopoverAnimationVertical } from 'material-ui/Popover';
|
||||
export default class AutoComplete extends Component {
|
||||
static propTypes = {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onUpdateInput: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
label: PropTypes.string,
|
||||
hint: PropTypes.string,
|
||||
@ -43,7 +44,7 @@ export default class AutoComplete extends Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { disabled, error, hint, label, value, className, filter } = this.props;
|
||||
const { disabled, error, hint, label, value, className, filter, onUpdateInput } = this.props;
|
||||
const { open } = this.state;
|
||||
|
||||
return (
|
||||
@ -54,11 +55,11 @@ export default class AutoComplete extends Component {
|
||||
hintText={ hint }
|
||||
errorText={ error }
|
||||
onNewRequest={ this.onChange }
|
||||
onUpdateInput={ onUpdateInput }
|
||||
searchText={ value }
|
||||
onFocus={ this.onFocus }
|
||||
onBlur={ this.onBlur }
|
||||
animation={ PopoverAnimationVertical }
|
||||
|
||||
filter={ filter }
|
||||
popoverProps={ { open } }
|
||||
openOnFocus
|
||||
@ -108,12 +109,18 @@ export default class AutoComplete extends Component {
|
||||
}
|
||||
|
||||
onBlur = () => {
|
||||
const { onUpdateInput } = this.props;
|
||||
|
||||
// TODO: Handle blur gracefully where we use onUpdateInput (currently replaces input
|
||||
// input where text is allowed with the last selected value from the dropdown)
|
||||
if (!onUpdateInput) {
|
||||
window.setTimeout(() => {
|
||||
const { entry } = this.state;
|
||||
|
||||
this.handleOnChange(entry);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
onFocus = () => {
|
||||
const { entry } = this.props;
|
||||
@ -131,5 +138,4 @@ export default class AutoComplete extends Component {
|
||||
this.props.onChange(value, empty);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,8 +26,16 @@
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
|
||||
.icon {
|
||||
.icon,
|
||||
.iconDisabled {
|
||||
position: absolute;
|
||||
top: 35px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.iconDisabled {
|
||||
left: 24px;
|
||||
}
|
||||
|
@ -69,14 +69,14 @@ class InputAddress extends Component {
|
||||
}
|
||||
|
||||
renderIcon () {
|
||||
const { value } = this.props;
|
||||
const { value, disabled } = this.props;
|
||||
|
||||
if (!value || !value.length || !util.isAddressValid(value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.icon }>
|
||||
<div className={ disabled ? styles.iconDisabled : styles.icon }>
|
||||
<IdentityIcon
|
||||
inline center
|
||||
address={ value } />
|
||||
|
@ -1,31 +0,0 @@
|
||||
/* Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
/* This file is part of Parity.
|
||||
/*
|
||||
/* Parity is free software: you can redistribute it and/or modify
|
||||
/* it under the terms of the GNU General Public License as published by
|
||||
/* the Free Software Foundation, either version 3 of the License, or
|
||||
/* (at your option) any later version.
|
||||
/*
|
||||
/* Parity is distributed in the hope that it will be useful,
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
/* GNU General Public License for more details.
|
||||
/*
|
||||
/* You should have received a copy of the GNU General Public License
|
||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
.inputselect {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.inputselect svg {
|
||||
padding-right: 84px;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
position: absolute !important;
|
||||
top: 38px;
|
||||
right: 0;
|
||||
display: inline-block !important;
|
||||
width: auto !important;
|
||||
}
|
@ -17,103 +17,46 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { Toggle } from 'material-ui';
|
||||
|
||||
import AddressSelect from '../AddressSelect';
|
||||
import InputAddress from '../InputAddress';
|
||||
|
||||
import styles from './inputAddressSelect.css';
|
||||
|
||||
class InputAddressSelect extends Component {
|
||||
static propTypes = {
|
||||
accounts: PropTypes.object,
|
||||
contacts: PropTypes.object,
|
||||
disabled: PropTypes.bool,
|
||||
editing: PropTypes.bool,
|
||||
accounts: PropTypes.object.isRequired,
|
||||
contacts: PropTypes.object.isRequired,
|
||||
contracts: PropTypes.object.isRequired,
|
||||
error: PropTypes.string,
|
||||
label: PropTypes.string,
|
||||
hint: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
tokens: PropTypes.object,
|
||||
onChange: PropTypes.func
|
||||
};
|
||||
|
||||
state = {
|
||||
editing: this.props.editing || false,
|
||||
entries: []
|
||||
}
|
||||
|
||||
render () {
|
||||
const { editing } = this.state;
|
||||
|
||||
return (
|
||||
<div className={ styles.inputselect }>
|
||||
{ editing ? this.renderInput() : this.renderSelect() }
|
||||
<Toggle
|
||||
className={ styles.toggle }
|
||||
label='Edit'
|
||||
labelPosition='right'
|
||||
toggled={ editing }
|
||||
onToggle={ this.onToggle } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderInput () {
|
||||
const { disabled, error, hint, label, value, tokens } = this.props;
|
||||
|
||||
return (
|
||||
<InputAddress
|
||||
disabled={ disabled }
|
||||
error={ error }
|
||||
hint={ hint }
|
||||
label={ label }
|
||||
value={ value }
|
||||
tokens={ tokens }
|
||||
onChange={ this.onChangeInput } />
|
||||
);
|
||||
}
|
||||
|
||||
renderSelect () {
|
||||
const { accounts, contacts, disabled, error, hint, label, value, tokens } = this.props;
|
||||
const { accounts, contacts, contracts, label, hint, error, value, onChange } = this.props;
|
||||
|
||||
return (
|
||||
<AddressSelect
|
||||
allowInput
|
||||
accounts={ accounts }
|
||||
contacts={ contacts }
|
||||
disabled={ disabled }
|
||||
contracts={ contracts }
|
||||
error={ error }
|
||||
label={ label }
|
||||
hint={ hint }
|
||||
error={ error }
|
||||
value={ value }
|
||||
tokens={ tokens }
|
||||
onChange={ this.onChangeSelect } />
|
||||
onChange={ onChange } />
|
||||
);
|
||||
}
|
||||
|
||||
onToggle = () => {
|
||||
const { editing } = this.state;
|
||||
|
||||
this.setState({
|
||||
editing: !editing
|
||||
});
|
||||
}
|
||||
|
||||
onChangeInput = (event, value) => {
|
||||
this.props.onChange(event, value);
|
||||
}
|
||||
|
||||
onChangeSelect = (event, value) => {
|
||||
this.props.onChange(event, value);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
const { accounts, contacts } = state.personal;
|
||||
const { accounts, contacts, contracts } = state.personal;
|
||||
|
||||
return {
|
||||
accounts,
|
||||
contacts
|
||||
contacts,
|
||||
contracts
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
import util from '../api/util';
|
||||
|
||||
export const ERRORS = {
|
||||
@ -22,7 +24,10 @@ export const ERRORS = {
|
||||
invalidChecksum: 'address has failed the checksum formatting',
|
||||
invalidName: 'name should not be blank and longer than 2',
|
||||
invalidAbi: 'abi should be a valid JSON array',
|
||||
invalidCode: 'code should be the compiled hex string'
|
||||
invalidCode: 'code should be the compiled hex string',
|
||||
invalidNumber: 'invalid number format',
|
||||
negativeNumber: 'input number should be positive',
|
||||
decimalNumber: 'input number should not contain decimals'
|
||||
};
|
||||
|
||||
export function validateAbi (abi, api) {
|
||||
@ -88,3 +93,23 @@ export function validateName (name) {
|
||||
nameError
|
||||
};
|
||||
}
|
||||
|
||||
export function validateUint (value) {
|
||||
let valueError = null;
|
||||
|
||||
try {
|
||||
const bn = new BigNumber(value);
|
||||
if (bn.lt(0)) {
|
||||
valueError = ERRORS.negativeNumber;
|
||||
} else if (bn.toString().indexOf('.') !== -1) {
|
||||
valueError = ERRORS.decimalNumber;
|
||||
}
|
||||
} catch (e) {
|
||||
valueError = ERRORS.invalidNumber;
|
||||
}
|
||||
|
||||
return {
|
||||
value,
|
||||
valueError
|
||||
};
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ export default class List extends Component {
|
||||
search: PropTypes.array,
|
||||
empty: PropTypes.bool,
|
||||
order: PropTypes.string,
|
||||
orderFallback: PropTypes.string,
|
||||
handleAddSearchToken: PropTypes.func
|
||||
};
|
||||
|
||||
@ -79,9 +80,9 @@ export default class List extends Component {
|
||||
}
|
||||
|
||||
sortAddresses (addresses) {
|
||||
const { order } = this.props;
|
||||
const { order, orderFallback } = this.props;
|
||||
|
||||
if (!order || ['tags', 'name'].indexOf(order) === -1) {
|
||||
if (!order) {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
@ -91,24 +92,75 @@ export default class List extends Component {
|
||||
const accountA = accounts[addressA];
|
||||
const accountB = accounts[addressB];
|
||||
|
||||
if (order === 'name') {
|
||||
const sort = this.compareAccounts(accountA, accountB, order);
|
||||
|
||||
if (sort === 0 && orderFallback) {
|
||||
return this.compareAccounts(accountA, accountB, orderFallback);
|
||||
}
|
||||
|
||||
return sort;
|
||||
});
|
||||
}
|
||||
|
||||
compareAccounts (accountA, accountB, key) {
|
||||
if (key === 'name') {
|
||||
return accountA.name.localeCompare(accountB.name);
|
||||
}
|
||||
|
||||
if (order === 'tags') {
|
||||
if (key === 'eth') {
|
||||
const { balances } = this.props;
|
||||
|
||||
const balanceA = balances[accountA.address];
|
||||
const balanceB = balances[accountB.address];
|
||||
|
||||
if (!balanceA && !balanceB) return 0;
|
||||
if (balanceA && !balanceB) return -1;
|
||||
if (!balanceA && balanceB) return 1;
|
||||
|
||||
const ethA = balanceA.tokens
|
||||
.find(token => token.token.tag.toLowerCase() === 'eth')
|
||||
.value;
|
||||
const ethB = balanceB.tokens
|
||||
.find(token => token.token.tag.toLowerCase() === 'eth')
|
||||
.value;
|
||||
|
||||
return -1 * ethA.comparedTo(ethB);
|
||||
}
|
||||
|
||||
if (key === 'tags') {
|
||||
const tagsA = [].concat(accountA.meta.tags)
|
||||
.filter(t => t)
|
||||
.sort();
|
||||
.sort()
|
||||
.join('');
|
||||
|
||||
const tagsB = [].concat(accountB.meta.tags)
|
||||
.filter(t => t)
|
||||
.sort();
|
||||
.sort()
|
||||
.join('');
|
||||
|
||||
if (tagsA.length === 0) return 1;
|
||||
if (tagsB.length === 0) return -1;
|
||||
if (!tagsA && !tagsB) return 0;
|
||||
if (tagsA && !tagsB) return -1;
|
||||
if (!tagsA && tagsB) return 1;
|
||||
|
||||
return tagsA.join('').localeCompare(tagsB.join(''));
|
||||
return tagsA.localeCompare(tagsB);
|
||||
}
|
||||
});
|
||||
|
||||
const metaA = accountA.meta[key];
|
||||
const metaB = accountB.meta[key];
|
||||
|
||||
if (!metaA && !metaB) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((metaA && !metaB) || (metaA < metaB)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((!metaA && metaB) || (metaA > metaB)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
getFilteredAddresses () {
|
||||
|
@ -15,16 +15,24 @@
|
||||
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
.status {
|
||||
clear: both;
|
||||
padding: 1.5em;
|
||||
text-align: right;
|
||||
color: #ddd;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0 0.5em 0 2em;
|
||||
}
|
||||
|
||||
.enode {
|
||||
width: 45em;
|
||||
word-wrap: break-word;
|
||||
margin: 0.5em 0 0.25em;
|
||||
}
|
||||
|
||||
.block {
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ class Status extends Component {
|
||||
static propTypes = {
|
||||
blockNumber: PropTypes.object.isRequired,
|
||||
clientVersion: PropTypes.string,
|
||||
enode: PropTypes.string,
|
||||
netPeers: PropTypes.object,
|
||||
netChain: PropTypes.string,
|
||||
isTest: PropTypes.bool
|
||||
@ -44,6 +45,7 @@ class Status extends Component {
|
||||
<div className={ styles.version }>
|
||||
{ clientVersion }
|
||||
</div>
|
||||
{ this.renderEnode() }
|
||||
<div className={ styles.netinfo }>
|
||||
<div>
|
||||
<BlockStatus />
|
||||
@ -58,14 +60,29 @@ class Status extends Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderEnode () {
|
||||
const { enode } = this.props;
|
||||
|
||||
if (!enode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.enode }>
|
||||
{ enode }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps (state) {
|
||||
const { blockNumber, clientVersion, netPeers, netChain, isTest } = state.nodeStatus;
|
||||
const { blockNumber, clientVersion, enode, netPeers, netChain, isTest } = state.nodeStatus;
|
||||
|
||||
return {
|
||||
blockNumber,
|
||||
clientVersion,
|
||||
enode,
|
||||
netPeers,
|
||||
netChain,
|
||||
isTest
|
||||
|
@ -19,7 +19,7 @@ import React, { Component, PropTypes } from 'react';
|
||||
import LinearProgress from 'material-ui/LinearProgress';
|
||||
import { Card, CardActions, CardTitle, CardText } from 'material-ui/Card';
|
||||
|
||||
import { Button, Input } from '../../../ui';
|
||||
import { Button, Input, InputAddressSelect } from '../../../ui';
|
||||
|
||||
import styles from './queries.css';
|
||||
|
||||
@ -124,8 +124,8 @@ export default class InputQuery extends Component {
|
||||
const { name, type } = input;
|
||||
const label = `${name ? `${name}: ` : ''}${type}`;
|
||||
|
||||
const onChange = (event) => {
|
||||
const value = event.target.value;
|
||||
const onChange = (event, input) => {
|
||||
const value = event && event.target.value || input;
|
||||
const { values } = this.state;
|
||||
|
||||
this.setState({
|
||||
@ -136,6 +136,19 @@ export default class InputQuery extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
if (type === 'address') {
|
||||
return (
|
||||
<div key={ name }>
|
||||
<InputAddressSelect
|
||||
hint={ type }
|
||||
label={ label }
|
||||
required
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={ name }>
|
||||
<Input
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
.txhash {
|
||||
text-overflow: ellipsis;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.key {
|
||||
@ -82,6 +83,7 @@
|
||||
.eventAddress {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.eventIdentityicon {
|
||||
|
@ -312,7 +312,7 @@ class Contract extends Component {
|
||||
|
||||
const contract = api.newContract(account.meta.abi, params.address);
|
||||
contract
|
||||
.subscribe(null, { limit: 50, fromBlock: 0, toBlock: 'pending' }, this._receiveEvents)
|
||||
.subscribe(null, { limit: 25, fromBlock: 0, toBlock: 'pending' }, this._receiveEvents)
|
||||
.then((subscriptionId) => {
|
||||
this.setState({ subscriptionId });
|
||||
});
|
||||
|
@ -42,7 +42,7 @@ class Contracts extends Component {
|
||||
state = {
|
||||
addContract: false,
|
||||
deployContract: false,
|
||||
sortOrder: '',
|
||||
sortOrder: 'timestamp',
|
||||
searchValues: [],
|
||||
searchTokens: []
|
||||
}
|
||||
@ -65,6 +65,7 @@ class Contracts extends Component {
|
||||
balances={ balances }
|
||||
empty={ !hasContracts }
|
||||
order={ sortOrder }
|
||||
orderFallback='name'
|
||||
handleAddSearchToken={ this.onAddSearchToken } />
|
||||
</Page>
|
||||
</div>
|
||||
@ -80,6 +81,10 @@ class Contracts extends Component {
|
||||
<ActionbarSort
|
||||
key='sortAccounts'
|
||||
order={ this.state.sortOrder }
|
||||
metas={ [
|
||||
{ key: 'timestamp', label: 'date' }
|
||||
] }
|
||||
showDefault={ false }
|
||||
onChange={ onChange } />
|
||||
);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ use regex::Regex;
|
||||
use util::RotatingLogger;
|
||||
use util::log::Colour;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Config {
|
||||
pub mode: Option<String>,
|
||||
pub color: bool,
|
||||
|
@ -1,3 +1,9 @@
|
||||
!include WinMessages.nsh
|
||||
|
||||
!define WND_CLASS "Parity"
|
||||
!define WND_TITLE "Parity"
|
||||
!define WAIT_MS 5000
|
||||
!define SYNC_TERM 0x00100001
|
||||
|
||||
!define APPNAME "Parity"
|
||||
!define COMPANYNAME "Ethcore"
|
||||
@ -5,6 +11,7 @@
|
||||
!define VERSIONMAJOR 1
|
||||
!define VERSIONMINOR 4
|
||||
!define VERSIONBUILD 0
|
||||
!define ARGS "--warp --mode=passive"
|
||||
|
||||
!addplugindir .\
|
||||
|
||||
@ -13,6 +20,10 @@
|
||||
!define ABOUTURL "https://github.com/ethcore/parity" # "Publisher" link
|
||||
!define INSTALLSIZE 26120
|
||||
|
||||
!define termMsg "Installer cannot stop running ${WND_TITLE}.$\nDo you want to terminate process?"
|
||||
!define stopMsg "Stopping ${WND_TITLE} Application"
|
||||
|
||||
|
||||
RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on)
|
||||
|
||||
InstallDir "$PROGRAMFILES64\${COMPANYNAME}\${APPNAME}"
|
||||
@ -26,7 +37,7 @@ outFile "installer.exe"
|
||||
|
||||
page license
|
||||
page directory
|
||||
Page instfiles
|
||||
page instfiles
|
||||
|
||||
!macro VerifyUserIsAdmin
|
||||
UserInfo::GetAccountType
|
||||
@ -38,6 +49,31 @@ ${If} $0 != "admin" ;Require admin rights on NT4+
|
||||
${EndIf}
|
||||
!macroend
|
||||
|
||||
!macro TerminateApp
|
||||
Push $0 ; window handle
|
||||
Push $1
|
||||
Push $2 ; process handle
|
||||
DetailPrint "$(stopMsg)"
|
||||
FindWindow $0 '${WND_CLASS}' ''
|
||||
IntCmp $0 0 done
|
||||
System::Call 'user32.dll::GetWindowThreadProcessId(i r0, *i .r1) i .r2'
|
||||
System::Call 'kernel32.dll::OpenProcess(i ${SYNC_TERM}, i 0, i r1) i .r2'
|
||||
SendMessage $0 ${WM_CLOSE} 0 0 /TIMEOUT=${TO_MS}
|
||||
System::Call 'kernel32.dll::WaitForSingleObject(i r2, i ${WAIT_MS}) i .r1'
|
||||
IntCmp $1 0 close
|
||||
MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION "$(termMsg)" /SD IDYES IDYES terminate IDNO close
|
||||
System::Call 'kernel32.dll::CloseHandle(i r2) i .r1'
|
||||
Quit
|
||||
terminate:
|
||||
System::Call 'kernel32.dll::TerminateProcess(i r2, i 0) i .r1'
|
||||
close:
|
||||
System::Call 'kernel32.dll::CloseHandle(i r2) i .r1'
|
||||
done:
|
||||
Pop $2
|
||||
Pop $1
|
||||
Pop $0
|
||||
!macroend
|
||||
|
||||
function .onInit
|
||||
setShellVarContext all
|
||||
!insertmacro VerifyUserIsAdmin
|
||||
@ -48,10 +84,13 @@ section "install"
|
||||
setOutPath $INSTDIR
|
||||
# Files added here should be removed by the uninstaller (see section "uninstall")
|
||||
file /oname=parity.exe ..\target\release\parity.exe
|
||||
file /oname=ptray.exe ..\windows\ptray\Release\ptray.exe
|
||||
|
||||
file "logo.ico"
|
||||
file vc_redist.x64.exe
|
||||
|
||||
ExecWait '"$INSTDIR\vc_redist.x64.exe" /passive /norestart'
|
||||
delete $INSTDIR\vc_redist.x64.exe
|
||||
# Add any other files for the install directory (license files, app data, etc) here
|
||||
|
||||
# Uninstaller - See function un.onInit and section "uninstall" for configuration
|
||||
@ -79,11 +118,11 @@ section "install"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "InstallLocation" "$\"$INSTDIR$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayIcon" "$\"$INSTDIR\logo.ico$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "Publisher" "$\"${COMPANYNAME}$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "Publisher" "${COMPANYNAME}"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "HelpLink" "$\"${HELPURL}$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "URLUpdateInfo" "$\"${UPDATEURL}$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "URLInfoAbout" "$\"${ABOUTURL}$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayVersion" "$\"${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}$\""
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayVersion" "${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "VersionMajor" ${VERSIONMAJOR}
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "VersionMinor" ${VERSIONMINOR}
|
||||
# There is no option for modifying or repairing the install
|
||||
@ -91,6 +130,9 @@ section "install"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "NoRepair" 1
|
||||
# Set the INSTALLSIZE constant (!defined at the top of this script) so Add/Remove Programs can accurately report the size
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "EstimatedSize" ${INSTALLSIZE}
|
||||
|
||||
WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Run" ${APPNAME} "$INSTDIR\ptray.exe ${ARGS}"
|
||||
ExecShell "" "$INSTDIR\ptray.exe" "${ARGS}"
|
||||
sectionEnd
|
||||
|
||||
# Uninstaller
|
||||
@ -107,7 +149,7 @@ function un.onInit
|
||||
functionEnd
|
||||
|
||||
section "uninstall"
|
||||
|
||||
!insertmacro TerminateApp
|
||||
# Remove Start Menu launcher
|
||||
delete "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk"
|
||||
# Try to remove the Start Menu folder - this will only happen if it is empty
|
||||
@ -115,6 +157,7 @@ section "uninstall"
|
||||
|
||||
# Remove files
|
||||
delete $INSTDIR\parity.exe
|
||||
delete $INSTDIR\ptray.exe
|
||||
delete $INSTDIR\logo.ico
|
||||
|
||||
# Always delete uninstaller as the last action
|
||||
@ -131,5 +174,6 @@ section "uninstall"
|
||||
|
||||
# Remove uninstaller information from the registry
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}"
|
||||
|
||||
DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "${APPNAME}"
|
||||
sectionEnd
|
||||
|
||||
|
BIN
nsis/logo.ico
BIN
nsis/logo.ico
Binary file not shown.
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 66 KiB |
@ -21,7 +21,6 @@ use std::time::{Instant, Duration};
|
||||
use std::thread::sleep;
|
||||
use std::sync::Arc;
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use ethcore_logger::{setup_log, Config as LogConfig};
|
||||
use io::{PanicHandler, ForwardPanic};
|
||||
use util::{ToPretty, Uint};
|
||||
use rlp::PayloadInfo;
|
||||
@ -71,7 +70,6 @@ pub enum BlockchainCmd {
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ImportBlockchain {
|
||||
pub spec: SpecType,
|
||||
pub logger_config: LogConfig,
|
||||
pub cache_config: CacheConfig,
|
||||
pub dirs: Directories,
|
||||
pub file_path: Option<String>,
|
||||
@ -85,12 +83,12 @@ pub struct ImportBlockchain {
|
||||
pub fat_db: Switch,
|
||||
pub vm_type: VMType,
|
||||
pub check_seal: bool,
|
||||
pub with_color: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ExportBlockchain {
|
||||
pub spec: SpecType,
|
||||
pub logger_config: LogConfig,
|
||||
pub cache_config: CacheConfig,
|
||||
pub dirs: Directories,
|
||||
pub file_path: Option<String>,
|
||||
@ -120,9 +118,6 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
||||
// Setup panic handler
|
||||
let panic_handler = PanicHandler::new_in_arc();
|
||||
|
||||
// Setup logging
|
||||
let _logger = setup_log(&cmd.logger_config);
|
||||
|
||||
// create dirs used by parity
|
||||
try!(cmd.dirs.create_dirs());
|
||||
|
||||
@ -196,7 +191,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
|
||||
}
|
||||
};
|
||||
|
||||
let informant = Informant::new(client.clone(), None, None, None, cmd.logger_config.color);
|
||||
let informant = Informant::new(client.clone(), None, None, None, cmd.with_color);
|
||||
|
||||
try!(service.register_io_handler(Arc::new(ImportIoHandler {
|
||||
info: Arc::new(informant),
|
||||
@ -269,9 +264,6 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
|
||||
// Setup panic handler
|
||||
let panic_handler = PanicHandler::new_in_arc();
|
||||
|
||||
// Setup logging
|
||||
let _logger = setup_log(&cmd.logger_config);
|
||||
|
||||
// create dirs used by parity
|
||||
try!(cmd.dirs.create_dirs());
|
||||
|
||||
|
@ -35,7 +35,7 @@ use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras};
|
||||
use ethcore_logger::Config as LogConfig;
|
||||
use dir::Directories;
|
||||
use dapps::Configuration as DappsConfiguration;
|
||||
use signer::Configuration as SignerConfiguration;
|
||||
use signer::{Configuration as SignerConfiguration, SignerCommand};
|
||||
use run::RunCmd;
|
||||
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat};
|
||||
use presale::ImportWallet;
|
||||
@ -49,11 +49,16 @@ pub enum Cmd {
|
||||
Account(AccountCmd),
|
||||
ImportPresaleWallet(ImportWallet),
|
||||
Blockchain(BlockchainCmd),
|
||||
SignerToken(String),
|
||||
SignerToken(SignerCommand),
|
||||
Snapshot(SnapshotCommand),
|
||||
Hash(Option<String>),
|
||||
}
|
||||
|
||||
pub struct Execute {
|
||||
pub logger: LogConfig,
|
||||
pub cmd: Cmd,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Configuration {
|
||||
pub args: Args,
|
||||
@ -70,7 +75,7 @@ impl Configuration {
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn into_command(self) -> Result<Cmd, String> {
|
||||
pub fn into_command(self) -> Result<Execute, String> {
|
||||
let dirs = self.directories();
|
||||
let pruning = try!(self.args.flag_pruning.parse());
|
||||
let pruning_history = self.args.flag_pruning_history;
|
||||
@ -99,7 +104,9 @@ impl Configuration {
|
||||
let cmd = if self.args.flag_version {
|
||||
Cmd::Version
|
||||
} else if self.args.cmd_signer && self.args.cmd_new_token {
|
||||
Cmd::SignerToken(dirs.signer)
|
||||
Cmd::SignerToken(SignerCommand {
|
||||
path: dirs.signer
|
||||
})
|
||||
} else if self.args.cmd_tools && self.args.cmd_hash {
|
||||
Cmd::Hash(self.args.arg_file)
|
||||
} else if self.args.cmd_account {
|
||||
@ -141,7 +148,6 @@ impl Configuration {
|
||||
} else if self.args.cmd_import {
|
||||
let import_cmd = ImportBlockchain {
|
||||
spec: spec,
|
||||
logger_config: logger_config,
|
||||
cache_config: cache_config,
|
||||
dirs: dirs,
|
||||
file_path: self.args.arg_file.clone(),
|
||||
@ -155,12 +161,12 @@ impl Configuration {
|
||||
fat_db: fat_db,
|
||||
vm_type: vm_type,
|
||||
check_seal: !self.args.flag_no_seal_check,
|
||||
with_color: logger_config.color,
|
||||
};
|
||||
Cmd::Blockchain(BlockchainCmd::Import(import_cmd))
|
||||
} else if self.args.cmd_export {
|
||||
let export_cmd = ExportBlockchain {
|
||||
spec: spec,
|
||||
logger_config: logger_config,
|
||||
cache_config: cache_config,
|
||||
dirs: dirs,
|
||||
file_path: self.args.arg_file.clone(),
|
||||
@ -184,7 +190,6 @@ impl Configuration {
|
||||
spec: spec,
|
||||
pruning: pruning,
|
||||
pruning_history: pruning_history,
|
||||
logger_config: logger_config,
|
||||
mode: mode,
|
||||
tracing: tracing,
|
||||
fat_db: fat_db,
|
||||
@ -202,7 +207,6 @@ impl Configuration {
|
||||
spec: spec,
|
||||
pruning: pruning,
|
||||
pruning_history: pruning_history,
|
||||
logger_config: logger_config,
|
||||
mode: mode,
|
||||
tracing: tracing,
|
||||
fat_db: fat_db,
|
||||
@ -227,7 +231,7 @@ impl Configuration {
|
||||
pruning: pruning,
|
||||
pruning_history: pruning_history,
|
||||
daemon: daemon,
|
||||
logger_config: logger_config,
|
||||
logger_config: logger_config.clone(),
|
||||
miner_options: miner_options,
|
||||
http_conf: http_conf,
|
||||
ipc_conf: ipc_conf,
|
||||
@ -258,7 +262,10 @@ impl Configuration {
|
||||
Cmd::Run(run_cmd)
|
||||
};
|
||||
|
||||
Ok(cmd)
|
||||
Ok(Execute {
|
||||
logger: logger_config,
|
||||
cmd: cmd,
|
||||
})
|
||||
}
|
||||
|
||||
fn enable_network(&self, mode: &Mode) -> bool {
|
||||
@ -684,7 +691,7 @@ mod tests {
|
||||
use ethcore::miner::{MinerOptions, PrioritizationStrategy};
|
||||
use helpers::{replace_home, default_network_config};
|
||||
use run::RunCmd;
|
||||
use signer::Configuration as SignerConfiguration;
|
||||
use signer::{Configuration as SignerConfiguration, SignerCommand};
|
||||
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat};
|
||||
use presale::ImportWallet;
|
||||
use account::{AccountCmd, NewAccount, ImportAccounts};
|
||||
@ -705,14 +712,14 @@ mod tests {
|
||||
fn test_command_version() {
|
||||
let args = vec!["parity", "--version"];
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap(), Cmd::Version);
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Version);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_command_account_new() {
|
||||
let args = vec!["parity", "account", "new"];
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap(), Cmd::Account(AccountCmd::New(NewAccount {
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::New(NewAccount {
|
||||
iterations: 10240,
|
||||
path: replace_home("$HOME/.parity/keys"),
|
||||
password_file: None,
|
||||
@ -723,16 +730,16 @@ mod tests {
|
||||
fn test_command_account_list() {
|
||||
let args = vec!["parity", "account", "list"];
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap(), Cmd::Account(
|
||||
AccountCmd::List(replace_home("$HOME/.parity/keys")))
|
||||
);
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(
|
||||
AccountCmd::List(replace_home("$HOME/.parity/keys")),
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_command_account_import() {
|
||||
let args = vec!["parity", "account", "import", "my_dir", "another_dir"];
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap(), Cmd::Account(AccountCmd::Import(ImportAccounts {
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Account(AccountCmd::Import(ImportAccounts {
|
||||
from: vec!["my_dir".into(), "another_dir".into()],
|
||||
to: replace_home("$HOME/.parity/keys"),
|
||||
})));
|
||||
@ -742,7 +749,7 @@ mod tests {
|
||||
fn test_command_wallet_import() {
|
||||
let args = vec!["parity", "wallet", "import", "my_wallet.json", "--password", "pwd"];
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap(), Cmd::ImportPresaleWallet(ImportWallet {
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::ImportPresaleWallet(ImportWallet {
|
||||
iterations: 10240,
|
||||
path: replace_home("$HOME/.parity/keys"),
|
||||
wallet_path: "my_wallet.json".into(),
|
||||
@ -754,9 +761,8 @@ mod tests {
|
||||
fn test_command_blockchain_import() {
|
||||
let args = vec!["parity", "import", "blockchain.json"];
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap(), Cmd::Blockchain(BlockchainCmd::Import(ImportBlockchain {
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Import(ImportBlockchain {
|
||||
spec: Default::default(),
|
||||
logger_config: Default::default(),
|
||||
cache_config: Default::default(),
|
||||
dirs: Default::default(),
|
||||
file_path: Some("blockchain.json".into()),
|
||||
@ -770,6 +776,7 @@ mod tests {
|
||||
fat_db: Default::default(),
|
||||
vm_type: VMType::Interpreter,
|
||||
check_seal: true,
|
||||
with_color: !cfg!(windows),
|
||||
})));
|
||||
}
|
||||
|
||||
@ -777,9 +784,8 @@ mod tests {
|
||||
fn test_command_blockchain_export() {
|
||||
let args = vec!["parity", "export", "blockchain.json"];
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap(), Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
|
||||
spec: Default::default(),
|
||||
logger_config: Default::default(),
|
||||
cache_config: Default::default(),
|
||||
dirs: Default::default(),
|
||||
file_path: Some("blockchain.json".into()),
|
||||
@ -801,9 +807,8 @@ mod tests {
|
||||
fn test_command_blockchain_export_with_custom_format() {
|
||||
let args = vec!["parity", "export", "--format", "hex", "blockchain.json"];
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap(), Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
|
||||
spec: Default::default(),
|
||||
logger_config: Default::default(),
|
||||
cache_config: Default::default(),
|
||||
dirs: Default::default(),
|
||||
file_path: Some("blockchain.json".into()),
|
||||
@ -826,14 +831,16 @@ mod tests {
|
||||
let args = vec!["parity", "signer", "new-token"];
|
||||
let conf = parse(&args);
|
||||
let expected = replace_home("$HOME/.parity/signer");
|
||||
assert_eq!(conf.into_command().unwrap(), Cmd::SignerToken(expected));
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::SignerToken(SignerCommand {
|
||||
path: expected,
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_run_cmd() {
|
||||
let args = vec!["parity"];
|
||||
let conf = parse(&args);
|
||||
assert_eq!(conf.into_command().unwrap(), Cmd::Run(RunCmd {
|
||||
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Run(RunCmd {
|
||||
cache_config: Default::default(),
|
||||
dirs: Default::default(),
|
||||
spec: Default::default(),
|
||||
|
@ -114,12 +114,13 @@ mod user_defaults;
|
||||
mod stratum;
|
||||
|
||||
use std::{process, env};
|
||||
use std::io::BufReader;
|
||||
use std::io::{self as stdio, BufReader, Write};
|
||||
use std::fs::File;
|
||||
use util::sha3::sha3;
|
||||
use cli::Args;
|
||||
use configuration::{Cmd, Configuration};
|
||||
use configuration::{Cmd, Execute, Configuration};
|
||||
use deprecated::find_deprecated;
|
||||
use ethcore_logger::setup_log;
|
||||
|
||||
fn print_hash_of(maybe_file: Option<String>) -> Result<String, String> {
|
||||
if let Some(file) = maybe_file {
|
||||
@ -131,10 +132,12 @@ fn print_hash_of(maybe_file: Option<String>) -> Result<String, String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn execute(command: Cmd) -> Result<String, String> {
|
||||
match command {
|
||||
fn execute(command: Execute) -> Result<String, String> {
|
||||
let logger = setup_log(&command.logger).expect("Logger is initialized only once; qed");
|
||||
|
||||
match command.cmd {
|
||||
Cmd::Run(run_cmd) => {
|
||||
try!(run::execute(run_cmd));
|
||||
try!(run::execute(run_cmd, logger));
|
||||
Ok("".into())
|
||||
},
|
||||
Cmd::Version => Ok(Args::print_version()),
|
||||
@ -142,7 +145,7 @@ fn execute(command: Cmd) -> Result<String, String> {
|
||||
Cmd::Account(account_cmd) => account::execute(account_cmd),
|
||||
Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd),
|
||||
Cmd::Blockchain(blockchain_cmd) => blockchain::execute(blockchain_cmd),
|
||||
Cmd::SignerToken(path) => signer::new_token(path),
|
||||
Cmd::SignerToken(signer_cmd) => signer::execute(signer_cmd),
|
||||
Cmd::Snapshot(snapshot_cmd) => snapshot::execute(snapshot_cmd),
|
||||
}
|
||||
}
|
||||
@ -210,7 +213,7 @@ fn main() {
|
||||
info!("{}", result);
|
||||
},
|
||||
Err(err) => {
|
||||
info!("{}", err);
|
||||
writeln!(&mut stdio::stderr(), "{}", err).expect("StdErr available; qed");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -15,13 +15,14 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::sync::{Arc, Mutex, Condvar};
|
||||
use std::net::{TcpListener};
|
||||
use ctrlc::CtrlC;
|
||||
use fdlimit::raise_fd_limit;
|
||||
use ethcore_logger::{Config as LogConfig, setup_log};
|
||||
use ethcore_rpc::{NetworkSettings, is_major_importing};
|
||||
use ethsync::NetworkConfiguration;
|
||||
use util::{Colour, version, U256};
|
||||
use util::{Colour, version, U256, RotatingLogger};
|
||||
use io::{MayPanic, ForwardPanic, PanicHandler};
|
||||
use ethcore_logger::{Config as LogConfig};
|
||||
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, ChainNotify, BlockChainClient};
|
||||
use ethcore::service::ClientService;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
@ -93,13 +94,19 @@ pub struct RunCmd {
|
||||
pub check_seal: bool,
|
||||
}
|
||||
|
||||
pub fn execute(cmd: RunCmd) -> Result<(), String> {
|
||||
pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
||||
if cmd.ui && cmd.dapps_conf.enabled {
|
||||
// Check if Parity is already running
|
||||
let addr = format!("{}:{}", cmd.dapps_conf.interface, cmd.dapps_conf.port);
|
||||
if !TcpListener::bind(&addr as &str).is_ok() {
|
||||
url::open(&format!("http://{}:{}/", cmd.dapps_conf.interface, cmd.dapps_conf.port));
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// set up panic handler
|
||||
let panic_handler = PanicHandler::new_in_arc();
|
||||
|
||||
// set up logger
|
||||
let logger = try!(setup_log(&cmd.logger_config));
|
||||
|
||||
// increase max number of open files
|
||||
raise_fd_limit();
|
||||
|
||||
|
@ -68,8 +68,13 @@ fn codes_path(path: String) -> PathBuf {
|
||||
p
|
||||
}
|
||||
|
||||
pub fn new_token(path: String) -> Result<String, String> {
|
||||
generate_new_token(path)
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct SignerCommand {
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
pub fn execute(cmd: SignerCommand) -> Result<String, String> {
|
||||
generate_new_token(cmd.path)
|
||||
.map(|code| format!("This key code will authorise your System Signer UI: {}", Colour::White.bold().paint(code)))
|
||||
.map_err(|err| format!("Error generating token: {:?}", err))
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ use std::time::Duration;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ethcore_logger::{setup_log, Config as LogConfig};
|
||||
use ethcore::snapshot::{Progress, RestorationStatus, SnapshotService as SS};
|
||||
use ethcore::snapshot::io::{SnapshotReader, PackedReader, PackedWriter};
|
||||
use ethcore::snapshot::service::Service as SnapshotService;
|
||||
@ -55,7 +54,6 @@ pub struct SnapshotCommand {
|
||||
pub spec: SpecType,
|
||||
pub pruning: Pruning,
|
||||
pub pruning_history: u64,
|
||||
pub logger_config: LogConfig,
|
||||
pub mode: Mode,
|
||||
pub tracing: Switch,
|
||||
pub fat_db: Switch,
|
||||
@ -141,9 +139,6 @@ impl SnapshotCommand {
|
||||
// load user defaults
|
||||
let user_defaults = try!(UserDefaults::load(&user_defaults_path));
|
||||
|
||||
// Setup logging
|
||||
let _logger = setup_log(&self.logger_config);
|
||||
|
||||
fdlimit::raise_fd_limit();
|
||||
|
||||
// select pruning algorithm
|
||||
|
@ -41,6 +41,7 @@ mod codes {
|
||||
pub const ACCOUNT_ERROR: i64 = -32023;
|
||||
pub const SIGNER_DISABLED: i64 = -32030;
|
||||
pub const DAPPS_DISABLED: i64 = -32031;
|
||||
pub const NETWORK_DISABLED: i64 = -32035;
|
||||
pub const REQUEST_REJECTED: i64 = -32040;
|
||||
pub const REQUEST_REJECTED_LIMIT: i64 = -32041;
|
||||
pub const REQUEST_NOT_FOUND: i64 = -32042;
|
||||
@ -185,6 +186,14 @@ pub fn dapps_disabled() -> Error {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn network_disabled() -> Error {
|
||||
Error {
|
||||
code: ErrorCode::ServerError(codes::NETWORK_DISABLED),
|
||||
message: "Network is disabled or not yet up.".into(),
|
||||
data: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encryption_error<T: fmt::Debug>(error: T) -> Error {
|
||||
Error {
|
||||
code: ErrorCode::ServerError(codes::ENCRYPTION_ERROR),
|
||||
|
@ -353,4 +353,8 @@ impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where
|
||||
Mode::Active => "active",
|
||||
}.into())
|
||||
}
|
||||
|
||||
fn enode(&self) -> Result<String, Error> {
|
||||
take_weak!(self.sync).enode().ok_or_else(errors::network_disabled)
|
||||
}
|
||||
}
|
||||
|
@ -93,5 +93,9 @@ impl SyncProvider for TestSyncProvider {
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
fn enode(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,5 +133,9 @@ build_rpc_trait! {
|
||||
/// Get the mode. Results one of: "active", "passive", "dark", "off".
|
||||
#[rpc(name = "ethcore_mode")]
|
||||
fn mode(&self) -> Result<String, Error>;
|
||||
|
||||
/// Get the enode of this node.
|
||||
#[rpc(name = "ethcore_enode")]
|
||||
fn enode(&self) -> Result<String, Error>;
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +73,9 @@ pub trait SyncProvider: Send + Sync {
|
||||
|
||||
/// Get peers information
|
||||
fn peers(&self) -> Vec<PeerInfo>;
|
||||
|
||||
/// Get the enode if available.
|
||||
fn enode(&self) -> Option<String>;
|
||||
}
|
||||
|
||||
/// Peer connection information
|
||||
@ -143,6 +146,10 @@ impl SyncProvider for EthSync {
|
||||
self.handler.sync.write().peers(&sync_io)
|
||||
}).unwrap_or(Vec::new())
|
||||
}
|
||||
|
||||
fn enode(&self) -> Option<String> {
|
||||
self.network.external_url()
|
||||
}
|
||||
}
|
||||
|
||||
struct SyncProtocolHandler {
|
||||
|
@ -32,7 +32,8 @@ use node_table::NodeId;
|
||||
use stats::NetworkStats;
|
||||
use time;
|
||||
|
||||
const PING_TIMEOUT_SEC: u64 = 65;
|
||||
// Timeout must be less than (interval - 1).
|
||||
const PING_TIMEOUT_SEC: u64 = 15;
|
||||
const PING_INTERVAL_SEC: u64 = 30;
|
||||
|
||||
/// Peer session over encrypted connection.
|
||||
|
@ -30,7 +30,7 @@ pub struct Histogram {
|
||||
impl Histogram {
|
||||
/// Histogram if a sorted corpus is at least fills the buckets.
|
||||
pub fn new(corpus: &[U256], bucket_number: usize) -> Option<Histogram> {
|
||||
if corpus.len() < bucket_number { return None; }
|
||||
if corpus.len() <= bucket_number { return None; }
|
||||
let corpus_end = corpus.last().expect("there are at least bucket_number elements; qed").clone();
|
||||
// If there are extremely few transactions, go from zero.
|
||||
let corpus_start = corpus.first().expect("there are at least bucket_number elements; qed").clone();
|
||||
@ -67,4 +67,9 @@ mod tests {
|
||||
|
||||
assert!(Histogram::new(&vec_into![1, 2], 5).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_panic_when_asking_for_bucket_too_big() {
|
||||
assert!(Histogram::new(&vec_into![1, 2], 2).is_none());
|
||||
}
|
||||
}
|
||||
|
274
windows/ptray/ptray.cpp
Normal file
274
windows/ptray/ptray.cpp
Normal file
@ -0,0 +1,274 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
#include <tchar.h>
|
||||
#include <Windows.h>
|
||||
#include <Shellapi.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
#pragma comment(lib, "shlwapi.lib")
|
||||
|
||||
#define MAX_LOADSTRING 100
|
||||
#define IDM_EXIT 100
|
||||
#define IDM_OPEN 101
|
||||
#define WM_USER_SHELLICON WM_USER + 1
|
||||
|
||||
HANDLE parityHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD parityProcId = 0;
|
||||
NOTIFYICONDATA nidApp;
|
||||
WCHAR szTitle[MAX_LOADSTRING];
|
||||
WCHAR szWindowClass[MAX_LOADSTRING];
|
||||
|
||||
LPCWSTR cParityExe = _T("parity.exe");
|
||||
|
||||
ATOM MyRegisterClass(HINSTANCE hInstance);
|
||||
bool InitInstance(HINSTANCE, int, LPWSTR cmdLine);
|
||||
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
void KillParity();
|
||||
void OpenUI();
|
||||
bool ParityIsRunning();
|
||||
|
||||
bool GetParityExePath(TCHAR* dest, size_t destSize)
|
||||
{
|
||||
if (!dest || MAX_PATH > destSize)
|
||||
return false;
|
||||
GetModuleFileName(NULL, dest, destSize);
|
||||
if (!PathRemoveFileSpec(dest))
|
||||
return false;
|
||||
return PathAppend(dest, _T("parity.exe")) == TRUE;
|
||||
}
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
|
||||
_In_opt_ HINSTANCE hPrevInstance,
|
||||
_In_ LPWSTR lpCmdLine,
|
||||
_In_ int nCmdShow)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(hPrevInstance);
|
||||
UNREFERENCED_PARAMETER(lpCmdLine);
|
||||
|
||||
CreateMutex(0, FALSE, _T("Local\\ParityTray"));
|
||||
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
return -1;
|
||||
|
||||
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
|
||||
LoadStringW(hInstance, IDC_PTRAY, szWindowClass, MAX_LOADSTRING);
|
||||
MyRegisterClass(hInstance);
|
||||
|
||||
if (!InitInstance(hInstance, nCmdShow, lpCmdLine))
|
||||
return FALSE;
|
||||
|
||||
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PTRAY));
|
||||
MSG msg;
|
||||
// Main message loop:
|
||||
while (GetMessage(&msg, nullptr, 0, 0))
|
||||
{
|
||||
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)msg.wParam;
|
||||
}
|
||||
|
||||
ATOM MyRegisterClass(HINSTANCE hInstance)
|
||||
{
|
||||
WNDCLASSEXW wcex;
|
||||
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcex.lpfnWndProc = WndProc;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
wcex.hInstance = hInstance;
|
||||
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PTRAY));
|
||||
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PTRAY);
|
||||
wcex.lpszClassName = szWindowClass;
|
||||
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
|
||||
|
||||
return RegisterClassExW(&wcex);
|
||||
}
|
||||
|
||||
|
||||
bool InitInstance(HINSTANCE hInstance, int nCmdShow, LPWSTR cmdLine)
|
||||
{
|
||||
// Check if already running
|
||||
PROCESSENTRY32 entry;
|
||||
entry.dwSize = sizeof(PROCESSENTRY32);
|
||||
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
|
||||
if (Process32First(snapshot, &entry) == TRUE)
|
||||
{
|
||||
while (Process32Next(snapshot, &entry) == TRUE)
|
||||
{
|
||||
if (lstrcmp(entry.szExeFile, cParityExe) == 0)
|
||||
{
|
||||
parityHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID);
|
||||
parityProcId = entry.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(snapshot);
|
||||
|
||||
if (parityHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// Launch parity
|
||||
TCHAR path[MAX_PATH] = { 0 };
|
||||
if (!GetParityExePath(path, MAX_PATH))
|
||||
return false;
|
||||
|
||||
PROCESS_INFORMATION procInfo = { 0 };
|
||||
STARTUPINFO startupInfo = { sizeof(STARTUPINFO) };
|
||||
|
||||
LPWSTR cmd = new WCHAR[lstrlen(cmdLine) + lstrlen(path) + 2];
|
||||
lstrcpy(cmd, path);
|
||||
lstrcat(cmd, _T(" "));
|
||||
lstrcat(cmd, cmdLine);
|
||||
if (!CreateProcess(nullptr, cmd, nullptr, nullptr, false, CREATE_NO_WINDOW, nullptr, nullptr, &startupInfo, &procInfo))
|
||||
return false;
|
||||
delete[] cmd;
|
||||
parityHandle = procInfo.hProcess;
|
||||
parityProcId = procInfo.dwProcessId;
|
||||
}
|
||||
|
||||
HWND hWnd = CreateWindowW(szWindowClass, szTitle, 0,
|
||||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
|
||||
|
||||
if (!hWnd)
|
||||
return false;
|
||||
|
||||
HICON hMainIcon = LoadIcon(hInstance, (LPCTSTR)MAKEINTRESOURCE(IDI_PTRAY));
|
||||
|
||||
nidApp.cbSize = sizeof(NOTIFYICONDATA); // sizeof the struct in bytes
|
||||
nidApp.hWnd = (HWND)hWnd; //handle of the window which will process this app. messages
|
||||
nidApp.uID = IDI_PTRAY; //ID of the icon that willl appear in the system tray
|
||||
nidApp.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; //ORing of all the flags
|
||||
nidApp.hIcon = hMainIcon; // handle of the Icon to be displayed, obtained from LoadIcon
|
||||
nidApp.uCallbackMessage = WM_USER_SHELLICON;
|
||||
LoadString(hInstance, IDS_CONTROL_PARITY, nidApp.szTip, MAX_LOADSTRING);
|
||||
Shell_NotifyIcon(NIM_ADD, &nidApp);
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_USER_SHELLICON:
|
||||
// systray msg callback
|
||||
POINT lpClickPoint;
|
||||
switch (LOWORD(lParam))
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
OpenUI();
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
UINT uFlag = MF_BYPOSITION | MF_STRING;
|
||||
GetCursorPos(&lpClickPoint);
|
||||
HMENU hPopMenu = CreatePopupMenu();
|
||||
InsertMenu(hPopMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, IDM_EXIT, _T("Open"));
|
||||
InsertMenu(hPopMenu, 0xFFFFFFFF, MF_SEPARATOR | MF_BYPOSITION, 0, nullptr);
|
||||
InsertMenu(hPopMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, IDM_EXIT, _T("Exit"));
|
||||
|
||||
SetForegroundWindow(hWnd);
|
||||
TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, lpClickPoint.x, lpClickPoint.y, 0, hWnd, NULL);
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
int wmId = LOWORD(wParam);
|
||||
// Parse the menu selections:
|
||||
switch (wmId)
|
||||
{
|
||||
case IDM_EXIT:
|
||||
DestroyWindow(hWnd);
|
||||
break;
|
||||
case IDM_OPEN:
|
||||
OpenUI();
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
Shell_NotifyIcon(NIM_DELETE, &nidApp);
|
||||
KillParity();
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
case WM_TIMER:
|
||||
if (!ParityIsRunning())
|
||||
DestroyWindow(hWnd);
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KillParity()
|
||||
{
|
||||
DWORD procId = parityProcId;
|
||||
//This does not require the console window to be visible.
|
||||
if (AttachConsole(procId))
|
||||
{
|
||||
// Disable Ctrl-C handling for our program
|
||||
SetConsoleCtrlHandler(nullptr, true);
|
||||
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
|
||||
FreeConsole();
|
||||
|
||||
//Re-enable Ctrl-C handling or any subsequently started
|
||||
//programs will inherit the disabled state.
|
||||
SetConsoleCtrlHandler(nullptr, false);
|
||||
}
|
||||
WaitForSingleObject(parityHandle, INFINITE);
|
||||
}
|
||||
|
||||
bool ParityIsRunning()
|
||||
{
|
||||
return WaitForSingleObject(parityHandle, 0) == WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
void OpenUI()
|
||||
{
|
||||
// Launch parity
|
||||
TCHAR path[MAX_PATH] = { 0 };
|
||||
if (!GetParityExePath(path, MAX_PATH))
|
||||
return;
|
||||
|
||||
PROCESS_INFORMATION procInfo = { 0 };
|
||||
STARTUPINFO startupInfo = { sizeof(STARTUPINFO) };
|
||||
|
||||
LPWSTR cmd = _T("parity.exe ui");
|
||||
CreateProcess(path, cmd, nullptr, nullptr, false, CREATE_NO_WINDOW, nullptr, nullptr, &startupInfo, &procInfo);
|
||||
}
|
BIN
windows/ptray/ptray.ico
Normal file
BIN
windows/ptray/ptray.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
BIN
windows/ptray/ptray.rc
Normal file
BIN
windows/ptray/ptray.rc
Normal file
Binary file not shown.
155
windows/ptray/ptray.vcxproj
Normal file
155
windows/ptray/ptray.vcxproj
Normal file
@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{37C89E90-8C9E-4FFC-AAE7-B3695D5EB6F4}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>ptray</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ptray.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="ptray.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="ptray.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
BIN
windows/ptray/resource.h
Normal file
BIN
windows/ptray/resource.h
Normal file
Binary file not shown.
8
windows/ptray/targetver.h
Normal file
8
windows/ptray/targetver.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
Loading…
Reference in New Issue
Block a user