From d8a4000141295a2e41fb51a133ddcc9962e10856 Mon Sep 17 00:00:00 2001 From: vadym Date: Thu, 27 Oct 2022 22:03:37 +0300 Subject: [PATCH] 1. added multipath protocol and schema suport 2. added SCTP protocol and schema support 3. added set of NAS models support (Asustor, ReadyNAS, Drobo, QNAP, WD, Synology, Terramaster) 4. moved to fc00::/7 private segment 5. added Windows, MacOS and Linux UI for peers edit and current status --- CHANGELOG.md | 8 +- LICENSE.rtf | 189 +++++ README.md | 88 ++- SECURITY.md | 21 + appveyor.yml | 31 + build | 13 +- cmd/genkeys/main.go | 2 +- cmd/{yggdrasil => mesh}/main.go | 43 +- cmd/{yggdrasilctl => meshctl}/cmd_line_env.go | 2 +- cmd/{yggdrasilctl => meshctl}/main.go | 19 +- contrib/ansible/genkeys.go | 10 +- .../{usr.bin.yggdrasil => usr.bin.mesh} | 6 +- .../busybox-init/{S42yggdrasil => S42mesh} | 16 +- contrib/deb/generate-gui.sh | 165 +++++ contrib/deb/generate.sh | 110 +-- contrib/docker/Dockerfile | 12 +- contrib/docker/entrypoint.sh | 6 +- contrib/freebsd/mesh | 72 ++ contrib/freebsd/yggdrasil | 72 -- contrib/macos/create-pkg-gui.sh | 176 +++++ contrib/macos/create-pkg.sh | 64 +- contrib/macos/mesh.plist | 26 + .../LICENSE | 0 contrib/mesh-brute-simple/Makefile | 12 + .../README.md | 2 +- .../mesh-brute-multi-curve25519.c} | 6 +- .../mesh-brute-multi-ed25519.c} | 6 +- .../mesh-brute.h} | 0 .../util.c | 4 +- contrib/mobile/build | 6 +- contrib/mobile/mobile.go | 58 +- contrib/mobile/mobile_test.go | 14 +- contrib/msi/build-msi-gui.sh | 313 ++++++++ contrib/msi/build-msi.sh | 86 ++- contrib/msi/msversion.sh | 28 +- contrib/nas/nas-asustor.sh | 108 +++ contrib/nas/nas-drobo.sh | 90 +++ contrib/nas/nas-netgear-os6.sh | 108 +++ contrib/nas/nas-qnap.sh | 84 +++ contrib/nas/nas-synology-dsm6.0.sh | 92 +++ contrib/nas/nas-synology-dsm7.0.sh | 95 +++ contrib/nas/nas-terramaster.sh | 91 +++ contrib/nas/nas-westerndigital-os3.sh | 92 +++ contrib/nas/nas-westerndigital-os5.sh | 92 +++ contrib/nas/tool/asustor_apkg_tools.py | 574 +++++++++++++++ contrib/nas/tool/synology_pkg_util.sh | 436 ++++++++++++ contrib/nas/tool/synology_version.sh | 33 + contrib/openrc/{yggdrasil => mesh} | 8 +- contrib/semver/name.sh | 7 +- contrib/systemd/mesh-debug.service | 21 + contrib/systemd/mesh-default-config.service | 13 + contrib/systemd/mesh.service | 21 + .../systemd/yggdrasil-default-config.service | 13 - contrib/systemd/yggdrasil.service | 21 - .../ui/mesh-ui/dll/arm64/WebView2Loader.dll | Bin 0 -> 391056 bytes contrib/ui/mesh-ui/dll/x64/WebView2Loader.dll | Bin 0 -> 427928 bytes contrib/ui/mesh-ui/dll/x64/webview.dll | Bin 0 -> 857600 bytes contrib/ui/mesh-ui/dll/x86/WebView2Loader.dll | Bin 0 -> 326552 bytes contrib/ui/mesh-ui/dll/x86/webview.dll | Bin 0 -> 683008 bytes contrib/ui/mesh-ui/index.html | 669 ++++++++++++++++++ contrib/ui/mesh-ui/webview.go | 266 +++++++ .../ui/nas-asustor/CONTROL/description.txt | 4 + contrib/ui/nas-asustor/CONTROL/start-stop.sh | 87 +++ .../ui/nas-asustor/var/lib/mesh/deviceinfo | 6 + contrib/ui/nas-asustor/var/lib/mesh/webauth | 76 ++ .../nas-asustor/www/assets/partner-logo.png | Bin 0 -> 16205 bytes .../ui/nas-asustor/www/assets/properties.js | 35 + contrib/ui/nas-drobo/Content/install.sh | 4 + contrib/ui/nas-drobo/Content/mesh.conf | 20 + contrib/ui/nas-drobo/Content/scripts.sh | 40 ++ contrib/ui/nas-drobo/Content/service.sh | 121 ++++ contrib/ui/nas-drobo/Content/uninstall.sh | 4 + contrib/ui/nas-drobo/Content/update.sh | 3 + .../Content/var/lib/mesh/hooks/deviceinfo | 16 + .../Content/www/assets/partner-logo.png | Bin 0 -> 5568 bytes .../nas-drobo/Content/www/assets/partner.css | 25 + .../Content/www/assets/properties.js | 9 + .../ui/nas-netgear-os6/package/DEBIAN/control | 11 + .../nas-netgear-os6/package/DEBIAN/postinst | 61 ++ .../ui/nas-netgear-os6/package/DEBIAN/postrm | 32 + .../ui/nas-netgear-os6/package/DEBIAN/prerm | 32 + .../package/apps/mesh/fvapp-mesh.service | 19 + .../package/apps/mesh/https.conf | 12 + .../apps/mesh/var/lib/mesh/hooks/deviceinfo | 10 + .../apps/mesh/www/assets/partner-logo.png | Bin 0 -> 6708 bytes .../package/apps/mesh/www/assets/partner.css | 9 + .../apps/mesh/www/assets/properties.js | 10 + contrib/ui/nas-qnap/au/apache-mesh.conf | 8 + .../nas-qnap/au/var/lib/mesh/hooks/deviceinfo | 7 + .../ui/nas-qnap/au/var/lib/mesh/hooks/webauth | 31 + .../nas-qnap/au/var/lib/mesh/pre_upgrade.sh | 12 + contrib/ui/nas-qnap/au/www/assets/get_sid.js | 102 +++ .../nas-qnap/au/www/assets/partner-logo.png | Bin 0 -> 16278 bytes .../ui/nas-qnap/au/www/assets/properties.js | 104 +++ contrib/ui/nas-qnap/package/package_routines | 42 ++ contrib/ui/nas-qnap/package/shared/mesh.sh | 120 ++++ .../nas-synology-dsm6.0/package/dsm.mesh.conf | 14 + .../ui/nas-synology-dsm6.0/package/mesh.sc | 5 + .../ui/nas-synology-dsm6.0/package/ui/config | 11 + .../nas-synology-dsm6.0/package/ui/login.html | 18 + .../package/var/lib/mesh/hooks/deviceinfo | 7 + .../package/var/lib/mesh/hooks/webauth | 22 + .../package/var/lib/mesh/pre_upgrade.sh | 10 + .../package/www/assets/partner-logo.png | Bin 0 -> 5134 bytes .../package/www/assets/properties.js | 81 +++ .../ui/nas-synology-dsm6.0/spk/conf/resource | 5 + .../nas-synology-dsm6.0/spk/scripts/postinst | 17 + .../spk/scripts/postuninst | 8 + .../spk/scripts/postupgrade | 3 + .../nas-synology-dsm6.0/spk/scripts/preinst | 3 + .../nas-synology-dsm6.0/spk/scripts/preuninst | 3 + .../spk/scripts/preupgrade | 3 + .../spk/scripts/start-stop-status | 120 ++++ .../nas-synology-dsm7.0/package/ui/login.html | 15 + .../ui/nas-synology-dsm7.0/spk/conf/privilege | 21 + .../spk/scripts/start-stop-status | 120 ++++ contrib/ui/nas-terramaster/mesh/config.ini | 10 + .../ui/nas-terramaster/mesh/etc/init.d/mesh | 74 ++ .../mesh/etc/nginx/conf.d/mesh.conf | 4 + contrib/ui/nas-terramaster/mesh/mesh.lang | 11 + contrib/ui/nas-terramaster/mesh/remove_list | 1 + .../local/mesh/var/lib/mesh/hooks/deviceinfo | 6 + .../local/mesh/www/assets/partner-logo.png | Bin 0 -> 313 bytes .../usr/local/mesh/www/assets/properties.js | 11 + .../mesh/usr/www/css/style-mesh.css | 17 + .../mesh/usr/www/include/class/mesh.class.php | 33 + .../mesh/usr/www/lang/ext/mesh.lang | 11 + .../usr/www/mod/4.Application/21.mesh.php | 93 +++ .../package/mesh/apache-mesh.conf | 8 + .../nas-westerndigital/package/mesh/clean.sh | 11 + .../nas-westerndigital/package/mesh/init.sh | 34 + .../package/mesh/install.sh | 20 + .../package/mesh/preinst.sh | 11 + .../nas-westerndigital/package/mesh/remove.sh | 10 + .../nas-westerndigital/package/mesh/start.sh | 24 + .../nas-westerndigital/package/mesh/stop.sh | 47 ++ .../package/mesh/ui/desc.xml | 7 + .../mesh/var/lib/mesh/hooks/deviceinfo | 7 + .../package/mesh/var/lib/pre_upgrade.sh | 10 + .../package/mesh/www/assets/partner-logo.png | Bin 0 -> 2799 bytes .../package/mesh/www/assets/partner.css | 9 + .../package/mesh/www/assets/properties.js | 9 + contrib/ui/www/assets/ajax-loader.gif | Bin 0 -> 10819 bytes contrib/ui/www/assets/edrive.css | 160 +++++ contrib/ui/www/assets/edrive.js | 416 +++++++++++ contrib/ui/www/assets/favicon.png | Bin 0 -> 2849 bytes contrib/ui/www/assets/jquery.min.js | 5 + contrib/ui/www/assets/logo.png | Bin 0 -> 6800 bytes contrib/ui/www/index.html | 214 ++++++ contrib/yggdrasil-brute-simple/Makefile | 12 - go.mod | 21 +- go.sum | 80 +++ misc/run-schannel-netns | 12 +- misc/run-twolink-test | 4 +- riv.icns | Bin 0 -> 362765 bytes riv.ico | Bin 0 -> 270398 bytes riv.png | Bin 0 -> 130197 bytes riv.svg | 4 + src/address/address.go | 10 +- src/address/address_test.go | 16 +- src/admin/addpeers.go | 30 + src/admin/admin.go | 77 +- src/admin/getdht.go | 2 +- src/admin/getpaths.go | 2 +- src/admin/getpeers.go | 2 +- src/admin/getself.go | 2 +- src/admin/getsessions.go | 2 +- src/config/config.go | 22 +- src/core/api.go | 61 +- src/core/core.go | 10 +- src/core/link.go | 205 ++---- src/core/link_linux.go | 159 +++++ src/core/link_mpath.go | 282 ++++++++ src/core/link_mpath_android.go | 270 +++++++ src/core/link_mpath_darwin.go | 33 + src/core/link_mpath_linux.go | 46 ++ src/core/link_mpath_other.go | 18 + src/core/link_other.go | 147 ++++ src/core/link_sctp_linux.go | 176 +++++ src/core/link_tcp.go | 1 + src/core/nodeinfo.go | 5 +- src/core/proto.go | 2 +- src/core/version.go | 2 +- src/defaults/defaults.go | 4 +- src/defaults/defaults_darwin.go | 6 +- src/defaults/defaults_freebsd.go | 6 +- src/defaults/defaults_linux.go | 6 +- src/defaults/defaults_openbsd.go | 6 +- src/defaults/defaults_other.go | 4 +- src/defaults/defaults_windows.go | 6 +- src/ipv6rwc/ipv6rwc.go | 4 +- src/multicast/admin.go | 2 +- src/multicast/multicast.go | 15 +- src/multicast/multicast_darwin.go | 1 + src/multicast/multicast_unix.go | 22 +- src/tun/admin.go | 2 +- src/tun/tun.go | 16 +- src/tun/tun_windows.go | 20 +- 198 files changed, 8589 insertions(+), 697 deletions(-) create mode 100644 LICENSE.rtf create mode 100644 SECURITY.md create mode 100644 appveyor.yml rename cmd/{yggdrasil => mesh}/main.go (91%) rename cmd/{yggdrasilctl => meshctl}/cmd_line_env.go (98%) rename cmd/{yggdrasilctl => meshctl}/main.go (93%) rename contrib/apparmor/{usr.bin.yggdrasil => usr.bin.mesh} (80%) rename contrib/busybox-init/{S42yggdrasil => S42mesh} (68%) create mode 100755 contrib/deb/generate-gui.sh create mode 100644 contrib/freebsd/mesh delete mode 100644 contrib/freebsd/yggdrasil create mode 100644 contrib/macos/create-pkg-gui.sh create mode 100644 contrib/macos/mesh.plist rename contrib/{yggdrasil-brute-simple => mesh-brute-simple}/LICENSE (100%) create mode 100644 contrib/mesh-brute-simple/Makefile rename contrib/{yggdrasil-brute-simple => mesh-brute-simple}/README.md (93%) rename contrib/{yggdrasil-brute-simple/yggdrasil-brute-multi-curve25519.c => mesh-brute-simple/mesh-brute-multi-curve25519.c} (90%) rename contrib/{yggdrasil-brute-simple/yggdrasil-brute-multi-ed25519.c => mesh-brute-simple/mesh-brute-multi-ed25519.c} (91%) rename contrib/{yggdrasil-brute-simple/yggdrasil-brute.h => mesh-brute-simple/mesh-brute.h} (100%) rename contrib/{yggdrasil-brute-simple => mesh-brute-simple}/util.c (94%) create mode 100644 contrib/msi/build-msi-gui.sh create mode 100644 contrib/nas/nas-asustor.sh create mode 100644 contrib/nas/nas-drobo.sh create mode 100644 contrib/nas/nas-netgear-os6.sh create mode 100644 contrib/nas/nas-qnap.sh create mode 100644 contrib/nas/nas-synology-dsm6.0.sh create mode 100644 contrib/nas/nas-synology-dsm7.0.sh create mode 100644 contrib/nas/nas-terramaster.sh create mode 100644 contrib/nas/nas-westerndigital-os3.sh create mode 100644 contrib/nas/nas-westerndigital-os5.sh create mode 100755 contrib/nas/tool/asustor_apkg_tools.py create mode 100755 contrib/nas/tool/synology_pkg_util.sh create mode 100644 contrib/nas/tool/synology_version.sh rename contrib/openrc/{yggdrasil => mesh} (87%) create mode 100644 contrib/systemd/mesh-debug.service create mode 100644 contrib/systemd/mesh-default-config.service create mode 100644 contrib/systemd/mesh.service delete mode 100644 contrib/systemd/yggdrasil-default-config.service delete mode 100644 contrib/systemd/yggdrasil.service create mode 100644 contrib/ui/mesh-ui/dll/arm64/WebView2Loader.dll create mode 100644 contrib/ui/mesh-ui/dll/x64/WebView2Loader.dll create mode 100755 contrib/ui/mesh-ui/dll/x64/webview.dll create mode 100644 contrib/ui/mesh-ui/dll/x86/WebView2Loader.dll create mode 100755 contrib/ui/mesh-ui/dll/x86/webview.dll create mode 100755 contrib/ui/mesh-ui/index.html create mode 100755 contrib/ui/mesh-ui/webview.go create mode 100644 contrib/ui/nas-asustor/CONTROL/description.txt create mode 100644 contrib/ui/nas-asustor/CONTROL/start-stop.sh create mode 100644 contrib/ui/nas-asustor/var/lib/mesh/deviceinfo create mode 100644 contrib/ui/nas-asustor/var/lib/mesh/webauth create mode 100644 contrib/ui/nas-asustor/www/assets/partner-logo.png create mode 100644 contrib/ui/nas-asustor/www/assets/properties.js create mode 100644 contrib/ui/nas-drobo/Content/install.sh create mode 100644 contrib/ui/nas-drobo/Content/mesh.conf create mode 100644 contrib/ui/nas-drobo/Content/scripts.sh create mode 100644 contrib/ui/nas-drobo/Content/service.sh create mode 100644 contrib/ui/nas-drobo/Content/uninstall.sh create mode 100644 contrib/ui/nas-drobo/Content/update.sh create mode 100644 contrib/ui/nas-drobo/Content/var/lib/mesh/hooks/deviceinfo create mode 100644 contrib/ui/nas-drobo/Content/www/assets/partner-logo.png create mode 100644 contrib/ui/nas-drobo/Content/www/assets/partner.css create mode 100644 contrib/ui/nas-drobo/Content/www/assets/properties.js create mode 100644 contrib/ui/nas-netgear-os6/package/DEBIAN/control create mode 100755 contrib/ui/nas-netgear-os6/package/DEBIAN/postinst create mode 100755 contrib/ui/nas-netgear-os6/package/DEBIAN/postrm create mode 100755 contrib/ui/nas-netgear-os6/package/DEBIAN/prerm create mode 100755 contrib/ui/nas-netgear-os6/package/apps/mesh/fvapp-mesh.service create mode 100755 contrib/ui/nas-netgear-os6/package/apps/mesh/https.conf create mode 100755 contrib/ui/nas-netgear-os6/package/apps/mesh/var/lib/mesh/hooks/deviceinfo create mode 100755 contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/partner-logo.png create mode 100755 contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/partner.css create mode 100755 contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/properties.js create mode 100644 contrib/ui/nas-qnap/au/apache-mesh.conf create mode 100644 contrib/ui/nas-qnap/au/var/lib/mesh/hooks/deviceinfo create mode 100644 contrib/ui/nas-qnap/au/var/lib/mesh/hooks/webauth create mode 100644 contrib/ui/nas-qnap/au/var/lib/mesh/pre_upgrade.sh create mode 100644 contrib/ui/nas-qnap/au/www/assets/get_sid.js create mode 100644 contrib/ui/nas-qnap/au/www/assets/partner-logo.png create mode 100644 contrib/ui/nas-qnap/au/www/assets/properties.js create mode 100644 contrib/ui/nas-qnap/package/package_routines create mode 100644 contrib/ui/nas-qnap/package/shared/mesh.sh create mode 100644 contrib/ui/nas-synology-dsm6.0/package/dsm.mesh.conf create mode 100644 contrib/ui/nas-synology-dsm6.0/package/mesh.sc create mode 100644 contrib/ui/nas-synology-dsm6.0/package/ui/config create mode 100644 contrib/ui/nas-synology-dsm6.0/package/ui/login.html create mode 100644 contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/hooks/deviceinfo create mode 100644 contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/hooks/webauth create mode 100644 contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/pre_upgrade.sh create mode 100644 contrib/ui/nas-synology-dsm6.0/package/www/assets/partner-logo.png create mode 100644 contrib/ui/nas-synology-dsm6.0/package/www/assets/properties.js create mode 100644 contrib/ui/nas-synology-dsm6.0/spk/conf/resource create mode 100644 contrib/ui/nas-synology-dsm6.0/spk/scripts/postinst create mode 100644 contrib/ui/nas-synology-dsm6.0/spk/scripts/postuninst create mode 100644 contrib/ui/nas-synology-dsm6.0/spk/scripts/postupgrade create mode 100644 contrib/ui/nas-synology-dsm6.0/spk/scripts/preinst create mode 100644 contrib/ui/nas-synology-dsm6.0/spk/scripts/preuninst create mode 100644 contrib/ui/nas-synology-dsm6.0/spk/scripts/preupgrade create mode 100644 contrib/ui/nas-synology-dsm6.0/spk/scripts/start-stop-status create mode 100644 contrib/ui/nas-synology-dsm7.0/package/ui/login.html create mode 100644 contrib/ui/nas-synology-dsm7.0/spk/conf/privilege create mode 100644 contrib/ui/nas-synology-dsm7.0/spk/scripts/start-stop-status create mode 100644 contrib/ui/nas-terramaster/mesh/config.ini create mode 100755 contrib/ui/nas-terramaster/mesh/etc/init.d/mesh create mode 100644 contrib/ui/nas-terramaster/mesh/etc/nginx/conf.d/mesh.conf create mode 100644 contrib/ui/nas-terramaster/mesh/mesh.lang create mode 100644 contrib/ui/nas-terramaster/mesh/remove_list create mode 100644 contrib/ui/nas-terramaster/mesh/usr/local/mesh/var/lib/mesh/hooks/deviceinfo create mode 100644 contrib/ui/nas-terramaster/mesh/usr/local/mesh/www/assets/partner-logo.png create mode 100644 contrib/ui/nas-terramaster/mesh/usr/local/mesh/www/assets/properties.js create mode 100644 contrib/ui/nas-terramaster/mesh/usr/www/css/style-mesh.css create mode 100644 contrib/ui/nas-terramaster/mesh/usr/www/include/class/mesh.class.php create mode 100644 contrib/ui/nas-terramaster/mesh/usr/www/lang/ext/mesh.lang create mode 100644 contrib/ui/nas-terramaster/mesh/usr/www/mod/4.Application/21.mesh.php create mode 100644 contrib/ui/nas-westerndigital/package/mesh/apache-mesh.conf create mode 100755 contrib/ui/nas-westerndigital/package/mesh/clean.sh create mode 100755 contrib/ui/nas-westerndigital/package/mesh/init.sh create mode 100755 contrib/ui/nas-westerndigital/package/mesh/install.sh create mode 100755 contrib/ui/nas-westerndigital/package/mesh/preinst.sh create mode 100755 contrib/ui/nas-westerndigital/package/mesh/remove.sh create mode 100755 contrib/ui/nas-westerndigital/package/mesh/start.sh create mode 100755 contrib/ui/nas-westerndigital/package/mesh/stop.sh create mode 100644 contrib/ui/nas-westerndigital/package/mesh/ui/desc.xml create mode 100644 contrib/ui/nas-westerndigital/package/mesh/var/lib/mesh/hooks/deviceinfo create mode 100644 contrib/ui/nas-westerndigital/package/mesh/var/lib/pre_upgrade.sh create mode 100644 contrib/ui/nas-westerndigital/package/mesh/www/assets/partner-logo.png create mode 100755 contrib/ui/nas-westerndigital/package/mesh/www/assets/partner.css create mode 100644 contrib/ui/nas-westerndigital/package/mesh/www/assets/properties.js create mode 100644 contrib/ui/www/assets/ajax-loader.gif create mode 100644 contrib/ui/www/assets/edrive.css create mode 100644 contrib/ui/www/assets/edrive.js create mode 100644 contrib/ui/www/assets/favicon.png create mode 100644 contrib/ui/www/assets/jquery.min.js create mode 100644 contrib/ui/www/assets/logo.png create mode 100644 contrib/ui/www/index.html delete mode 100644 contrib/yggdrasil-brute-simple/Makefile create mode 100755 riv.icns create mode 100644 riv.ico create mode 100644 riv.png create mode 100644 riv.svg create mode 100644 src/admin/addpeers.go create mode 100644 src/core/link_linux.go create mode 100644 src/core/link_mpath.go create mode 100644 src/core/link_mpath_android.go create mode 100644 src/core/link_mpath_darwin.go create mode 100644 src/core/link_mpath_linux.go create mode 100644 src/core/link_mpath_other.go create mode 100644 src/core/link_other.go create mode 100644 src/core/link_sctp_linux.go diff --git a/CHANGELOG.md b/CHANGELOG.md index af827b21..adc6335e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,13 +57,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - It is now possible to `addPeer` and `removePeer` using the admin socket again - The `getSessions` admin socket call reports number of bytes received and transmitted again - The link setup code has been refactored, making it easier to support new peering types in the future -- Yggdrasil now maintains configuration internally, rather than relying on a shared and potentially mutable structure +- RiV-mesh now maintains configuration internally, rather than relying on a shared and potentially mutable structure ### Fixed - Tracking information about expired root nodes has been fixed, which should hopefully resolve issues with reparenting and connection failures when the root node disappears - A bug in the mobile framework code which caused a crash on Android when multicast failed to set up has been fixed -- Yggdrasil should now shut down gracefully and clean up correctly when running as a Windows service +- RiV-mesh should now shut down gracefully and clean up correctly when running as a Windows service ## [0.4.4] - 2022-07-07 @@ -71,11 +71,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - ICMPv6 "Packet Too Big" payload size has been increased, which should fix Path MTU Discovery (PMTUD) when two nodes have different `IfMTU` values configured - A crash has been fixed when handling debug packet responses -- `yggdrasilctl getSelf` should now report coordinates correctly again +- `meshctl getSelf` should now report coordinates correctly again ### Changed -- Go 1.17 is now required to build Yggdrasil +- Go 1.17 is now required to build RiV-mesh ## [0.4.3] - 2022-02-06 diff --git a/LICENSE.rtf b/LICENSE.rtf new file mode 100644 index 00000000..c5ad8d48 --- /dev/null +++ b/LICENSE.rtf @@ -0,0 +1,189 @@ +{\rtf1\ansi\ansicpg1251\deff0\nouicompat\deflang1049{\fonttbl{\f0\fnil\fcharset0 Roboto;}} +{\colortbl ;\red0\green0\blue255;} +{\*\generator Riched20 10.0.19041}\viewkind4\uc1 +\pard\sl240\slmult1\f0\fs16\lang9 This software is licensed under the LGPLv3, included below.\par +\par +As a special exception to the GNU Lesser General Public License version 3\par +("LGPL3"), the copyright holders of this Library give you permission to\par +convey to a third party a Combined Work that links statically or dynamically\par +to this Library without providing any Minimal Corresponding Source or\par +Minimal Application Code as set out in 4d or providing the installation\par +information set out in section 4e, provided that you comply with the other\par +provisions of LGPL3 and provided that you meet, for the Application the\par +terms and conditions of the license(s) which apply to the Application.\par +\par +Except as stated in this special exception, the provisions of LGPL3 will\par +continue to comply in full to this Library. If you modify this Library, you\par +may apply this exception to your version of this Library, but you are not\par +obliged to do so. If you do not wish to do so, delete this exception\par +statement from your version. This exception does not (and cannot) modify any\par +license terms which apply to the Application, with which you must still\par +comply.\par +\par + GNU LESSER GENERAL PUBLIC LICENSE\par + Version 3, 29 June 2007\par +\par + Copyright (C) 2007 Free Software Foundation, Inc. <{{\field{\*\fldinst{HYPERLINK "https://fsf.org/"}}{\fldrslt{https://fsf.org/\ul0\cf0}}}}\f0\fs16 >\par + Everyone is permitted to copy and distribute verbatim copies\par + of this license document, but changing it is not allowed.\par +\par +\par + This version of the GNU Lesser General Public License incorporates\par +the terms and conditions of version 3 of the GNU General Public\par +License, supplemented by the additional permissions listed below.\par +\par + 0. Additional Definitions.\par +\par + As used herein, "this License" refers to version 3 of the GNU Lesser\par +General Public License, and the "GNU GPL" refers to version 3 of the GNU\par +General Public License.\par +\par + "The Library" refers to a covered work governed by this License,\par +other than an Application or a Combined Work as defined below.\par +\par + An "Application" is any work that makes use of an interface provided\par +by the Library, but which is not otherwise based on the Library.\par +Defining a subclass of a class defined by the Library is deemed a mode\par +of using an interface provided by the Library.\par +\par + A "Combined Work" is a work produced by combining or linking an\par +Application with the Library. The particular version of the Library\par +with which the Combined Work was made is also called the "Linked\par +Version".\par +\par + The "Minimal Corresponding Source" for a Combined Work means the\par +Corresponding Source for the Combined Work, excluding any source code\par +for portions of the Combined Work that, considered in isolation, are\par +based on the Application, and not on the Linked Version.\par +\par + The "Corresponding Application Code" for a Combined Work means the\par +object code and/or source code for the Application, including any data\par +and utility programs needed for reproducing the Combined Work from the\par +Application, but excluding the System Libraries of the Combined Work.\par +\par + 1. Exception to Section 3 of the GNU GPL.\par +\par + You may convey a covered work under sections 3 and 4 of this License\par +without being bound by section 3 of the GNU GPL.\par +\par + 2. Conveying Modified Versions.\par +\par + If you modify a copy of the Library, and, in your modifications, a\par +facility refers to a function or data to be supplied by an Application\par +that uses the facility (other than as an argument passed when the\par +facility is invoked), then you may convey a copy of the modified\par +version:\par +\par + a) under this License, provided that you make a good faith effort to\par + ensure that, in the event an Application does not supply the\par + function or data, the facility still operates, and performs\par + whatever part of its purpose remains meaningful, or\par +\par + b) under the GNU GPL, with none of the additional permissions of\par + this License applicable to that copy.\par +\par + 3. Object Code Incorporating Material from Library Header Files.\par +\par + The object code form of an Application may incorporate material from\par +a header file that is part of the Library. You may convey such object\par +code under terms of your choice, provided that, if the incorporated\par +material is not limited to numerical parameters, data structure\par +layouts and accessors, or small macros, inline functions and templates\par +(ten or fewer lines in length), you do both of the following:\par +\par + a) Give prominent notice with each copy of the object code that the\par + Library is used in it and that the Library and its use are\par + covered by this License.\par +\par + b) Accompany the object code with a copy of the GNU GPL and this license\par + document.\par +\par + 4. Combined Works.\par +\par + You may convey a Combined Work under terms of your choice that,\par +taken together, effectively do not restrict modification of the\par +portions of the Library contained in the Combined Work and reverse\par +engineering for debugging such modifications, if you also do each of\par +the following:\par +\par + a) Give prominent notice with each copy of the Combined Work that\par + the Library is used in it and that the Library and its use are\par + covered by this License.\par +\par + b) Accompany the Combined Work with a copy of the GNU GPL and this license\par + document.\par +\par + c) For a Combined Work that displays copyright notices during\par + execution, include the copyright notice for the Library among\par + these notices, as well as a reference directing the user to the\par + copies of the GNU GPL and this license document.\par +\par + d) Do one of the following:\par +\par + 0) Convey the Minimal Corresponding Source under the terms of this\par + License, and the Corresponding Application Code in a form\par + suitable for, and under terms that permit, the user to\par + recombine or relink the Application with a modified version of\par + the Linked Version to produce a modified Combined Work, in the\par + manner specified by section 6 of the GNU GPL for conveying\par + Corresponding Source.\par +\par + 1) Use a suitable shared library mechanism for linking with the\par + Library. A suitable mechanism is one that (a) uses at run time\par + a copy of the Library already present on the user's computer\par + system, and (b) will operate properly with a modified version\par + of the Library that is interface-compatible with the Linked\par + Version.\par +\par + e) Provide Installation Information, but only if you would otherwise\par + be required to provide such information under section 6 of the\par + GNU GPL, and only to the extent that such information is\par + necessary to install and execute a modified version of the\par + Combined Work produced by recombining or relinking the\par + Application with a modified version of the Linked Version. (If\par + you use option 4d0, the Installation Information must accompany\par + the Minimal Corresponding Source and Corresponding Application\par + Code. If you use option 4d1, you must provide the Installation\par + Information in the manner specified by section 6 of the GNU GPL\par + for conveying Corresponding Source.)\par +\par + 5. Combined Libraries.\par +\par + You may place library facilities that are a work based on the\par +Library side by side in a single library together with other library\par +facilities that are not Applications and are not covered by this\par +License, and convey such a combined library under terms of your\par +choice, if you do both of the following:\par +\par + a) Accompany the combined library with a copy of the same work based\par + on the Library, uncombined with any other library facilities,\par + conveyed under the terms of this License.\par +\par + b) Give prominent notice with the combined library that part of it\par + is a work based on the Library, and explaining where to find the\par + accompanying uncombined form of the same work.\par +\par + 6. Revised Versions of the GNU Lesser General Public License.\par +\par + The Free Software Foundation may publish revised and/or new versions\par +of the GNU Lesser General Public License from time to time. Such new\par +versions will be similar in spirit to the present version, but may\par +differ in detail to address new problems or concerns.\par +\par + Each version is given a distinguishing version number. If the\par +Library as you received it specifies that a certain numbered version\par +of the GNU Lesser General Public License "or any later version"\par +applies to it, you have the option of following the terms and\par +conditions either of that published version or of any later version\par +published by the Free Software Foundation. If the Library as you\par +received it does not specify a version number of the GNU Lesser\par +General Public License, you may choose any version of the GNU Lesser\par +General Public License ever published by the Free Software Foundation.\par +\par + If the Library as you received it specifies that a proxy can decide\par +whether future versions of the GNU Lesser General Public License shall\par +apply, that proxy's public statement of acceptance of any version is\par +permanent authorization for you to choose that version for the\par +Library.\par +} + \ No newline at end of file diff --git a/README.md b/README.md index d0afae47..79e13e06 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,28 @@ -# Yggdrasil +# RiV-mesh first self arranging mesh network with link aggregation. -[![Build status](https://github.com/yggdrasil-network/yggdrasil-go/actions/workflows/ci.yml/badge.svg)](https://github.com/yggdrasil-network/yggdrasil-go/actions/workflows/ci.yml) +[![CircleCI](https://circleci.com/gh/RiV-chain/RiV-mesh.svg?style=shield&circle-token=:circle-token +)](https://circleci.com/gh/RiV-chain/RiV-mesh) + +## Why fork? +RiV-mesh is fork of Yggdrasil which is great project. Starting from Yggdrasil 0.4 dev team removed CKR feature which is a core for secure tunneling like VPN does. RiV-mesh gets back CKR feature. Second reason: Yggdrasil uses deprecated 200::/7 IPv6 address pool which can be assigned for some network in future, unlike this fc00::/7 is safe and has been taken for RiV-mesh. ## Introduction -Yggdrasil is an early-stage implementation of a fully end-to-end encrypted IPv6 -network. It is lightweight, self-arranging, supported on multiple platforms and -allows pretty much any IPv6-capable application to communicate securely with -other Yggdrasil nodes. Yggdrasil does not require you to have IPv6 Internet -connectivity - it also works over IPv4. +RiV-mesh is an implementation of a fully end-to-end encrypted IPv6 +network, created in the scope to produce the Transport Layer for RiV Chain Blockchain, +also to facilitate secure conectivity between a wide spectrum of endpoint devices like IoT devices, +desktop computers or even routers. +It is lightweight, self-arranging, supported on multiple +platforms and allows pretty much any IPv6-capable application +to communicate securely with other RiV-mesh nodes. +RiV-mesh does not require you to have IPv6 Internet connectivity - it also works over IPv4. ## Supported Platforms -Yggdrasil works on a number of platforms, including Linux, macOS, Ubiquiti +RiV-mesh works on a number of platforms, including Linux, macOS, Ubiquiti EdgeRouter, VyOS, Windows, FreeBSD, OpenBSD and OpenWrt. -Please see our [Installation](https://yggdrasil-network.github.io/installation.html) +Please see our [Installation](https://RiV-chain.github.io/installation.html) page for more information. You may also find other platform-specific wrappers, scripts or tools in the `contrib` folder. @@ -40,52 +47,85 @@ To generate static configuration, either generate a HJSON file (human-friendly, complete with comments): ``` -./yggdrasil -genconf > /path/to/yggdrasil.conf +./mesh -genconf > /path/to/mesh.conf ``` ... or generate a plain JSON file (which is easy to manipulate programmatically): ``` -./yggdrasil -genconf -json > /path/to/yggdrasil.conf +./mesh -genconf -json > /path/to/mesh.conf ``` -You will need to edit the `yggdrasil.conf` file to add or remove peers, modify +You will need to edit the `mesh.conf` file to add or remove peers, modify other configuration such as listen addresses or multicast addresses, etc. -### Run Yggdrasil +### Run RiV-mesh To run with the generated static configuration: ``` -./yggdrasil -useconffile /path/to/yggdrasil.conf +./mesh -useconffile /path/to/mesh.conf ``` To run in auto-configuration mode (which will use sane defaults and random keys at each startup, instead of using a static configuration file): ``` -./yggdrasil -autoconf +./mesh -autoconf ``` -You will likely need to run Yggdrasil as a privileged user or under `sudo`, +You will likely need to run RiV-mesh as a privileged user or under `sudo`, unless you have permission to create TUN/TAP adapters. On Linux this can be done -by giving the Yggdrasil binary the `CAP_NET_ADMIN` capability. +by giving the RiV-mesh binary the `CAP_NET_ADMIN` capability. ## Documentation -Documentation is available [on our website](https://yggdrasil-network.github.io). +Documentation is available [on our website](https://riv-chain.github.io/RiV-mesh/). -- [Installing Yggdrasil](https://yggdrasil-network.github.io/installation.html) -- [Configuring Yggdrasil](https://yggdrasil-network.github.io/configuration.html) -- [Frequently asked questions](https://yggdrasil-network.github.io/faq.html) +- [Installing RiV-mesh](https://riv-chain.github.io/RiV-mesh/) +- [Configuring RiV-mesh](https://riv-chain.github.io/RiV-mesh/) +- [Frequently asked questions](https://riv-chain.github.io/RiV-mesh/) - [Version changelog](CHANGELOG.md) ## Community -Feel free to join us on our [Matrix -channel](https://matrix.to/#/#yggdrasil:matrix.org) at `#yggdrasil:matrix.org` -or in the `#yggdrasil` IRC channel on [libera.chat](https://libera.chat). +Feel free to join us on our [Telegram +channel](https://t.me/rivchain). + +## Public peers +If you are operating RiV-mesh peer and may create your pool request with your new per or use existing one https://github.com/RiV-chain/public-peers + +## Known issues + +### 1. Log message: +``` +An error occurred starting multicast: listen udp6 [::]:9001: socket: address family not supported by protocol +``` +and +``` +An error occurred starting TUN/TAP: operation not supported +``` + +### Caused by: +The device has no IPv6 support + + +### 2. Log message: +``` +An error occurred starting TUN/TAP: permission denied +``` + +### Caused by: +IPv6 support is not enabled. See the solution: https://github.com/yggdrasil-network/yggdrasil-go/issues/479#issuecomment-519512395 + +### 3. Mesh infinite output in log: + Connected SCTP ... + + Disconnected SCTP ... + +### Caused by: +Docker interface docker0 is conflicting with SCTP bind process. The issue can be resolved by removing docker. ## License diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..034e8480 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,21 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 5.1.x | :white_check_mark: | +| 5.0.x | :x: | +| 4.0.x | :white_check_mark: | +| < 4.0 | :x: | + +## Reporting a Vulnerability + +Use this section to tell people how to report a vulnerability. + +Tell them where to go, how often they can expect to get an update on a +reported vulnerability, what to expect if the vulnerability is accepted or +declined, etc. diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..d5ec8dad --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,31 @@ +version: '{build}' +pull_requests: + do_not_increment_build_number: true +os: Visual Studio 2022 +shallow_clone: false + +environment: + MSYSTEM: MINGW64 + MSYS2_PATH_TYPE: inherit + CHERE_INVOKING: enabled_from_arguments + GO111MODULE: on + GOPATH: c:\gopath + +stack: go 1.19 + +build_script: +- cmd: >- + cd %APPVEYOR_BUILD_FOLDER% + ##### MinGW build +- set OPT_PATH=C:\msys64\mingw32\bin;C:\msys64\mingw64\bin; +- set PATH=%GOPATH%\bin;%OPT_PATH%%PATH% +- go install github.com/tc-hib/go-winres@latest +- c:\msys64\usr\bin\bash -lc "./contrib/msi/build-msi.sh x64" +- c:\msys64\usr\bin\bash -lc "./contrib/msi/build-msi.sh x86" +- c:\msys64\usr\bin\bash -lc "./contrib/msi/build-msi-gui.sh x64" +- c:\msys64\usr\bin\bash -lc "./contrib/msi/build-msi-gui.sh x86" + +test: off + +artifacts: +- path: '*.msi' diff --git a/build b/build index c7214438..708c431b 100755 --- a/build +++ b/build @@ -2,11 +2,14 @@ set -ef -PKGSRC=${PKGSRC:-github.com/yggdrasil-network/yggdrasil-go/src/version} +PKGSRC=${PKGSRC:-github.com/RiV-chain/RiV-mesh/src/version} PKGNAME=${PKGNAME:-$(sh contrib/semver/name.sh)} PKGVER=${PKGVER:-$(sh contrib/semver/version.sh --bare)} - -LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER" +if [ "$LDFLAGS" ]; then + LDFLAGS="$LDFLAGS -X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER" +else + LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER" +fi ARGS="-v" while getopts "utc:l:dro:p" option @@ -28,9 +31,9 @@ if [ -z $TABLES ] && [ -z $DEBUG ]; then LDFLAGS="$LDFLAGS -s -w" fi -for CMD in yggdrasil yggdrasilctl ; do +for CMD in ./cmd/mesh ./cmd/meshctl ./contrib/ui/mesh-ui ; do echo "Building: $CMD" - go build $ARGS -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" ./cmd/$CMD + go build $ARGS -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" $CMD if [ $UPX ]; then upx --brute $CMD diff --git a/cmd/genkeys/main.go b/cmd/genkeys/main.go index 81942446..30b7d604 100644 --- a/cmd/genkeys/main.go +++ b/cmd/genkeys/main.go @@ -19,7 +19,7 @@ import ( "net" "runtime" - "github.com/yggdrasil-network/yggdrasil-go/src/address" + "github.com/RiV-chain/RiV-mesh/src/address" ) type keySet struct { diff --git a/cmd/yggdrasil/main.go b/cmd/mesh/main.go similarity index 91% rename from cmd/yggdrasil/main.go rename to cmd/mesh/main.go index 8185dee0..adf0e467 100644 --- a/cmd/yggdrasil/main.go +++ b/cmd/mesh/main.go @@ -25,16 +25,16 @@ import ( "github.com/kardianos/minwinsvc" "github.com/mitchellh/mapstructure" - "github.com/yggdrasil-network/yggdrasil-go/src/address" - "github.com/yggdrasil-network/yggdrasil-go/src/admin" - "github.com/yggdrasil-network/yggdrasil-go/src/config" - "github.com/yggdrasil-network/yggdrasil-go/src/defaults" - "github.com/yggdrasil-network/yggdrasil-go/src/ipv6rwc" + "github.com/RiV-chain/RiV-mesh/src/address" + "github.com/RiV-chain/RiV-mesh/src/admin" + "github.com/RiV-chain/RiV-mesh/src/config" + "github.com/RiV-chain/RiV-mesh/src/defaults" - "github.com/yggdrasil-network/yggdrasil-go/src/core" - "github.com/yggdrasil-network/yggdrasil-go/src/multicast" - "github.com/yggdrasil-network/yggdrasil-go/src/tun" - "github.com/yggdrasil-network/yggdrasil-go/src/version" + "github.com/RiV-chain/RiV-mesh/src/core" + "github.com/RiV-chain/RiV-mesh/src/ipv6rwc" + "github.com/RiV-chain/RiV-mesh/src/multicast" + "github.com/RiV-chain/RiV-mesh/src/tun" + "github.com/RiV-chain/RiV-mesh/src/version" ) type node struct { @@ -153,6 +153,8 @@ type yggArgs struct { useconffile string logto string loglevel string + httpaddress string + wwwroot string } func getArgs() yggArgs { @@ -167,6 +169,9 @@ func getArgs() yggArgs { getaddr := flag.Bool("address", false, "returns the IPv6 address as derived from the supplied configuration") getsnet := flag.Bool("subnet", false, "returns the IPv6 subnet as derived from the supplied configuration") loglevel := flag.String("loglevel", "info", "loglevel to enable") + httpaddress := flag.String("httpaddress", "", "httpaddress to enable") + wwwroot := flag.String("wwwroot", "", "wwwroot to enable") + flag.Parse() return yggArgs{ genconf: *genconf, @@ -180,10 +185,11 @@ func getArgs() yggArgs { getaddr: *getaddr, getsnet: *getsnet, loglevel: *loglevel, + httpaddress: *httpaddress, + wwwroot: *wwwroot, } } -// The main function is responsible for configuring and starting Yggdrasil. func run(args yggArgs, ctx context.Context) { // Create a new logger that logs output to stdout. var logger *log.Logger @@ -281,10 +287,12 @@ func run(args yggArgs, ctx context.Context) { } return } + //override httpaddress and wwwroot parameters in cfg + cfg.HttpAddress = args.httpaddress + cfg.WwwRoot = args.wwwroot n := &node{} - - // Setup the Yggdrasil node itself. + // Setup the RiV-mesh node itself. { sk, err := hex.DecodeString(cfg.PrivateKey) if err != nil { @@ -335,10 +343,10 @@ func run(args yggArgs, ctx context.Context) { options := []multicast.SetupOption{} for _, intf := range cfg.MulticastInterfaces { options = append(options, multicast.MulticastInterface{ - Regex: regexp.MustCompile(intf.Regex), - Beacon: intf.Beacon, - Listen: intf.Listen, - Port: intf.Port, + Regex: regexp.MustCompile(intf.Regex), + Beacon: intf.Beacon, + Listen: intf.Listen, + Port: intf.Port, Priority: intf.Priority, }) } @@ -372,7 +380,8 @@ func run(args yggArgs, ctx context.Context) { logger.Infof("Your public key is %s", hex.EncodeToString(public[:])) logger.Infof("Your IPv6 address is %s", address.String()) logger.Infof("Your IPv6 subnet is %s", subnet.String()) - + // Start HTTP server + n.admin.StartHttpServer(cfg) // Block until we are told to shut down. <-ctx.Done() diff --git a/cmd/yggdrasilctl/cmd_line_env.go b/cmd/meshctl/cmd_line_env.go similarity index 98% rename from cmd/yggdrasilctl/cmd_line_env.go rename to cmd/meshctl/cmd_line_env.go index 9fcabad9..b2883b84 100644 --- a/cmd/yggdrasilctl/cmd_line_env.go +++ b/cmd/meshctl/cmd_line_env.go @@ -10,7 +10,7 @@ import ( "github.com/hjson/hjson-go" "golang.org/x/text/encoding/unicode" - "github.com/yggdrasil-network/yggdrasil-go/src/defaults" + "github.com/RiV-chain/RiV-mesh/src/defaults" ) type CmdLineEnv struct { diff --git a/cmd/yggdrasilctl/main.go b/cmd/meshctl/main.go similarity index 93% rename from cmd/yggdrasilctl/main.go rename to cmd/meshctl/main.go index c9b1522a..0aba84ea 100644 --- a/cmd/yggdrasilctl/main.go +++ b/cmd/meshctl/main.go @@ -14,11 +14,11 @@ import ( "time" "github.com/olekukonko/tablewriter" - "github.com/yggdrasil-network/yggdrasil-go/src/admin" - "github.com/yggdrasil-network/yggdrasil-go/src/core" - "github.com/yggdrasil-network/yggdrasil-go/src/multicast" - "github.com/yggdrasil-network/yggdrasil-go/src/tun" - "github.com/yggdrasil-network/yggdrasil-go/src/version" + "github.com/RiV-chain/RiV-mesh/src/admin" + "github.com/RiV-chain/RiV-mesh/src/core" + "github.com/RiV-chain/RiV-mesh/src/multicast" + "github.com/RiV-chain/RiV-mesh/src/tun" + "github.com/RiV-chain/RiV-mesh/src/version" ) func main() { @@ -45,7 +45,7 @@ func run() int { if cmdLineEnv.ver { fmt.Println("Build name:", version.BuildName()) fmt.Println("Build version:", version.BuildVersion()) - fmt.Println("To get the version number of the running Yggdrasil node, run", os.Args[0], "getSelf") + fmt.Println("To get the version number of the running Mesh node, run", os.Args[0], "getSelf") return 0 } @@ -111,6 +111,8 @@ func run() int { panic(err) } logger.Printf("Request sent") + //js, _ := json.Marshal(send) + //fmt.Println("sent:", string(js)) if err := decoder.Decode(&recv); err != nil { panic(err) } @@ -180,11 +182,10 @@ func run() int { fmt.Sprintf("%d", peer.Port), peer.PublicKey, peer.IPAddress, + peer.Remote, (time.Duration(peer.Uptime) * time.Second).String(), peer.RXBytes.String(), peer.TXBytes.String(), - fmt.Sprintf("%d", peer.Priority), - peer.Remote, }) } table.Render() @@ -270,8 +271,6 @@ func run() int { } table.Render() - case "addpeer", "removepeer": - default: fmt.Println(string(recv.Response)) } diff --git a/contrib/ansible/genkeys.go b/contrib/ansible/genkeys.go index 4a02b9bd..5d941ad1 100644 --- a/contrib/ansible/genkeys.go +++ b/contrib/ansible/genkeys.go @@ -1,6 +1,6 @@ /* -This file generates crypto keys for [ansible-yggdrasil](https://github.com/jcgruenhage/ansible-yggdrasil/) +This file generates crypto keys for [ansible-mesh](https://github.com/jcgruenhage/ansible-mesh/) */ package main @@ -14,7 +14,7 @@ import ( "os" "github.com/cheggaaa/pb/v3" - "github.com/yggdrasil-network/yggdrasil-go/src/address" + "github.com/RiV-chain/RiV-mesh/src/address" ) var numHosts = flag.Int("hosts", 1, "number of host vars to generate") @@ -57,8 +57,8 @@ func main() { return } defer file.Close() - file.WriteString(fmt.Sprintf("yggdrasil_public_key: %v\n", hex.EncodeToString(keys[i].pub))) - file.WriteString("yggdrasil_private_key: \"{{ vault_yggdrasil_private_key }}\"\n") + file.WriteString(fmt.Sprintf("mesh_public_key: %v\n", hex.EncodeToString(keys[i].pub))) + file.WriteString("mesh_private_key: \"{{ vault_mesh_private_key }}\"\n") file.WriteString(fmt.Sprintf("ansible_host: %v\n", keys[i].ip)) file, err = os.Create(fmt.Sprintf("host_vars/%x/vault", i)) @@ -66,7 +66,7 @@ func main() { return } defer file.Close() - file.WriteString(fmt.Sprintf("vault_yggdrasil_private_key: %v\n", hex.EncodeToString(keys[i].priv))) + file.WriteString(fmt.Sprintf("vault_mesh_private_key: %v\n", hex.EncodeToString(keys[i].priv))) bar.Increment() } bar.Finish() diff --git a/contrib/apparmor/usr.bin.yggdrasil b/contrib/apparmor/usr.bin.mesh similarity index 80% rename from contrib/apparmor/usr.bin.yggdrasil rename to contrib/apparmor/usr.bin.mesh index b305199f..cecd410b 100644 --- a/contrib/apparmor/usr.bin.yggdrasil +++ b/contrib/apparmor/usr.bin.mesh @@ -1,7 +1,7 @@ # Last Modified: Fri Oct 30 11:33:31 2020 #include -/usr/bin/yggdrasil { +/usr/bin/mesh { #include #include @@ -12,6 +12,6 @@ /proc/sys/net/core/somaxconn r, /sys/kernel/mm/transparent_hugepage/hpage_pmd_size r, - /etc/yggdrasil.conf rw, - /run/yggdrasil.sock rw, + /etc/mesh.conf rw, + /run/mesh.sock rw, } diff --git a/contrib/busybox-init/S42yggdrasil b/contrib/busybox-init/S42mesh similarity index 68% rename from contrib/busybox-init/S42yggdrasil rename to contrib/busybox-init/S42mesh index 862efc25..9d6b0e39 100755 --- a/contrib/busybox-init/S42yggdrasil +++ b/contrib/busybox-init/S42mesh @@ -1,9 +1,9 @@ #!/bin/sh -CONFFILE="/etc/yggdrasil.conf" +CONFFILE="/etc/mesh.conf" genconf() { - /usr/bin/yggdrasil -genconf > "$1" + /usr/bin/mesh -genconf > "$1" return $? } @@ -33,8 +33,8 @@ start() { fi fi - printf 'Starting yggdrasil: ' - if start-stop-daemon -S -q -b -x /usr/bin/yggdrasil \ + printf 'Starting mesh: ' + if start-stop-daemon -S -q -b -x /usr/bin/mesh \ -- -useconffile "$CONFFILE"; then echo "OK" else @@ -43,8 +43,8 @@ start() { } stop() { - printf "Stopping yggdrasil: " - if start-stop-daemon -K -q -x /usr/bin/yggdrasil; then + printf "Stopping mesh: " + if start-stop-daemon -K -q -x /usr/bin/mesh; then echo "OK" else echo "FAIL" @@ -52,8 +52,8 @@ stop() { } reload() { - printf "Reloading yggdrasil: " - if start-stop-daemon -K -q -s HUP -x /usr/bin/yggdrasil; then + printf "Reloading mesh: " + if start-stop-daemon -K -q -s HUP -x /usr/bin/mesh; then echo "OK" else echo "FAIL" diff --git a/contrib/deb/generate-gui.sh b/contrib/deb/generate-gui.sh new file mode 100755 index 00000000..42905376 --- /dev/null +++ b/contrib/deb/generate-gui.sh @@ -0,0 +1,165 @@ +#!/bin/sh + +# This is a lazy script to create a .deb for Debian/Ubuntu. It installs +# mesh and enables it in systemd. You can give it the PKGARCH= argument +# i.e. PKGARCH=i386 sh contrib/deb/generate.sh + +if [ `pwd` != `git rev-parse --show-toplevel` ] +then + echo "You should run this script from the top-level directory of the git repo" + exit 1 +fi + +PKGBRANCH=$(basename `git name-rev --name-only HEAD`) +PKG=$(sh contrib/semver/name.sh) +PKGVERSION=$(sh contrib/semver/version.sh --bare) +PKGARCH=${PKGARCH-amd64} +PKGNAME=$PKG-$PKGVERSION-$PKGARCH +PKGFILE=$PKGNAME.deb +PKGREPLACES=mesh + +if [ $PKGBRANCH = "master" ]; then + PKGREPLACES=mesh-develop +fi + +if [ $PKGARCH = "amd64" ]; then GOARCH=amd64 GOOS=linux ./build +elif [ $PKGARCH = "i386" ]; then GOARCH=386 GOOS=linux ./build +else + echo "Specify PKGARCH=amd64,i386,mips,mipsel,armhf,arm64,armel" + exit 1 +fi + +echo "Building $PKGFILE" + +mkdir -p /tmp/$PKGNAME/ +mkdir -p /tmp/$PKGNAME/debian/ +mkdir -p /tmp/$PKGNAME/DEBIAN/ +mkdir -p /tmp/$PKGNAME/usr/bin/ +mkdir -p /tmp/$PKGNAME/usr/local/bin/ +mkdir -p /tmp/$PKGNAME/etc/systemd/system/ +mkdir -p /tmp/$PKGNAME/usr/share/applications/ +mkdir -p /tmp/$PKGNAME/etc/ +mkdir -p /tmp/$PKGNAME/etc/xdg/autostart +chmod 0775 /tmp/$PKGNAME/ -R + +for resolution in 16x16 24x24 32x32 48x48 64x64 192x192 256x256 512x512; do + echo "Converting icon for: $resolution" + mkdir -p /tmp/$PKGNAME/usr/share/icons/hicolor/$resolution/apps && \ + convert -colorspace sRGB ./riv.png -resize $resolution PNG8:/tmp/$PKGNAME/usr/share/icons/hicolor/$resolution/apps/riv.png && \ + chmod 644 /tmp/$PKGNAME/usr/share/icons/hicolor/$resolution/apps/riv.png +done + +cp contrib/ui/mesh-ui/index.html /tmp/$PKGNAME/etc/ + +cat > /tmp/$PKGNAME/usr/share/applications/riv.desktop << EOF +[Desktop Entry] +Name=RiV mesh +GenericName=Mesh network +Comment=RiV-mesh is an early-stage implementation of a fully end-to-end encrypted IPv6 network +Exec=sh -c "/usr/bin/mesh-ui /etc/index.html" +Terminal=false +Type=Application +Icon=riv +Categories=Network;FileTransfer; +StartupNotify=false +EOF + +cat > /tmp/$PKGNAME/debian/changelog << EOF +Please see https://github.com/RiV-chain/RiV-mesh/ +EOF +echo 9 > /tmp/$PKGNAME/debian/compat +cat > /tmp/$PKGNAME/DEBIAN/control << EOF +Package: mesh +Version: $PKGVERSION +Section: contrib/net +Priority: extra +Architecture: $PKGARCH +Replaces: $PKGREPLACES +Conflicts: $PKGREPLACES +Maintainer: Vadym Vikulin +Description: RiV-mesh is an implementation of a fully end-to-end encrypted IPv6 network. + It is lightweight, self-arranging, supported on multiple platforms and + allows pretty much any IPv6-capable application to communicate securely with + other RiV-mesh nodes. +EOF +cat > /tmp/$PKGNAME/debian/copyright << EOF +Please see https://github.com/RiV-chain/RiV-mesh/ +EOF +cat > /tmp/$PKGNAME/debian/docs << EOF +Please see https://github.com/RiV-chain/RiV-mesh/ +EOF +cat > /tmp/$PKGNAME/debian/install << EOF +usr/bin/mesh usr/bin +usr/bin/meshctl usr/bin +usr/bin/mesh-ui usr/bin +usr/local/bin/meshctl usr/local/bin +etc/index.html etc +etc/xdg/autostart/riv.desktop etc/xdg/autostart +etc/systemd/system/*.service etc/systemd/system +usr/share/applications/riv.desktop usr/share/applications +usr/share/icons/hicolor/16x16/apps/riv.png usr/share/icons/hicolor/16x16/apps +usr/share/icons/hicolor/24x24/apps/riv.png usr/share/icons/hicolor/24x24/apps +usr/share/icons/hicolor/32x32/apps/riv.png usr/share/icons/hicolor/32x32/apps +usr/share/icons/hicolor/48x48/apps/riv.png usr/share/icons/hicolor/48x48/apps +usr/share/icons/hicolor/64x64/apps/riv.png usr/share/icons/hicolor/64x64/apps +usr/share/icons/hicolor/192x192/apps/riv.png usr/share/icons/hicolor/192x192/apps +usr/share/icons/hicolor/256x256/apps/riv.png usr/share/icons/hicolor/256x256/apps +usr/share/icons/hicolor/512x512/apps/riv.png usr/share/icons/hicolor/512x512/apps +EOF + +cat > /tmp/$PKGNAME/DEBIAN/postinst << EOF +#!/bin/sh + +if ! getent group mesh 2>&1 > /dev/null; then + groupadd --system --force mesh || echo "Failed to create group 'mesh' - please create it manually and reinstall" +fi + +if [ -f /etc/mesh.conf ]; then + mkdir -p /var/backups + echo "Backing up configuration file to /var/backups/mesh.conf.`date +%Y%m%d`" + cp /etc/mesh.conf /var/backups/mesh.conf.`date +%Y%m%d` + echo "Normalising and updating /etc/mesh.conf" + /usr/bin/mesh -useconf -normaliseconf < /var/backups/mesh.conf.`date +%Y%m%d` > /etc/mesh.conf +else + echo "Generating initial configuration file /etc/mesh.conf" + echo "Please familiarise yourself with this file before starting Mesh" + sh -c 'umask 0027 && /usr/bin/mesh -genconf > /etc/mesh.conf' +fi +chgrp mesh /etc/mesh.conf +chmod 755 /etc/mesh.conf +if command -v systemctl >/dev/null; then + systemctl daemon-reload || echo -n "daemon not reloaded!" + systemctl enable mesh || echo -n "systemctl enable failed!" + systemctl restart mesh || echo -n "systemctl restart failed!" +fi +update-icon-caches /usr/share/icons/* +update-desktop-database /usr/share/applications +EOF + +cat > /tmp/$PKGNAME/DEBIAN/prerm << EOF +#!/bin/sh +if command -v systemctl >/dev/null; then + if systemctl is-active --quiet mesh; then + systemctl stop mesh || true + fi + systemctl disable mesh || true +fi +EOF + +cp mesh /tmp/$PKGNAME/usr/bin/ +cp meshctl /tmp/$PKGNAME/usr/bin/ +cp mesh-ui /tmp/$PKGNAME/usr/bin/ +ln -s /usr/bin/meshctl /tmp/$PKGNAME/usr/local/bin/meshctl +cp contrib/systemd/*.service /tmp/$PKGNAME/etc/systemd/system/ +cp /tmp/$PKGNAME/usr/share/applications/riv.desktop /tmp/$PKGNAME/etc/xdg/autostart +chmod 0775 /tmp/$PKGNAME/DEBIAN/* +chmod 644 /tmp/$PKGNAME/etc/systemd/system/* +chmod 644 /tmp/$PKGNAME/usr/share/applications/riv.desktop +chmod 644 /tmp/$PKGNAME/etc/xdg/autostart/* +chmod 755 /tmp/$PKGNAME/usr/bin/* +chmod 755 /tmp/$PKGNAME/etc/index.html + +dpkg-deb --build --root-owner-group /tmp/$PKGNAME +cp /tmp/$PKGFILE . + +rm -rf /tmp/$PKGNAME diff --git a/contrib/deb/generate.sh b/contrib/deb/generate.sh index ebe2753a..30622c19 100644 --- a/contrib/deb/generate.sh +++ b/contrib/deb/generate.sh @@ -1,7 +1,7 @@ #!/bin/sh # This is a lazy script to create a .deb for Debian/Ubuntu. It installs -# yggdrasil and enables it in systemd. You can give it the PKGARCH= argument +# mesh and enables it in systemd. You can give it the PKGARCH= argument # i.e. PKGARCH=i386 sh contrib/deb/generate.sh if [ `pwd` != `git rev-parse --show-toplevel` ] @@ -11,14 +11,15 @@ then fi PKGBRANCH=$(basename `git name-rev --name-only HEAD`) -PKGNAME=$(sh contrib/semver/name.sh) +PKG=$(sh contrib/semver/name.sh) PKGVERSION=$(sh contrib/semver/version.sh --bare) PKGARCH=${PKGARCH-amd64} -PKGFILE=$PKGNAME-$PKGVERSION-$PKGARCH.deb -PKGREPLACES=yggdrasil +PKGNAME=$PKG-$PKGVERSION-$PKGARCH-nogui +PKGFILE=$PKGNAME.deb +PKGREPLACES=mesh if [ $PKGBRANCH = "master" ]; then - PKGREPLACES=yggdrasil-develop + PKGREPLACES=mesh-develop fi if [ $PKGARCH = "amd64" ]; then GOARCH=amd64 GOOS=linux ./build @@ -37,91 +38,92 @@ echo "Building $PKGFILE" mkdir -p /tmp/$PKGNAME/ mkdir -p /tmp/$PKGNAME/debian/ +mkdir -p /tmp/$PKGNAME/DEBIAN/ mkdir -p /tmp/$PKGNAME/usr/bin/ +mkdir -p /tmp/$PKGNAME/usr/local/bin/ mkdir -p /tmp/$PKGNAME/etc/systemd/system/ +chmod 0775 /tmp/$PKGNAME/ -R cat > /tmp/$PKGNAME/debian/changelog << EOF -Please see https://github.com/yggdrasil-network/yggdrasil-go/ +Please see https://github.com/RiV-chain/RiV-mesh/ EOF echo 9 > /tmp/$PKGNAME/debian/compat -cat > /tmp/$PKGNAME/debian/control << EOF -Package: $PKGNAME +cat > /tmp/$PKGNAME/DEBIAN/control << EOF +Package: mesh Version: $PKGVERSION Section: contrib/net Priority: extra Architecture: $PKGARCH Replaces: $PKGREPLACES Conflicts: $PKGREPLACES -Maintainer: Neil Alexander -Description: Yggdrasil Network - Yggdrasil is an early-stage implementation of a fully end-to-end encrypted IPv6 - network. It is lightweight, self-arranging, supported on multiple platforms and +Maintainer: Vadym Vikulin +Description: RiV-mesh is an implementation of a fully end-to-end encrypted IPv6 network. + It is lightweight, self-arranging, supported on multiple platforms and allows pretty much any IPv6-capable application to communicate securely with - other Yggdrasil nodes. + other RiV-mesh nodes. EOF cat > /tmp/$PKGNAME/debian/copyright << EOF -Please see https://github.com/yggdrasil-network/yggdrasil-go/ +Please see https://github.com/RiV-chain/RiV-mesh/ EOF cat > /tmp/$PKGNAME/debian/docs << EOF -Please see https://github.com/yggdrasil-network/yggdrasil-go/ +Please see https://github.com/RiV-chain/RiV-mesh/ EOF cat > /tmp/$PKGNAME/debian/install << EOF -usr/bin/yggdrasil usr/bin -usr/bin/yggdrasilctl usr/bin +usr/bin/mesh usr/bin +usr/bin/meshctl usr/bin +usr/local/bin/meshctl usr/local/bin etc/systemd/system/*.service etc/systemd/system EOF -cat > /tmp/$PKGNAME/debian/postinst << EOF +cat > /tmp/$PKGNAME/DEBIAN/postinst << EOF #!/bin/sh -if ! getent group yggdrasil 2>&1 > /dev/null; then - groupadd --system --force yggdrasil || echo "Failed to create group 'yggdrasil' - please create it manually and reinstall" +if ! getent group mesh 2>&1 > /dev/null; then + groupadd --system --force mesh || echo "Failed to create group 'mesh' - please create it manually and reinstall" fi -if [ -f /etc/yggdrasil.conf ]; -then +if [ -f /etc/mesh.conf ]; then mkdir -p /var/backups - echo "Backing up configuration file to /var/backups/yggdrasil.conf.`date +%Y%m%d`" - cp /etc/yggdrasil.conf /var/backups/yggdrasil.conf.`date +%Y%m%d` - echo "Normalising and updating /etc/yggdrasil.conf" - /usr/bin/yggdrasil -useconf -normaliseconf < /var/backups/yggdrasil.conf.`date +%Y%m%d` > /etc/yggdrasil.conf - chgrp yggdrasil /etc/yggdrasil.conf - - if command -v systemctl >/dev/null; then - systemctl daemon-reload >/dev/null || true - systemctl enable yggdrasil || true - systemctl start yggdrasil || true - fi + echo "Backing up configuration file to /var/backups/mesh.conf.`date +%Y%m%d`" + cp /etc/mesh.conf /var/backups/mesh.conf.`date +%Y%m%d` + echo "Normalising and updating /etc/mesh.conf" + /usr/bin/mesh -useconf -normaliseconf < /var/backups/mesh.conf.`date +%Y%m%d` > /etc/mesh.conf else - echo "Generating initial configuration file /etc/yggdrasil.conf" - echo "Please familiarise yourself with this file before starting Yggdrasil" - sh -c 'umask 0027 && /usr/bin/yggdrasil -genconf > /etc/yggdrasil.conf' - chgrp yggdrasil /etc/yggdrasil.conf + echo "Generating initial configuration file /etc/mesh.conf" + echo "Please familiarise yourself with this file before starting RiV-mesh" + sh -c 'umask 0027 && /usr/bin/mesh -genconf > /etc/mesh.conf' +fi +chgrp mesh /etc/mesh.conf +chmod 755 /etc/mesh.conf +if command -v systemctl >/dev/null; then + systemctl daemon-reload || echo -n "daemon not reloaded!" + systemctl enable mesh || echo -n "systemctl enable failed!" + systemctl restart mesh || echo -n "systemctl restart failed!" fi EOF -cat > /tmp/$PKGNAME/debian/prerm << EOF +cat > /tmp/$PKGNAME/DEBIAN/prerm << EOF #!/bin/sh if command -v systemctl >/dev/null; then - if systemctl is-active --quiet yggdrasil; then - systemctl stop yggdrasil || true + if systemctl is-active --quiet mesh; then + systemctl stop mesh || true fi - systemctl disable yggdrasil || true + systemctl disable mesh || true fi EOF -cp yggdrasil /tmp/$PKGNAME/usr/bin/ -cp yggdrasilctl /tmp/$PKGNAME/usr/bin/ -cp contrib/systemd/*.service /tmp/$PKGNAME/etc/systemd/system/ +cp mesh /tmp/$PKGNAME/usr/bin/ +cp meshctl /tmp/$PKGNAME/usr/bin/ +ln -s /usr/bin/meshctl /tmp/$PKGNAME/usr/local/bin/meshctl +if [ $LOGLEVEL = "DEBUG" ]; then cp contrib/systemd/mesh-debug.service /tmp/$PKGNAME/etc/systemd/system/mesh.service +else + cp contrib/systemd/mesh.service /tmp/$PKGNAME/etc/systemd/system/ +fi -tar -czvf /tmp/$PKGNAME/data.tar.gz -C /tmp/$PKGNAME/ \ - usr/bin/yggdrasil usr/bin/yggdrasilctl \ - etc/systemd/system/yggdrasil.service \ - etc/systemd/system/yggdrasil-default-config.service -tar -czvf /tmp/$PKGNAME/control.tar.gz -C /tmp/$PKGNAME/debian . -echo 2.0 > /tmp/$PKGNAME/debian-binary +cp contrib/systemd/mesh-default-config.service /tmp/$PKGNAME/etc/systemd/system/ +chmod 0775 /tmp/$PKGNAME/DEBIAN/* +chmod 644 /tmp/$PKGNAME/etc/systemd/system/* +chmod 755 /tmp/$PKGNAME/usr/bin/* -ar -r $PKGFILE \ - /tmp/$PKGNAME/debian-binary \ - /tmp/$PKGNAME/control.tar.gz \ - /tmp/$PKGNAME/data.tar.gz +dpkg-deb --build --root-owner-group /tmp/$PKGNAME +cp /tmp/$PKGFILE . rm -rf /tmp/$PKGNAME diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 15129b16..bdce88d7 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -9,17 +9,17 @@ RUN apk add git && ./build && go build -o /src/genkeys cmd/genkeys/main.go FROM docker.io/alpine -COPY --from=builder /src/yggdrasil /usr/bin/yggdrasil -COPY --from=builder /src/yggdrasilctl /usr/bin/yggdrasilctl +COPY --from=builder /src/mesh /usr/bin/mesh +COPY --from=builder /src/meshctl /usr/bin/meshctl COPY --from=builder /src/genkeys /usr/bin/genkeys COPY contrib/docker/entrypoint.sh /usr/bin/entrypoint.sh -# RUN addgroup -g 1000 -S yggdrasil-network \ -# && adduser -u 1000 -S -g 1000 --home /etc/yggdrasil-network yggdrasil-network +# RUN addgroup -g 1000 -S RiV-chain \ +# && adduser -u 1000 -S -g 1000 --home /etc/RiV-chain RiV-chain # -# USER yggdrasil-network +# USER RiV-chain # TODO: Make running unprivileged work -VOLUME [ "/etc/yggdrasil-network" ] +VOLUME [ "/etc/RiV-chain" ] ENTRYPOINT [ "/usr/bin/entrypoint.sh" ] diff --git a/contrib/docker/entrypoint.sh b/contrib/docker/entrypoint.sh index 26c685a8..167eead1 100755 --- a/contrib/docker/entrypoint.sh +++ b/contrib/docker/entrypoint.sh @@ -2,12 +2,12 @@ set -e -CONF_DIR="/etc/yggdrasil-network" +CONF_DIR="/etc/RiV-chain" if [ ! -f "$CONF_DIR/config.conf" ]; then echo "generate $CONF_DIR/config.conf" - yggdrasil --genconf > "$CONF_DIR/config.conf" + mesh --genconf > "$CONF_DIR/config.conf" fi -yggdrasil --useconf < "$CONF_DIR/config.conf" +mesh --useconf < "$CONF_DIR/config.conf" exit $? diff --git a/contrib/freebsd/mesh b/contrib/freebsd/mesh new file mode 100644 index 00000000..30fb8471 --- /dev/null +++ b/contrib/freebsd/mesh @@ -0,0 +1,72 @@ +#!/bin/sh +# +# Put the mesh and meshctl binaries into /usr/local/bin +# Then copy this script into /etc/rc.d/mesh +# Finally, run: +# 1. chmod +x /etc/rc.d/mesh /usr/local/bin/{mesh,meshctl} +# 2. echo "mesh_enable=yes" >> /etc/rc.d +# 3. service mesh start +# +# PROVIDE: mesh +# REQUIRE: networking +# KEYWORD: + +. /etc/rc.subr + +name="mesh" +rcvar="mesh_enable" + +start_cmd="${name}_start" +stop_cmd="${name}_stop" + +pidfile="/var/run/mesh/${name}.pid" +command="/usr/sbin/daemon" +command_args="-P ${pidfile} -r -f ${mesh_command}" + +mesh_start() +{ + test ! -x /usr/local/bin/mesh && ( + logger -s -t mesh "Warning: /usr/local/bin/mesh is missing or not executable" + logger -s -t mesh "Copy the mesh binary into /usr/local/bin and then chmod +x /usr/local/bin/mesh" + return 1 + ) + + test ! -f /etc/mesh.conf && ( + logger -s -t mesh "Generating new configuration file into /etc/mesh.conf" + /usr/local/bin/mesh -genconf > /etc/mesh.conf + ) + + tap_path="$(cat /etc/mesh.conf | egrep -o '/dev/tap[0-9]{1,2}$')" + tap_name="$(echo -n ${tap_path} | tr -d '/dev/')" + + /sbin/ifconfig ${tap_name} >/dev/null 2>&1 || ( + logger -s -t mesh "Creating ${tap_name} adapter" + /sbin/ifconfig ${tap_name} create || logger -s -t mesh "Failed to create ${tap_name} adapter" + ) + + test ! -d /var/run/mesh && mkdir -p /var/run/mesh + + logger -s -t mesh "Starting mesh" + ${command} ${command_args} /usr/local/bin/mesh -useconffile /etc/mesh.conf \ + 1>/var/log/mesh.stdout.log \ + 2>/var/log/mesh.stderr.log & +} + +mesh_stop() +{ + logger -s -t mesh "Stopping mesh" + test -f /var/run/mesh/${name}.pid && kill -TERM $(cat /var/run/mesh/${name}.pid) + + tap_path="$(cat /etc/mesh.conf | grep /dev/tap | egrep -o '/dev/.*$')" + tap_name="$(echo -n ${tap_path} | tr -d '/dev/')" + + /sbin/ifconfig ${tap_name} >/dev/null 2>&1 && ( + logger -s -t mesh "Destroying ${tap_name} adapter" + /sbin/ifconfig ${tap_name} destroy || logger -s -t mesh "Failed to destroy ${tap_name} adapter" + ) +} + +load_rc_config $name +: ${mesh_enable:=no} + +run_rc_command "$1" diff --git a/contrib/freebsd/yggdrasil b/contrib/freebsd/yggdrasil deleted file mode 100644 index 58482fc9..00000000 --- a/contrib/freebsd/yggdrasil +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/sh -# -# Put the yggdrasil and yggdrasilctl binaries into /usr/local/bin -# Then copy this script into /etc/rc.d/yggdrasil -# Finally, run: -# 1. chmod +x /etc/rc.d/yggdrasil /usr/local/bin/{yggdrasil,yggdrasilctl} -# 2. echo "yggdrasil_enable=yes" >> /etc/rc.d -# 3. service yggdrasil start -# -# PROVIDE: yggdrasil -# REQUIRE: networking -# KEYWORD: - -. /etc/rc.subr - -name="yggdrasil" -rcvar="yggdrasil_enable" - -start_cmd="${name}_start" -stop_cmd="${name}_stop" - -pidfile="/var/run/yggdrasil/${name}.pid" -command="/usr/sbin/daemon" -command_args="-P ${pidfile} -r -f ${yggdrasil_command}" - -yggdrasil_start() -{ - test ! -x /usr/local/bin/yggdrasil && ( - logger -s -t yggdrasil "Warning: /usr/local/bin/yggdrasil is missing or not executable" - logger -s -t yggdrasil "Copy the yggdrasil binary into /usr/local/bin and then chmod +x /usr/local/bin/yggdrasil" - return 1 - ) - - test ! -f /etc/yggdrasil.conf && ( - logger -s -t yggdrasil "Generating new configuration file into /etc/yggdrasil.conf" - /usr/local/bin/yggdrasil -genconf > /etc/yggdrasil.conf - ) - - tap_path="$(cat /etc/yggdrasil.conf | egrep -o '/dev/tap[0-9]{1,2}$')" - tap_name="$(echo -n ${tap_path} | tr -d '/dev/')" - - /sbin/ifconfig ${tap_name} >/dev/null 2>&1 || ( - logger -s -t yggdrasil "Creating ${tap_name} adapter" - /sbin/ifconfig ${tap_name} create || logger -s -t yggdrasil "Failed to create ${tap_name} adapter" - ) - - test ! -d /var/run/yggdrasil && mkdir -p /var/run/yggdrasil - - logger -s -t yggdrasil "Starting yggdrasil" - ${command} ${command_args} /usr/local/bin/yggdrasil -useconffile /etc/yggdrasil.conf \ - 1>/var/log/yggdrasil.stdout.log \ - 2>/var/log/yggdrasil.stderr.log & -} - -yggdrasil_stop() -{ - logger -s -t yggdrasil "Stopping yggdrasil" - test -f /var/run/yggdrasil/${name}.pid && kill -TERM $(cat /var/run/yggdrasil/${name}.pid) - - tap_path="$(cat /etc/yggdrasil.conf | grep /dev/tap | egrep -o '/dev/.*$')" - tap_name="$(echo -n ${tap_path} | tr -d '/dev/')" - - /sbin/ifconfig ${tap_name} >/dev/null 2>&1 && ( - logger -s -t yggdrasil "Destroying ${tap_name} adapter" - /sbin/ifconfig ${tap_name} destroy || logger -s -t yggdrasil "Failed to destroy ${tap_name} adapter" - ) -} - -load_rc_config $name -: ${yggdrasil_enable:=no} - -run_rc_command "$1" diff --git a/contrib/macos/create-pkg-gui.sh b/contrib/macos/create-pkg-gui.sh new file mode 100644 index 00000000..35a617e6 --- /dev/null +++ b/contrib/macos/create-pkg-gui.sh @@ -0,0 +1,176 @@ +#!/bin/sh + +# Check if xar and mkbom are available +command -v xar >/dev/null 2>&1 || ( + echo "Building xar" + sudo apt-get install libxml2-dev libssl1.0-dev zlib1g-dev autoconf -y + rm -rf /tmp/xar && mkdir -p /tmp/xar && cd /tmp/xar + #git clone https://github.com/mackyle/xar && cd xar/xar + git clone https://github.com/RiV-chain/xar.git && cd xar/xar + (sh autogen.sh && make && sudo make install) || (echo "Failed to build xar"; exit 1) +) +command -v mkbom >/dev/null 2>&1 || ( + echo "Building mkbom" + mkdir -p /tmp/mkbom && cd /tmp/mkbom + git clone https://github.com/hogliux/bomutils && cd bomutils + sudo make install || (echo "Failed to build mkbom"; exit 1) +) + +# Build RiV-mesh +echo "running GO111MODULE=on GOOS=darwin GOARCH=${PKGARCH-amd64} ./build" +GO111MODULE=on GOOS=darwin GOARCH=${PKGARCH-amd64} ./build + +# Check if we can find the files we need - they should +# exist if you are running this script from the root of +# the RiV-mesh repo and you have ran ./build +test -f mesh || (echo "mesh binary not found"; exit 1) +test -f meshctl || (echo "meshctl binary not found"; exit 1) +test -f mesh-ui || (echo "mesh-ui binary not found"; exit 1) +test -f contrib/macos/mesh.plist || (echo "contrib/macos/mesh.plist not found"; exit 1) +test -f contrib/semver/version.sh || (echo "contrib/semver/version.sh not found"; exit 1) + +# Delete the pkgbuild folder if it already exists +test -d pkgbuild && rm -rf pkgbuild + +# Create our folder structure + +mkdir -p pkgbuild/scripts +mkdir -p pkgbuild/flat/base.pkg +mkdir -p pkgbuild/flat/Resources/en.lproj +mkdir -p pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS +mkdir -p pkgbuild/root/Applications/RiV-mesh.app/Contents/Resources +mkdir -p pkgbuild/root/usr/local/bin +mkdir -p pkgbuild/root/Library/LaunchDaemons + +# Copy package contents into the pkgbuild root +cp meshctl pkgbuild/root/usr/local/bin +cp mesh pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS +cp mesh-ui pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS +cp riv.icns pkgbuild/root/Applications/RiV-mesh.app/Contents/Resources +cp contrib/ui/mesh-ui/index.html pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS +cp contrib/macos/mesh.plist pkgbuild/root/Library/LaunchDaemons + +# Create the postinstall script +cat > pkgbuild/scripts/postinstall << EOF +#!/bin/sh + +# Normalise the config if it exists, generate it if it doesn't +if [ -f /etc/mesh.conf ]; +then + mkdir -p /Library/Preferences/RiV-mesh + echo "Backing up configuration file to /Library/Preferences/RiV-mesh/mesh.conf.`date +%Y%m%d`" + cp /etc/mesh.conf /Library/Preferences/RiV-mesh/mesh.conf.`date +%Y%m%d` + echo "Normalising /etc/mesh.conf" + /Applications/RiV-mesh.app/Contents/MacOS/mesh -useconffile /Library/Preferences/RiV-mesh/mesh.conf.`date +%Y%m%d` -normaliseconf > /etc/mesh.conf +else + /Applications/RiV-mesh.app/Contents/MacOS/mesh -genconf > /etc/mesh.conf +fi + +chmod 755 /etc/mesh.conf + +# Unload existing RiV-mesh launchd service, if possible +test -f /Library/LaunchDaemons/mesh.plist && (launchctl unload /Library/LaunchDaemons/mesh.plist || true) + +# Load RiV-mesh launchd service and start RiV-mesh +launchctl load /Library/LaunchDaemons/mesh.plist +EOF + +# Set execution permissions +chmod 755 pkgbuild/scripts/postinstall +chmod 755 pkgbuild/root/usr/local/bin/meshctl +chmod 755 pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS/mesh +chmod 755 pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS/mesh-ui +chmod 755 pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS/index.html + +# Work out metadata for the package info +PKGNAME=$(sh contrib/semver/name.sh) +PKGVERSION=$(sh contrib/semver/version.sh --bare) +PKGARCH=${PKGARCH-amd64} + +# Create the Info.plist file +cat > pkgbuild/root/Applications/RiV-mesh.app/Contents/Info.plist << EOF + + + + Label + org.riv-mesh.ui + NSPrincipalClass + NSApplication + CFBundleName + RiV-mesh + NSHighResolutionCapable + True + CFBundleIconFile + riv.icns + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleGetInfoString + ${PKGVERSION} + CFBundleVersion + ${PKGVERSION} + CFBundleShortVersionString + ${PKGVERSION} + CFBundleExecutable + mesh-ui + CFBundleIdentifier + io.github.RiV-mesh.pkg + StandardOutPath + /tmp/mesh-ui.stdout.log + StandardErrorPath + /tmp/mesh-ui.stderr.log + + +EOF + +# Pack payload and scripts +( cd pkgbuild/scripts && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > pkgbuild/flat/base.pkg/Scripts +( cd pkgbuild/root && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > pkgbuild/flat/base.pkg/Payload + +PAYLOADSIZE=$(( $(wc -c pkgbuild/flat/base.pkg/Payload | awk '{ print $1 }') / 1024 )) + +# Create the PackageInfo file +cat > pkgbuild/flat/base.pkg/PackageInfo << EOF + + + + + + +EOF + +# Create the BOM +( cd pkgbuild && mkbom root flat/base.pkg/Bom ) + +# Create the Distribution file +cat > pkgbuild/flat/Distribution << EOF + + + RiV-mesh (${PKGNAME}-${PKGVERSION}) + + + + + + + + + + + #base.pkg + +EOF + +# Finally pack the .pkg +( cd pkgbuild/flat && xar --compression none -cf "../../${PKGNAME}-${PKGVERSION}-macos-${PKGARCH}.pkg" * ) diff --git a/contrib/macos/create-pkg.sh b/contrib/macos/create-pkg.sh index 773f01ee..960ee691 100755 --- a/contrib/macos/create-pkg.sh +++ b/contrib/macos/create-pkg.sh @@ -15,16 +15,12 @@ command -v mkbom >/dev/null 2>&1 || ( sudo make install || (echo "Failed to build mkbom"; exit 1) ) -# Build Yggdrasil -echo "running GO111MODULE=on GOOS=darwin GOARCH=${PKGARCH-amd64} ./build" -GO111MODULE=on GOOS=darwin GOARCH=${PKGARCH-amd64} ./build - # Check if we can find the files we need - they should # exist if you are running this script from the root of -# the yggdrasil-go repo and you have ran ./build -test -f yggdrasil || (echo "yggdrasil binary not found"; exit 1) -test -f yggdrasilctl || (echo "yggdrasilctl binary not found"; exit 1) -test -f contrib/macos/yggdrasil.plist || (echo "contrib/macos/yggdrasil.plist not found"; exit 1) +# the RiV-mesh repo and you have ran ./build +test -f mesh || (echo "mesh binary not found"; exit 1) +test -f meshctl || (echo "meshctl binary not found"; exit 1) +test -f contrib/macos/mesh.plist || (echo "contrib/macos/mesh.plist not found"; exit 1) test -f contrib/semver/version.sh || (echo "contrib/semver/version.sh not found"; exit 1) # Delete the pkgbuild folder if it already exists @@ -35,40 +31,43 @@ mkdir -p pkgbuild/scripts mkdir -p pkgbuild/flat/base.pkg mkdir -p pkgbuild/flat/Resources/en.lproj mkdir -p pkgbuild/root/usr/local/bin +mkdir -p pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS mkdir -p pkgbuild/root/Library/LaunchDaemons # Copy package contents into the pkgbuild root -cp yggdrasil pkgbuild/root/usr/local/bin -cp yggdrasilctl pkgbuild/root/usr/local/bin -cp contrib/macos/yggdrasil.plist pkgbuild/root/Library/LaunchDaemons +cp mesh pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS +cp meshctl pkgbuild/root/usr/local/bin +cp contrib/macos/mesh.plist pkgbuild/root/Library/LaunchDaemons # Create the postinstall script cat > pkgbuild/scripts/postinstall << EOF #!/bin/sh # Normalise the config if it exists, generate it if it doesn't -if [ -f /etc/yggdrasil.conf ]; +if [ -f /etc/mesh.conf ]; then - mkdir -p /Library/Preferences/Yggdrasil - echo "Backing up configuration file to /Library/Preferences/Yggdrasil/yggdrasil.conf.`date +%Y%m%d`" - cp /etc/yggdrasil.conf /Library/Preferences/Yggdrasil/yggdrasil.conf.`date +%Y%m%d` - echo "Normalising /etc/yggdrasil.conf" - /usr/local/bin/yggdrasil -useconffile /Library/Preferences/Yggdrasil/yggdrasil.conf.`date +%Y%m%d` -normaliseconf > /etc/yggdrasil.conf + mkdir -p /Library/Preferences/RiV-mesh + echo "Backing up configuration file to /Library/Preferences/RiV-mesh/mesh.conf.`date +%Y%m%d`" + cp /etc/mesh.conf /Library/Preferences/RiV-mesh/mesh.conf.`date +%Y%m%d` + echo "Normalising /etc/mesh.conf" + /Applications/RiV-mesh.app/Contents/MacOS/mesh -useconffile /Library/Preferences/RiV-mesh/mesh.conf.`date +%Y%m%d` -normaliseconf > /etc/mesh.conf else - /usr/local/bin/yggdrasil -genconf > /etc/yggdrasil.conf + /Applications/RiV-mesh.app/Contents/MacOS/mesh -genconf > /etc/mesh.conf fi -# Unload existing Yggdrasil launchd service, if possible -test -f /Library/LaunchDaemons/yggdrasil.plist && (launchctl unload /Library/LaunchDaemons/yggdrasil.plist || true) +chmod 755 /etc/mesh.conf -# Load Yggdrasil launchd service and start Yggdrasil -launchctl load /Library/LaunchDaemons/yggdrasil.plist +# Unload existing RiV-mesh launchd service, if possible +test -f /Library/LaunchDaemons/mesh.plist && (launchctl unload /Library/LaunchDaemons/mesh.plist || true) + +# Load RiV-mesh launchd service and start RiV-mesh +launchctl load /Library/LaunchDaemons/mesh.plist EOF # Set execution permissions -chmod +x pkgbuild/scripts/postinstall -chmod +x pkgbuild/root/usr/local/bin/yggdrasil -chmod +x pkgbuild/root/usr/local/bin/yggdrasilctl +chmod 755 pkgbuild/scripts/postinstall +chmod 755 pkgbuild/root/Applications/RiV-mesh.app/Contents/MacOS/mesh +chmod 755 pkgbuild/root/usr/local/bin/meshctl # Pack payload and scripts ( cd pkgbuild/scripts && find . | cpio -o --format odc --owner 0:80 | gzip -c ) > pkgbuild/flat/base.pkg/Scripts @@ -79,11 +78,10 @@ PKGNAME=$(sh contrib/semver/name.sh) PKGVERSION=$(sh contrib/semver/version.sh --bare) PKGARCH=${PKGARCH-amd64} PAYLOADSIZE=$(( $(wc -c pkgbuild/flat/base.pkg/Payload | awk '{ print $1 }') / 1024 )) -[ "$PKGARCH" = "amd64" ] && PKGHOSTARCH="x86_64" || PKGHOSTARCH=${PKGARCH} # Create the PackageInfo file cat > pkgbuild/flat/base.pkg/PackageInfo << EOF - + @@ -98,15 +96,15 @@ EOF cat > pkgbuild/flat/Distribution << EOF - Yggdrasil (${PKGNAME}-${PKGVERSION}) - + RiV-mesh (${PKGNAME}-${PKGVERSION}) + + + + + +
+
+ +
+ + + + +
+ +
+
+
IPv6
+
N/A
+
+ +
+
+ +
+
Subnet
+
N/A
+
+ +
+
+ +
+ +
Peers
+
+ +
+
+ +
+ +
+ +
+
+ + + + +
+ + +
+ +
+ + + + + diff --git a/contrib/ui/mesh-ui/webview.go b/contrib/ui/mesh-ui/webview.go new file mode 100755 index 00000000..80744d75 --- /dev/null +++ b/contrib/ui/mesh-ui/webview.go @@ -0,0 +1,266 @@ +package main + +import ( + "github.com/webview/webview" + "github.com/hjson/hjson-go" + "encoding/json" + "path/filepath" + "io/ioutil" + "os/exec" + "net/url" + "runtime" + "strings" + "strconv" + "time" + "net" + "log" + "fmt" + "os" + + "github.com/RiV-chain/RiV-mesh/src/admin" +) + +var riv_ctrl_path string + +func main() { + debug := true + w := webview.New(debug) + defer w.Destroy() + w.SetTitle("RiV-mesh") + w.SetSize(690, 920, webview.HintFixed) + /*1. Create ~/.riv-mesh folder if not existing + *2. Create ~/.riv-mesh/mesh.conf if not existing + *3. If the file exists read Peers. + *3.1 Invoke add peers for each record + */ + mesh_folder := ".riv-mesh" + mesh_conf := "mesh.conf" + user_home := get_user_home_path() + mesh_settings_folder := filepath.Join(user_home, mesh_folder) + err := os.MkdirAll(mesh_settings_folder, os.ModePerm) + if err != nil { + fmt.Printf("Unable to create folder: %v", err) + } + mesh_settings_path := filepath.Join(user_home, mesh_folder, mesh_conf) + riv_ctrl_path = get_ctl_path() + if _, err := os.Stat(mesh_settings_path); os.IsNotExist(err) { + err := ioutil.WriteFile(mesh_settings_path, []byte(""), 0750) + if err != nil { + fmt.Printf("Unable to write file: %v", err) + } + } else { + //read peers from mesh.conf + conf, _ := ioutil.ReadFile(mesh_settings_path) + var dat map[string]interface {} + if err := hjson.Unmarshal(conf, &dat); err != nil { + fmt.Printf("Unable to parse mesh.conf file: %v", err) + } else { + if dat["Peers"]!=nil { + peers := dat["Peers"].([]interface{}) + remove_peers() + for _, u := range peers { + log.Printf("Unmarshaled: %v", u.(string)) + add_peers(u.(string)) + } + } else { + fmt.Printf("Warning: Peers array not loaded from mesh.conf file") + } + } + } + var path string + + if len(os.Args)>1 { + path, err = filepath.Abs(filepath.Dir(os.Args[1])) + } else { + path, err = filepath.Abs(filepath.Dir(os.Args[0])) + } + if err != nil { + log.Fatal(err) + } + + log.Println(path) + w.Bind("onLoad", func() { + log.Println("page loaded") + go run(w) + }) + w.Bind("savePeers", func(peer_list string) { + //log.Println("peers saved ", peer_list) + var peers []string + _ = json.Unmarshal([]byte(peer_list), &peers) + log.Printf("Unmarshaled: %v", peers) + remove_peers() + for _, u := range peers { + log.Printf("Unmarshaled: %v", u) + add_peers(u) + } + //add peers to ~/mesh.conf + dat := make(map[string]interface{}) + dat["Peers"] = peers + bs, _ := hjson.Marshal(dat) + e := ioutil.WriteFile(mesh_settings_path, bs, 0750) + if e != nil { + fmt.Printf("Unable to write file: %v", e) + } + }) + w.Bind("ping", func(peer_list string) { + go ping(w, peer_list) + }) + dat, err := ioutil.ReadFile(path+"/index.html") + w.Navigate("data:text/html,"+url.QueryEscape(string(dat))) + //w.Navigate("data:text/html,"+""+path+"") + w.Run() +} + +func ping(w webview.WebView, peer_list string){ + var peers []string + _ = json.Unmarshal([]byte(peer_list), &peers) + log.Printf("Unmarshaled: %v", peers) + for _, u := range peers { + log.Printf("Unmarshaled: %v", u) + ping_time := check(u); + log.Printf("ping: %d", ping_time) + setPingValue(w, u, strconv.FormatInt(ping_time, 10)); + } +} + +func check(peer string) int64 { + u, e := url.Parse(peer) + if e!=nil { + return -1 + } + t := time.Now() + _, err := net.DialTimeout("tcp", u.Host, 5*time.Second) + if err!=nil { + return -1 + } + d := time.Since(t) + return d.Milliseconds() +} + +func get_user_home_path() string { + if runtime.GOOS == "windows" { + path, exists := os.LookupEnv("USERPROFILE") + if exists { + return path + } else { + return "" + } + } else { + path, exists := os.LookupEnv("HOME") + if exists { + return path + } else { + return "" + } + } +} + +func get_ctl_path() string{ + if runtime.GOOS == "windows" { + program_path := "programfiles" + path, exists := os.LookupEnv(program_path) + if exists { + fmt.Println("Program path: %s", path) + ctl_path := fmt.Sprintf("%s\\RiV-mesh\\meshctl.exe", path) + return ctl_path + } else { + fmt.Println("could not find Program Files path") + return "" + } + } else { + ctl_path := fmt.Sprintf("/usr/local/bin/meshctl") + return ctl_path + } +} + +func run(w webview.WebView){ + if len(riv_ctrl_path) > 0 { + get_self(w) + get_peers(w) + } + _ = time.AfterFunc(10*time.Second, func() { + run(w) + }) +} + +func run_command(command string) []byte{ + args := []string{"-json", command} + cmd := exec.Command(riv_ctrl_path, args...) + out, err := cmd.CombinedOutput() + if err != nil { + //log.Fatalf("cmd.Run() failed with %s\n", err) + return []byte(err.Error()) + } + return out +} + +func run_command_with_arg(command string, arg string) []byte{ + args := []string{"-json", command, arg} + cmd := exec.Command(riv_ctrl_path, args...) + out, err := cmd.CombinedOutput() + if err != nil { + //log.Fatalf("command failed: %s\n", riv_ctrl_path+" "+strings.Join(args, " ")) + return []byte(err.Error()) + } + return out +} + +func add_peers(uri string){ + run_command_with_arg("addpeers", "uri="+uri) +} + +func remove_peers(){ + run_command("removepeers") +} + +func get_self(w webview.WebView){ + + res := &admin.GetSelfResponse{} + out := run_command("getSelf") + if err := json.Unmarshal(out, &res); err != nil { + go setFieldValue(w, "ipv6", err.Error()) + return + } + //found ipv6 + fmt.Printf("IPv6: %s\n", res.IPAddress) + go setFieldValue(w, "ipv6", res.IPAddress) + //found subnet + fmt.Printf("Subnet: %s\n", res.Subnet) + go setFieldValue(w, "subnet", res.Subnet) + out = run_command("getPeers") + //go setFieldValue(w, "peers", string(out)) +} + +func get_peers(w webview.WebView){ + + res := &admin.GetPeersResponse{} + out := run_command("getPeers") + if err := json.Unmarshal(out, &res); err != nil { + go setFieldValue(w, "peers", err.Error()) + return + } + + var m []string + for _, s := range res.Peers { + m=append(m, s.Remote) + } + for k := range m { + // Loop + fmt.Println(k) + } + inner_html := strings.Join(m[:], "
") + strings.Join(m[:], "
") + go setFieldValue(w, "peers", inner_html) +} + +func setFieldValue(p webview.WebView, id string, value string) { + p.Dispatch(func() { + p.Eval("setFieldValue('"+id+"','"+value+"');") + }) +} + +func setPingValue(p webview.WebView, peer string, value string) { + p.Dispatch(func() { + p.Eval("setPingValue('"+peer+"','"+value+"');") + }) +} diff --git a/contrib/ui/nas-asustor/CONTROL/description.txt b/contrib/ui/nas-asustor/CONTROL/description.txt new file mode 100644 index 00000000..71124ae0 --- /dev/null +++ b/contrib/ui/nas-asustor/CONTROL/description.txt @@ -0,0 +1,4 @@ +RiV-mesh is an implementation of a fully end-to-end encrypted IPv6 network. +It is lightweight, self-arranging, supported on multiple platforms and +allows pretty much any IPv6-capable application to communicate securely with +other RiV-mesh nodes. diff --git a/contrib/ui/nas-asustor/CONTROL/start-stop.sh b/contrib/ui/nas-asustor/CONTROL/start-stop.sh new file mode 100644 index 00000000..4f883d27 --- /dev/null +++ b/contrib/ui/nas-asustor/CONTROL/start-stop.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +BASE="/usr/local/AppCentral/mesh-nas-asustor" +CONFIG_DIR="/usr/local/etc" + +MESH_PACKAGE_LOG=/tmp/mesh.log +echo "start-stop called" >> "$MESH_PACKAGE_LOG" + +exec 2>>$MESH_PACKAGE_LOG +set -x + +whoami + +init () +{ + config_file=${CONFIG_DIR}/mesh.conf + if [ ! -f "$CONFIG_DIR" ]; then + mkdir -p ${CONFIG_DIR} + fi + + if [ -f $config_file ]; then + mkdir -p /var/backups + echo "Backing up configuration file to /var/backups/mesh.conf.`date +%Y%m%d`" + cp $config_file /var/backups/mesh.conf.`date +%Y%m%d` + echo "Normalising and updating /etc/mesh.conf" + ${BASE}/bin/mesh -useconf -normaliseconf < /var/backups/mesh.conf.`date +%Y%m%d` > $config_file + else + echo "Generating initial configuration file $config_file" + echo "Please familiarise yourself with this file before starting RiV-mesh" + sh -c "umask 0027 && ${BASE}/bin/mesh -genconf > '$config_file'" + fi + + #chown -R admin:administrators $config_file + #chmod -R 664 $config_file + #sudo insmod /lib/modules/5.4.x/tun.ko + # Create the necessary file structure for /dev/net/tun + if ( [ ! -c /dev/net/tun ] ); then + if ( [ ! -d /dev/net ] ); then + mkdir -m 755 /dev/net + fi + mknod /dev/net/tun c 10 200 + chmod 0755 /dev/net/tun + fi + + # Load the tun module if not already loaded + if ( !(lsmod | grep -q "^tun\s") ); then + insmod /lib/modules/5.4.x/tun.ko + fi +} + +start_service () +{ + init + + # Launch the mesh in the background. + ${BASE}/bin/mesh -useconffile "$config_file" \ + -httpaddress "http://0.0.0.0:19019" \ + -wwwroot "$BASE/www" \ + -logto "$BASE/var/log/mesh.log" & + return $? +} + +stop_service () +{ + pid=`pidof -s mesh` + if [ -z "$pid" ]; then + echo "mesh was not running" + exit 0 + fi + kill "$pid" +} + +case $1 in + start) + start_service + echo "Running RiV Mesh" + exit 0 + ;; + stop) + stop_service + echo "Stopped RiV Mesh" + exit 0 + ;; + *) + exit 1 + ;; +esac diff --git a/contrib/ui/nas-asustor/var/lib/mesh/deviceinfo b/contrib/ui/nas-asustor/var/lib/mesh/deviceinfo new file mode 100644 index 00000000..81f5b3cd --- /dev/null +++ b/contrib/ui/nas-asustor/var/lib/mesh/deviceinfo @@ -0,0 +1,6 @@ +#!/bin/sh +echo vendor=Asustor +echo vendorOperatingSystemName=ADM +eval $(cat /etc/default/nas.conf | grep '\\|\' | sed 's/ //g') +echo firmwareVersion="$Version" +echo model=$Model diff --git a/contrib/ui/nas-asustor/var/lib/mesh/webauth b/contrib/ui/nas-asustor/var/lib/mesh/webauth new file mode 100644 index 00000000..1d1bc249 --- /dev/null +++ b/contrib/ui/nas-asustor/var/lib/mesh/webauth @@ -0,0 +1,76 @@ +#!/bin/sh +#exit with zero status on auth success and 1 on error +# +#You can use our cgi to restrict access to RiV Mesh configuration page only for authenticated NAS OS users. +#========================== +#1. use login to verify authenticated NAS OS user +# +#for example: +# +#root@AS6208T-RD:/ # REMOTE_ADDR="127.0.0.1" QUERY_STRING="act=login&apptag=mesh&account=admin&password=admin888" /usr/webman/portal/apis/appCentral/applogin.cgi +#Content-type: text/plain; charset=utf-8 +# +#result: +#{ "success": true, "account": "admin", "sid": "yPgoWu95eXxCxZJr", "isAdminGroup": 1, "model": "AS6208T", "hostid": "20-16-01-21-14-01" } +# +#explanation: +#apptag: application name +#account&password: which you want to verify +# +#2. When you finish verifying authenticated NAS OS user, you must logout from NAS. +# +#for example: +# +#root@AS6208T-RD:/ # QUERY_STRING="act=logout&sid=yPgoWu95eXxCxZJr" /usr/webman/portal/apis/login.cgi +#Content-type: text/plain; charset=utf-8 +# +#result +#{ "success": true } +# +#explanation: +#sid: same as above (login result) + + + +CACHE="/usr/local/AppCentral/mesh/var/lib/mesh/access_key" +if [ -f $CACHE ] && [ "$(expr $(date +%s) - $(date -r $CACHE +%s))" -lt 3600 ]; then + exit 0 +fi + +#we want read e.g.: +#HTTP_COOKIE='access_key=sdu45KJFDHksadulf=' +IFS=';' +for x in $HTTP_COOKIE +do + eval $x +done +#we want get e.g.: +#access_key='user=admin;pwd=L4edNyoCC15.kDBLIN05480' +access_key=$(echo $access_key | base64 -d) + +CACHE="/usr/local/AppCentral/mesh/var/lib/mesh/$access_key" +if [ -f $CACHE ] && [ "$(expr $(date +%s) - $(date -r $CACHE +%s))" -lt 3600 ]; then + exit 0 +fi + +IFS=';' +for x in $access_key +do + eval $x +done + +if [ -z "${user}" ] || [ -z "${pwd}" ]; then + exit 1 +fi + +export REMOTE_ADDR="127.0.0.1" +export QUERY_STRING="act=login&apptag=mesh&account=${user}&password=${pwd}" +S=$(/usr/webman/portal/apis/appCentral/applogin.cgi | sed '/"sid"/!d; s/\s\+//g; s/.*"sid":"\([^"]*\)".*/\1/') +if [ -z $S ]; then + exit 1 +else + export QUERY_STRING="act=logout&sid=$S" + /usr/webman/portal/apis/login.cgi >/dev/null + touch $CACHE + exit 0 +fi diff --git a/contrib/ui/nas-asustor/www/assets/partner-logo.png b/contrib/ui/nas-asustor/www/assets/partner-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..eb478e11ec904321bdec4bf62a3dffc30b3ac102 GIT binary patch literal 16205 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 literal 0 HcmV?d00001 diff --git a/contrib/ui/nas-asustor/www/assets/properties.js b/contrib/ui/nas-asustor/www/assets/properties.js new file mode 100644 index 00000000..d7af016c --- /dev/null +++ b/contrib/ui/nas-asustor/www/assets/properties.js @@ -0,0 +1,35 @@ +var ed = { + partnerId: 1422, + applicationName: 'RiV Mesh Asustor ADM App', + nasOSName: 'Asustor ADM', + useAuthNASRichScreen: true, + nasVisitEDWebsiteLogin: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteSignup: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteLoggedin: "https://github.com/RiV-chain/RiV-mesh", + getNasAuthUrl: function () { + return "/"; + }, + nasLoginCall: function (nasLoginSuccess, nasLoginFailure) { + var d = new Date(); + d.setTime(d.getTime() + (10 * 60 * 1000)); + document.cookie = "access_key=" + btoa( "user=" + encodeURIComponent($('#nasInputUser').val()) + ";pwd=" + encodeURIComponent($('#nasInputPassword').val()))+ "; expires=" + d.toUTCString() + "; path=/"; + $.ajax({url: "api/getself"}).done(function () { + window.location.reload(); + }).fail(function () { + ed.nasLogoutCall(); + nasLoginFailure(); + }); + }, + nasLogoutCall: function () { + document.cookie = "access_key=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/"; + }, + getNasUser: function() { + function getCookie(name) { + var matches = document.cookie.match(new RegExp( + "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" + )); + return matches ? decodeURIComponent(matches[1]) : undefined; + } + return decodeURIComponent(atob(getCookie('access_key')).split(';')[0].split('=')[1]); + } +}; diff --git a/contrib/ui/nas-drobo/Content/install.sh b/contrib/ui/nas-drobo/Content/install.sh new file mode 100644 index 00000000..31c1fde3 --- /dev/null +++ b/contrib/ui/nas-drobo/Content/install.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +. $(dirname $0)/scripts.sh +_install diff --git a/contrib/ui/nas-drobo/Content/mesh.conf b/contrib/ui/nas-drobo/Content/mesh.conf new file mode 100644 index 00000000..8b2ed5c6 --- /dev/null +++ b/contrib/ui/nas-drobo/Content/mesh.conf @@ -0,0 +1,20 @@ +RedirectMatch 301 ^/mesh$ /mesh/ +LoadModule proxy_http_module modules/mod_proxy_http.so + + + + AuthType Form + AuthName "DroboApps" + AuthUserFile /tmp/DroboApps/apache/htpasswd + AuthFormProvider file + ErrorDocument 401 /login/index.html + Session On + SessionCookieName session path=/ + SessionCryptoPassphrase "exec:/mnt/DroboFS/Shares/DroboApps/apache/libexec/cookie.sh" + Require valid-user + + ProxyPreserveHost On + + ProxyPass "http://127.0.0.1:19019/" + ProxyPassReverse "http://127.0.0.1:19019/" + diff --git a/contrib/ui/nas-drobo/Content/scripts.sh b/contrib/ui/nas-drobo/Content/scripts.sh new file mode 100644 index 00000000..6ae96e13 --- /dev/null +++ b/contrib/ui/nas-drobo/Content/scripts.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env sh + +tmpdir="/tmp/DroboApps/mesh" +errorfile="${tmpdir}/error.txt" +base_dir="/mnt/DroboFS/Shares/DroboApps/mesh" +config_dir="$base_dir/config" +config_file="$config_dir/mesh.conf" +prog_dir="$(dirname "$(realpath "${0}")")" + + +_install() { + if [ ! -f "${errorfile}" ] + then + mkdir -p "${tmpdir}" + if [ ! -f "$config_file" ]; then + echo 3 > "${errorfile}" + fi + fi + ln -s $base_dir/var/log/mesh.log $base_dir/www/log + # install apache 2.x + /usr/bin/DroboApps.sh install_version apache 2 +} + +_uninstall() { + pid=`pidof -s mesh` + if [ -z "$pid" ]; then + echo "mesh was not running" + else + kill "$pid" + fi +} + +_update() { + /bin/sh "${prog_dir}/service.sh" stop + + cd "$base_dir" + rm -rf $(ls | grep -v 'host_uid.txt\|var\|config') + + echo 'update successful' > "${prog_dir}/update.log" +} diff --git a/contrib/ui/nas-drobo/Content/service.sh b/contrib/ui/nas-drobo/Content/service.sh new file mode 100644 index 00000000..74b90520 --- /dev/null +++ b/contrib/ui/nas-drobo/Content/service.sh @@ -0,0 +1,121 @@ +#!/bin/sh +# + +##!! +. /etc/service.subr + +prog_dir=`dirname \`realpath $0\`` +base_dir=/mnt/DroboFS/Shares/DroboApps/mesh +config_dir="$base_dir/config" +config_file="$config_dir/mesh.conf" + +name="mesh" +framework_version="2.1" +description="RiV-mesh is an implementation of a fully end-to-end encrypted IPv6 network" +depends="" +webui="WebUI" + +errorfile=/tmp/DroboApps/mesh/error.txt +pidfile=/tmp/DroboApps/mesh/pid.txt +statusfile=/tmp/DroboApps/mesh/status.txt +edstatusfile=$base_dir/var/lib/mesh/status + +start() +{ + mkdir -p /tmp/DroboApps/mesh + # delete edstatufile before starting daemon to delete previous status + rm -f $edstatusfile + rm -f $errorfile + + if [ -f $config_file ]; then + mkdir -p /var/backups + echo "Backing up configuration file to /var/backups/mesh.conf.`date +%Y%m%d`" + cp $config_file /var/backups/mesh.conf.`date +%Y%m%d` + echo "Normalising and updating /etc/mesh.conf" + $base_dir/bin/mesh -useconf -normaliseconf < /var/backups/mesh.conf.`date +%Y%m%d` > $config_file + else + mkdir -p $config_dir + echo "Generating initial configuration file $config_file" + echo "Please familiarise yourself with this file before starting RiV-mesh" + sh -c "umask 0027 && $base_dir/bin/mesh -genconf > '$config_file'" + fi + + # Create the necessary file structure for /dev/net/tun + if ( [ ! -c /dev/net/tun ] ); then + if ( [ ! -d /dev/net ] ); then + mkdir -m 755 /dev/net + fi + mknod /dev/net/tun c 10 200 + chmod 0755 /dev/net/tun + fi + + # Load the tun module if not already loaded + if ( !(lsmod | grep -q "^tun\s") ); then + KERNEL_VERSION=$(/bin/uname -r) + insmod $base_dir/lib/modules/$KERNEL_VERSION/tun.ko + fi + + # Launch the mesh in the background. + ${base_dir}/bin/mesh -useconffile "$config_file" \ + -httpaddress "http://localhost:19019" \ + -wwwroot "$base_dir/www" \ + -logto "$base_dir/var/log/mesh.log" & + + sleep 1 + update_status +} + +update_status() +{ + + # wait until file appears + i=30 + + while [ -z $(pidof -s mesh) ] + do + sleep 1 + i=$((i-1)) + + if [ $i -eq 0 ] + then + break + fi + done + + # if we don't have file here. throw error into status and return + if [ -z $(pidof -s mesh) ] + then + echo "" > "$pidfile" + echo 1 > "${errorfile}" + echo "Configuration required" > $statusfile + else + echo $(pidof -s mesh) > "$pidfile" + echo 0 > "${errorfile}" + echo "Application is running" > $statusfile + fi + +} + +stop() +{ + pid=`pidof -s mesh` + if [ -z "$pid" ]; then + echo 1 > "${errorfile}" + echo "mesh was not running" > $statusfile + else + kill "$pid" + echo 0 > "${errorfile}" + echo "Application is stopped" > $statusfile + fi + echo "" > "$pidfile" + +} + +case "$1" in + update_status) + update_status + exit $? + ;; +esac + +main "$@" diff --git a/contrib/ui/nas-drobo/Content/uninstall.sh b/contrib/ui/nas-drobo/Content/uninstall.sh new file mode 100644 index 00000000..a0889ee2 --- /dev/null +++ b/contrib/ui/nas-drobo/Content/uninstall.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +# +. $(dirname $0)/scripts.sh +_uninstall diff --git a/contrib/ui/nas-drobo/Content/update.sh b/contrib/ui/nas-drobo/Content/update.sh new file mode 100644 index 00000000..5b4a3d43 --- /dev/null +++ b/contrib/ui/nas-drobo/Content/update.sh @@ -0,0 +1,3 @@ +#!/bin/sh +. $(dirname $0)/scripts.sh +_update diff --git a/contrib/ui/nas-drobo/Content/var/lib/mesh/hooks/deviceinfo b/contrib/ui/nas-drobo/Content/var/lib/mesh/hooks/deviceinfo new file mode 100644 index 00000000..bf591753 --- /dev/null +++ b/contrib/ui/nas-drobo/Content/var/lib/mesh/hooks/deviceinfo @@ -0,0 +1,16 @@ +#!/bin/sh +echo vendor=Drobo + +# get device model, e.g., "5N" +_get_device_model() { + for f in /sys/devices/dri_dnas_primary/dnas_adp_1/host*/target*/*:*:*:*/model; do + if [ -e "$f" ]; then + cat "$f" + return + fi + done +} + +echo serial=$(cat /mnt/DroboFS/Shares/DroboApps/mesh/host_uid.txt) +echo firmwareVersion=$(/usr/bin/esa vxver) +echo model=$(_get_device_model) diff --git a/contrib/ui/nas-drobo/Content/www/assets/partner-logo.png b/contrib/ui/nas-drobo/Content/www/assets/partner-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4df18638e201fbc8487fa33cc4e6794d723aff6d GIT binary patch literal 5568 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 O0000 +Depends: lsb-base, debconf, readynasos (>= 6.0.5~T1271) +Section: net +Priority: optional +Installed-Size: 20000 +Homepage: https://github.com/RiV-chain/RiV-mesh +Description: RiV-mesh is an implementation of a fully end-to-end encrypted IPv6 network diff --git a/contrib/ui/nas-netgear-os6/package/DEBIAN/postinst b/contrib/ui/nas-netgear-os6/package/DEBIAN/postinst new file mode 100755 index 00000000..37ab51c3 --- /dev/null +++ b/contrib/ui/nas-netgear-os6/package/DEBIAN/postinst @@ -0,0 +1,61 @@ +#!/bin/sh +# postinst script for mesh +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + chown -R admin:admin /apps/mesh + if systemctl restart apache2.service; then + # success + event_push app meshd '' 0 0 + else + # error + event_push app meshd '' 0 0 + fi + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +if [ -f /etc/mesh.conf ]; then + mkdir -p /var/backups + echo "Backing up configuration file to /var/backups/mesh.conf.`date +%Y%m%d`" + cp /etc/mesh.conf /var/backups/mesh.conf.`date +%Y%m%d` + echo "Normalising and updating /etc/mesh.conf" + /apps/mesh/bin/mesh -useconf -normaliseconf < /var/backups/mesh.conf.`date +%Y%m%d` > /etc/mesh.conf +else + echo "Generating initial configuration file /etc/mesh.conf" + echo "Please familiarise yourself with this file before starting RiV-mesh" + sh -c 'umask 0027 && /apps/mesh/bin/mesh -genconf > /etc/mesh.conf' +fi + +chmod 755 /etc/mesh.conf +if command -v systemctl >/dev/null; then + systemctl daemon-reload || echo -n "daemon not reloaded!" + systemctl enable mesh || echo -n "systemctl enable failed!" + systemctl restart mesh || echo -n "systemctl restart failed!" +fi + +exit 0 diff --git a/contrib/ui/nas-netgear-os6/package/DEBIAN/postrm b/contrib/ui/nas-netgear-os6/package/DEBIAN/postrm new file mode 100755 index 00000000..44d7e218 --- /dev/null +++ b/contrib/ui/nas-netgear-os6/package/DEBIAN/postrm @@ -0,0 +1,32 @@ +#! /bin/sh +# postrm script for mesh +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' overwrit>r> +# for details, see /usr/share/doc/packaging-manual/ + +case "$1" in + purge) + rm -rf /apps/mesh + systemctl restart apache2.service + event_push app meshd '' 0 0 + ;; + remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 0 + +esac diff --git a/contrib/ui/nas-netgear-os6/package/DEBIAN/prerm b/contrib/ui/nas-netgear-os6/package/DEBIAN/prerm new file mode 100755 index 00000000..64acb80d --- /dev/null +++ b/contrib/ui/nas-netgear-os6/package/DEBIAN/prerm @@ -0,0 +1,32 @@ +#! /bin/sh +# prerm script for mesh +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see /usr/share/doc/packaging-manual/ + +case "$1" in + remove|upgrade|deconfigure) + systemctl stop fvapp-mesh.service || true + systemctl disable fvapp-mesh.service || true + ;; + failed-upgrade) + ;; + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 0 + ;; +esac + + +exit 0 diff --git a/contrib/ui/nas-netgear-os6/package/apps/mesh/fvapp-mesh.service b/contrib/ui/nas-netgear-os6/package/apps/mesh/fvapp-mesh.service new file mode 100755 index 00000000..08c3bb9b --- /dev/null +++ b/contrib/ui/nas-netgear-os6/package/apps/mesh/fvapp-mesh.service @@ -0,0 +1,19 @@ +[Unit] +Description=RiV-mesh is an early-stage implementation of a fully end-to-end encrypted IPv6 network + +[Service] +Type=idle +Group=admin +ProtectHome=true +ProtectSystem=true +SyslogIdentifier=mesh +CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE +ExecStartPre=+-/sbin/modprobe tun +ExecStart=/apps/mesh/bin/mesh -useconffile /etc/mesh.conf -httpaddress http://localhost:19019 -wwwroot /apps/mesh/www -logto /apps/mesh/var/log/mesh.log +ExecStop=/bin/kill -HUP $MAINPID +KillMode=process +Restart=on-failure +TimeoutStopSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/contrib/ui/nas-netgear-os6/package/apps/mesh/https.conf b/contrib/ui/nas-netgear-os6/package/apps/mesh/https.conf new file mode 100755 index 00000000..5538c07e --- /dev/null +++ b/contrib/ui/nas-netgear-os6/package/apps/mesh/https.conf @@ -0,0 +1,12 @@ +RewriteEngine on +RewriteRule "(.*)/apps/mesh$" "$1/apps/mesh/" [R=301,L] +LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so +LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so + + + Include "/etc/frontview/apache/Admin_Auth.conf" + SSLRequireSSL + ProxyPreserveHost On + ProxyPass "http://127.0.0.1:19019/" + ProxyPassReverse "http://127.0.0.1:19019/" + diff --git a/contrib/ui/nas-netgear-os6/package/apps/mesh/var/lib/mesh/hooks/deviceinfo b/contrib/ui/nas-netgear-os6/package/apps/mesh/var/lib/mesh/hooks/deviceinfo new file mode 100755 index 00000000..93d2bcac --- /dev/null +++ b/contrib/ui/nas-netgear-os6/package/apps/mesh/var/lib/mesh/hooks/deviceinfo @@ -0,0 +1,10 @@ +#!/bin/sh + +get_info() { + rn_nml -g systeminfo | tr '\n' ' ' | sed -r "s|.*<$1>(.*).*|\1|" +} +echo vendor=Netgear +echo vendorOperatingSystemName="$(get_info Firmware_Name)" +echo firmwareVersion="$(get_info Firmware_Version)" +echo model="$(get_info Model)" +echo serial="$(get_info Serial)" diff --git a/contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/partner-logo.png b/contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/partner-logo.png new file mode 100755 index 0000000000000000000000000000000000000000..e64c371bf461b50979a345269b21d3b059a98cb0 GIT binary patch literal 6708 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 Dluj1Z literal 0 HcmV?d00001 diff --git a/contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/partner.css b/contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/partner.css new file mode 100755 index 00000000..9166c5e0 --- /dev/null +++ b/contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/partner.css @@ -0,0 +1,9 @@ +.nas-apps-config-form-app-logo { + height: 110px; + background: url(logo.png) left center no-repeat; + background-size: 262px 56px; +} + +a { + color: #692782!important; +} diff --git a/contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/properties.js b/contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/properties.js new file mode 100755 index 00000000..ee7a884b --- /dev/null +++ b/contrib/ui/nas-netgear-os6/package/apps/mesh/www/assets/properties.js @@ -0,0 +1,10 @@ +var ed = { + partnerId: 252, + applicationName: 'RiV-Mesh App', + nasOSName: 'Ready NAS OS 6', + vaultUrl: "https://github.com/RiV-chain/RiV-mesh", + basicEDWebsite: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteLogin: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteSignup: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteLoggedin: "https://github.com/RiV-chain/RiV-mesh" +}; diff --git a/contrib/ui/nas-qnap/au/apache-mesh.conf b/contrib/ui/nas-qnap/au/apache-mesh.conf new file mode 100644 index 00000000..c7a70f39 --- /dev/null +++ b/contrib/ui/nas-qnap/au/apache-mesh.conf @@ -0,0 +1,8 @@ +RedirectMatch 301 ^/mesh$ /mesh/ +LoadModule proxy_http_module modules/mod_proxy_http.so + + + ProxyPreserveHost On + ProxyPass "http://127.0.0.1:19019/" + ProxyPassReverse "http://127.0.0.1:19019/" + diff --git a/contrib/ui/nas-qnap/au/var/lib/mesh/hooks/deviceinfo b/contrib/ui/nas-qnap/au/var/lib/mesh/hooks/deviceinfo new file mode 100644 index 00000000..b4e73251 --- /dev/null +++ b/contrib/ui/nas-qnap/au/var/lib/mesh/hooks/deviceinfo @@ -0,0 +1,7 @@ +#!/bin/sh +CFG=/etc/default_config/uLinux.conf +echo vendor=QNAP +echo vendorOperatingSystemName=$(/sbin/getcfg System OS -f $CFG) +echo firmwareVersion=$(/sbin/getcfg System Version -f $CFG) +echo model=$(/sbin/getcfg System Model -f $CFG) +echo serial=$(/sbin/get_hwsn) diff --git a/contrib/ui/nas-qnap/au/var/lib/mesh/hooks/webauth b/contrib/ui/nas-qnap/au/var/lib/mesh/hooks/webauth new file mode 100644 index 00000000..8948b523 --- /dev/null +++ b/contrib/ui/nas-qnap/au/var/lib/mesh/hooks/webauth @@ -0,0 +1,31 @@ +#!/bin/sh +#we want read: +#export HTTP_COOKIE='qnapuser=admin; qnappwd=L4edNyoCC15.kDBLIN05480' + +IFS=';' +for x in $HTTP_COOKIE +do + eval $x +done +[ -z ${qnapuser} ] && exit 1 +[ -z ${qnappwd} ] && exit 1 + +#exit with zero status on auth success +#2-pass auth +S=$(curl -s -k -L "http://127.0.0.1:58080/cgi-bin/authLogin.cgi?user=${qnapuser}&pwd=${qnappwd}" | tr -d '\040\011\012\015' | grep -F '') +[ ! 0 -eq ${#S} ] && exit 0 + +AUTH_PORT=$(cat /etc/apache-sys-proxy.conf | grep Listen | awk '{print $2}') +if [ -n $AUTH_PORT ] ; then + AUTH_PORT=8080 +fi + +S=$(curl -s -k -L "http://127.0.0.1:${AUTH_PORT}/cgi-bin/authLogin.cgi?user=${qnapuser}&pwd=${qnappwd}" | tr -d '\040\011\012\015' | grep -F '') +[ ! 0 -eq ${#S} ] && exit 0 + +#fallback to plain password auth +#decode password first +plain_pwd=$(openssl enc -base64 -d <<< ${qnappwd}) +[ -z $plain_pwd ] && exit 1 +S=$(curl -s -k -L "http://127.0.0.1:${AUTH_PORT}/cgi-bin/authLogin.cgi?user=${qnapuser}&plain_pwd=${plain_pwd}" | tr -d '\040\011\012\015' | grep -F '') +[ 0 -eq ${#S} ] && exit 1 || exit 0 diff --git a/contrib/ui/nas-qnap/au/var/lib/mesh/pre_upgrade.sh b/contrib/ui/nas-qnap/au/var/lib/mesh/pre_upgrade.sh new file mode 100644 index 00000000..3d71230e --- /dev/null +++ b/contrib/ui/nas-qnap/au/var/lib/mesh/pre_upgrade.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +log_exit(){ + echo $2 + exit $1 +} + +[ -z "$MESH_USER_NAME" ] && log_exit 1 "Credentials are not set. Remove aborted" + +rm "$MESH_APP_ROOT/bin/mesh +rm -rf "$MESH_APP_ROOT/www" + diff --git a/contrib/ui/nas-qnap/au/www/assets/get_sid.js b/contrib/ui/nas-qnap/au/www/assets/get_sid.js new file mode 100644 index 00000000..d57b0dc7 --- /dev/null +++ b/contrib/ui/nas-qnap/au/www/assets/get_sid.js @@ -0,0 +1,102 @@ +/* encode function start */ +var ezEncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +var ezDecodeChars = new Array( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1); + +function utf16to8(str) +{ + var out, i, len, c; + out = ""; + len = str.length; + for (i=0; i= 0x0001) && (c <= 0x007F)) { + out += str.charAt(i); + } + else if (c > 0x07FF) { + out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); + out += String.fromCharCode(0x80 | ((c >>6) & 0x3F)); + out += String.fromCharCode(0x80 | ((c >>0) & 0x3F)); + + } + else { + out += String.fromCharCode(0xC0 | ((c >>6) & 0x1F)); + out += String.fromCharCode(0x80 | ((c >>0) & 0x3F)); + } + } + return out; +} +function utf8to16(str) { + var out, i, len, c; + var char2, char3; + + out = ""; + len = str.length; + i = 0; + while(i < len) { + c = str.charCodeAt(i++); + switch(c >> 4) + { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + // 0xxxxxxx + out += str.charAt(i-1); + break; + case 12: case 13: + // 110x xxxx 10xx xxxx + char2 = str.charCodeAt(i++); + out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + // 1110 xxxx10xx xxxx10xx xxxx + char2 = str.charCodeAt(i++); + char3 = str.charCodeAt(i++); + out += String.fromCharCode(((c & 0x0F) << 12) | + ((char2 & 0x3F) << 6) | + ((char3 & 0x3F) << 0)); + } + } + return out; +} + +function ezEncode(str) +{ + var out, i, len; + var c1, c2, c3; + + len = str.length; + i = 0; + out = ""; + while(i < len) + { + c1 = str.charCodeAt(i++) & 0xff; + if(i == len) + { + out += ezEncodeChars.charAt(c1 >> 2); + out += ezEncodeChars.charAt((c1 & 0x3) << 4); + out += "=="; + break; + } + c2 = str.charCodeAt(i++); + if(i == len) + { + out += ezEncodeChars.charAt(c1 >> 2); + out += ezEncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); + out += ezEncodeChars.charAt((c2 & 0xF) << 2); + out += "="; + break; + } + c3 = str.charCodeAt(i++); + out += ezEncodeChars.charAt(c1 >> 2); + out += ezEncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); + out += ezEncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)); + out += ezEncodeChars.charAt(c3 & 0x3F); + } + return out; +} diff --git a/contrib/ui/nas-qnap/au/www/assets/partner-logo.png b/contrib/ui/nas-qnap/au/www/assets/partner-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0d89fb31c8f7171bbe9c75e4788ec04b82382bdc GIT binary patch literal 16278 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 0x0001) && (c <= 0x007F)) { + out += str.charAt(i); + } else if (c > 0x07FF) { + out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); + out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F)); + out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); + + } else { + out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F)); + out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); + } + } + return out; + } + + function ezEncode(str) + { + var out, i, len; + var c1, c2, c3; + + len = str.length; + i = 0; + out = ""; + while (i < len) + { + c1 = str.charCodeAt(i++) & 0xff; + if (i == len) + { + out += ezEncodeChars.charAt(c1 >> 2); + out += ezEncodeChars.charAt((c1 & 0x3) << 4); + out += "=="; + break; + } + c2 = str.charCodeAt(i++); + if (i == len) + { + out += ezEncodeChars.charAt(c1 >> 2); + out += ezEncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); + out += ezEncodeChars.charAt((c2 & 0xF) << 2); + out += "="; + break; + } + c3 = str.charCodeAt(i++); + out += ezEncodeChars.charAt(c1 >> 2); + out += ezEncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)); + out += ezEncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)); + out += ezEncodeChars.charAt(c3 & 0x3F); + } + return out; + } + + var d = new Date(); + d.setTime(d.getTime() + (30 * 60 * 1000)); + document.cookie = "qnapuser=" + encodeURIComponent($('#nasInputUser').val()) + "; expires=" + d.toUTCString() + "; path=/"; + document.cookie = "qnappwd=" + encodeURIComponent(ezEncode(utf16to8($('#nasInputPassword').val()))) + "; expires=" + d.toUTCString() + "; path=/"; + $.ajax({url: "rest/info"}).done(function (response) { + window.location.reload(); + checkError(response); + }).fail(function () { + ed.nasLogoutCall(); + nasLoginFailure(); + }); + }; + ed.nasLogoutCall = function() { + document.cookie = "qnapuser=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/"; + document.cookie = "qnappwd=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/"; + }; + function getCookie(name) { + var matches = document.cookie.match(new RegExp( + "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" + )); + return matches ? decodeURIComponent(matches[1]) : undefined; + } + ed.getNasUser = function() { + return getCookie('qnapuser'); + }; +}); diff --git a/contrib/ui/nas-qnap/package/package_routines b/contrib/ui/nas-qnap/package/package_routines new file mode 100644 index 00000000..6d767310 --- /dev/null +++ b/contrib/ui/nas-qnap/package/package_routines @@ -0,0 +1,42 @@ +#script called from qinstall.sh + +#SYS_QPKG_SERVICE_ENABLED="FALSE" +QPKG_NAME="mesh" +CONF=/etc/config/mesh.conf + +PKG_PRE_REMOVE="{ + killall -q mesh + rm -rf /share/Web/$QPKG_NAME + [ -L /var/log/mesh.log ] && rm -f /var/log/mesh.log +}" + +PKG_MAIN_REMOVE="{ + $CMD_RM -f $CONF +}" + +pkg_pre_install(){ + killall -q mesh + rm -rf /share/Web/$QPKG_NAME +} + +pkg_install(){ + exec 2>/tmp/mesh.log + set -x + if [ -f $CONF ]; then + mkdir -p /var/backups + echo "Backing up configuration file to /var/backups/mesh.conf.`date +%Y%m%d`" + cp $CONF /var/backups/mesh.conf.`date +%Y%m%d` + echo "Normalising and updating $CONF" + ${SYS_QPKG_DIR}/bin/mesh -useconf -normaliseconf < /var/backups/mesh.conf.`date +%Y%m%d` > $CONF + else + echo "Generating initial configuration file $config_file" + echo "Please familiarise yourself with this file before starting RiV-mesh" + sh -c "umask 0027 && ${SYS_QPKG_DIR}/bin/mesh -genconf > '$CONF'" + fi + chmod a+w $CONF + +} + +pkg_post_install(){ + ln -sf $SYS_QPKG_DIR/var/log/mesh.log $SYS_QPKG_DIR/www/log +} diff --git a/contrib/ui/nas-qnap/package/shared/mesh.sh b/contrib/ui/nas-qnap/package/shared/mesh.sh new file mode 100644 index 00000000..92c8c788 --- /dev/null +++ b/contrib/ui/nas-qnap/package/shared/mesh.sh @@ -0,0 +1,120 @@ +#!/bin/sh +QPKG_CONF="/etc/config/qpkg.conf" +CONF="/etc/config/mesh.conf" +QPKG_NAME="mesh" +QPKG_DIR=$(/sbin/getcfg $QPKG_NAME Install_Path -f $QPKG_CONF) +KERNEL_MODULES+=" tun" + +load_kernel_modules(){ + local KERNEL_VERSION=$(/bin/uname -r) + local KERNEL_MODULES_PATH="/lib/modules" + for M in ${KERNEL_MODULES}; do + if [ -f ${KERNEL_MODULES_PATH}/vpn/${M}.ko ]; then + /sbin/insmod ${KERNEL_MODULES_PATH}/vpn/${M}.ko + continue + fi + if [ -f ${KERNEL_MODULES_PATH}/qvpn/${M}.ko ]; then + /sbin/insmod ${KERNEL_MODULES_PATH}/qvpn/${M}.ko + continue + fi + if [ -f ${KERNEL_MODULES_PATH}/misc/${M}.ko ]; then + /sbin/insmod ${KERNEL_MODULES_PATH}/misc/${M}.ko + continue + fi + if [ -f ${KERNEL_MODULES_PATH}/others/${M}.ko ]; then + /sbin/insmod ${KERNEL_MODULES_PATH}/others/${M}.ko + continue + fi + if [ -f ${KERNEL_MODULES_PATH}/${KERNEL_VERSION}/${M}.ko ]; then + /sbin/insmod ${KERNEL_MODULES_PATH}/${KERNEL_VERSION}/${M}.ko + continue + fi + done +} + +create_tun(){ + if ( [ ! -c /dev/net/tun ] ); then + if ( [ ! -d /dev/net ] ); then + mkdir -m 755 /dev/net + fi + mknod /dev/net/tun c 10 200 + chmod 0755 /dev/net/tun + fi + + # Load the tun module if not already loaded + if ( !(lsmod | grep -q "^tun\s") ); then + insmod /lib/modules/tun.ko + fi +} + +start_service () +{ + exec 2>>/tmp/mesh.log + set -x + + #enable ipv6 + sysctl -w net.ipv6.conf.all.disable_ipv6=0 + sysctl -w net.ipv6.conf.default.disable_ipv6=0 + + # Create the necessary file structure for /dev/net/tun + create_tun + load_kernel_modules + + #. /etc/init.d/vpn_common.sh && load_kernel_modules + + if [ ! -f '/etc/config/apache/extra/apache-mesh.conf' ] ; then + ln -sf $QPKG_DIR/apache-mesh.conf /etc/config/apache/extra/ + apache_reload=1 + fi + + if ! grep '/etc/config/apache/extra/apache-mesh.conf' /etc/config/apache/apache.conf ; then + echo 'Include /etc/config/apache/extra/apache-mesh.conf' >> /etc/config/apache/apache.conf + apache_reload=1 + fi + + if [ -n "$apache_reload" ] ; then + /usr/local/apache/bin/apachectl -k graceful + fi + + # Launch the mesh in the background. + ${QPKG_DIR}/bin/mesh -useconffile "$CONF" \ + -httpaddress "http://127.0.0.1:19019" \ + -wwwroot "$QPKG_DIR/www" \ + -logto "$QPKG_DIR/var/log/mesh.log" & + if [ $? -ne 0 ]; then + echo "Starting $QPKG_NAME failed" + exit 1 + fi +} + +stop_service () +{ + # Kill mesh + pid=`pidof -s mesh` + if [ -z "$pid" ]; then + echo "mesh was not running" + exit 0 + fi + kill "$pid" +} + +case "$1" in + start) + start_service + ;; + + stop) + stop_service + ;; + + restart) + $0 stop + $0 start + ;; + + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac + +exit 0 diff --git a/contrib/ui/nas-synology-dsm6.0/package/dsm.mesh.conf b/contrib/ui/nas-synology-dsm6.0/package/dsm.mesh.conf new file mode 100644 index 00000000..c22b015b --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/package/dsm.mesh.conf @@ -0,0 +1,14 @@ +location = /mesh { + return 301 /mesh/; +} + +location ~ ^/mesh/ { + rewrite ^/mesh/(.*) /$1 break; + proxy_pass http://127.0.0.1:19019; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-For-Addr $server_addr; + proxy_set_header X-Forwarded-For-Port $server_port; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Original-URI $request_uri; +} diff --git a/contrib/ui/nas-synology-dsm6.0/package/mesh.sc b/contrib/ui/nas-synology-dsm6.0/package/mesh.sc new file mode 100644 index 00000000..fd9eb76b --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/package/mesh.sc @@ -0,0 +1,5 @@ +[mesh] +title="HTTP" +desc="RiV Mesh Web interface" +port_forward="no" +dst.ports="19019/tcp" diff --git a/contrib/ui/nas-synology-dsm6.0/package/ui/config b/contrib/ui/nas-synology-dsm6.0/package/ui/config new file mode 100644 index 00000000..f84eb833 --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/package/ui/config @@ -0,0 +1,11 @@ +{ + ".url": { + "org.mesh": { + "type": "url", + "title": "RiV Mesh", + "desc": "ipv6 mesh network", + "icon": "mesh-{0}.png", + "url": "/webman/3rdparty/mesh/login.html" + } + } +} diff --git a/contrib/ui/nas-synology-dsm6.0/package/ui/login.html b/contrib/ui/nas-synology-dsm6.0/package/ui/login.html new file mode 100644 index 00000000..2befc70b --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/package/ui/login.html @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/hooks/deviceinfo b/contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/hooks/deviceinfo new file mode 100644 index 00000000..1dcdd82c --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/hooks/deviceinfo @@ -0,0 +1,7 @@ +#!/bin/sh +echo vendor=Synology +echo vendorOperatingSystemName=DSM +. /etc.defaults/VERSION +echo firmwareVersion="${productversion}-${buildnumber}" +echo $(cat /etc/avahi/services/dsminfo.service | grep model | sed -e 's/<[^>]*>//g;s/^ *//') +echo $(cat /etc/avahi/services/dsminfo.service | grep serial | sed -e 's/<[^>]*>//g;s/^ *//') diff --git a/contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/hooks/webauth b/contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/hooks/webauth new file mode 100644 index 00000000..cd61f3c5 --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/hooks/webauth @@ -0,0 +1,22 @@ +#!/bin/sh +export CONTENT_LENGTH=$HTTP_CONTENT_LENGTH +export CONTENT_TYPE=$HTTP_CONTENT_TYPE + +IFS=';' +for x in $HTTP_COOKIE +do + case $x in + *EdSynoToken*) + eval $x + ;; + esac +done +[ -z $QUERY_STRING ] && export QUERY_STRING=SynoToken=$EdSynoToken || export QUERY_STRING="$QUERY_STRING&SynoToken=$EdSynoToken" + +[ ! -z $HTTP_X_REAL_IP ] && export REMOTE_ADDR=$HTTP_X_REAL_IP +[ ! -z $HTTP_X_FORWARDED_FOR_ADDR ] && export SERVER_ADDR=$HTTP_X_FORWARDED_FOR_ADDR +[ ! -z $HTTP_X_FORWARDED_FOR_PORT ] && export SERVER_PORT=$HTTP_X_FORWARDED_FOR_PORT + +#exit with zero status on auth success and 1 on error +[ ! -z $(/usr/syno/synoman/webman/modules/authenticate.cgi) ] +exit $? diff --git a/contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/pre_upgrade.sh b/contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/pre_upgrade.sh new file mode 100644 index 00000000..1faceb4b --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/package/var/lib/mesh/pre_upgrade.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +log_exit(){ + echo $2 + exit $1 +} + +rm "$ED_APP_ROOT/bin/mesh +rm -rf "$ED_APP_ROOT/www" +rm -rf "$ED_APP_ROOT/ui" diff --git a/contrib/ui/nas-synology-dsm6.0/package/www/assets/partner-logo.png b/contrib/ui/nas-synology-dsm6.0/package/www/assets/partner-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..887975a11b51c364be5f33b89a6d96eeef2e289a GIT binary patch literal 5134 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
gP(%0^t~bP>91&0+q1 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 literal 0 HcmV?d00001 diff --git a/contrib/ui/nas-synology-dsm6.0/package/www/assets/properties.js b/contrib/ui/nas-synology-dsm6.0/package/www/assets/properties.js new file mode 100644 index 00000000..505d3f53 --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/package/www/assets/properties.js @@ -0,0 +1,81 @@ +var ed = { + partnerId: 1126, + brand: 'RiV Mesh', + applicationName: 'RiV Mesh Synology DSM App', + nasOSName: 'Synology DSM', + nasVisitEDWebsiteLogin: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteSignup: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteLoggedin: "https://github.com/RiV-chain/RiV-mesh", + getCookie: function (name) { + var matches = document.cookie.match(new RegExp( + "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" + )); + return matches ? decodeURIComponent(matches[1]) : undefined; + }, + setCookie: function (key, value, expires) { + if(expires) { + var d = new Date(); + d.setTime(d.getTime() + (30 * 60 * 1000)); + expires = "; expires=" + d.toUTCString(); + } else { + expires = ""; + } + document.cookie = key + "=" + value + expires + "; path=/"; + }, + getNasAuthUrl: function () { + ed.setCookie('EdSynoToken', ""); + var url = ed.getCookie('origin'); + if (url === undefined) { + url = window.location.protocol + "//" + window.location.hostname + ":" + 5000; + } + return url; + } +}; +$(function () { + function params(obj) { + if (typeof obj === 'string') { + if (obj[0] === '?') { + obj = obj.substring(1); + } + var result = {}; + obj = obj.split("&"); + obj.forEach(function (pair) { + pair = pair.split("="); + var key = decodeURIComponent(pair[0]); + var value = decodeURIComponent(pair[1]); + // If first entry with this name + if (typeof result[key] === "undefined") { + result[key] = value; + // If second entry with this name + } else if (typeof result[key] === "string") { + result[key] = [result[key], value]; + // If third or later entry with this name + } else { + result[key].push(value); + } + }); + return result; + } else { + return Object.keys(obj).map(function (key) { + return encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]); + }).join('&'); + } + }; + //Hide URL parameters + var query = params(window.location.search.substring(1)); + var refresh = false; + for (var k in query) { + if (k === 'SynoToken') { + ed.setCookie('EdSynoToken', query[k]); + refresh = true; + delete query[k]; + } else if (k === 'origin') { + ed.setCookie('origin', query[k]); + refresh = true; + delete query[k]; + } + } + query = $.param(query); + if (refresh) + window.location.replace(window.location.origin + window.location.pathname + window.location.hash + ((query === "") ? "" : ("?" + query))); +}); diff --git a/contrib/ui/nas-synology-dsm6.0/spk/conf/resource b/contrib/ui/nas-synology-dsm6.0/spk/conf/resource new file mode 100644 index 00000000..37c611c5 --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/spk/conf/resource @@ -0,0 +1,5 @@ +{ + "port-config": { + "protocol-file": "mesh.sc" + } +} diff --git a/contrib/ui/nas-synology-dsm6.0/spk/scripts/postinst b/contrib/ui/nas-synology-dsm6.0/spk/scripts/postinst new file mode 100644 index 00000000..824040ca --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/spk/scripts/postinst @@ -0,0 +1,17 @@ +#!/bin/bash +DEBUG=true +SH="$(readlink /proc/$$/exe)" +if $DEBUG ; then + echo "" > /tmp/mesh.log + exec 2>>/tmp/mesh.log + SH="$SH -x" + set -x +fi + +BASE="/var/packages/mesh/target" +LOG_FILE="$BASE/var/log/mesh.log" + +ln -sf $LOG_FILE $BASE/www/log +ln -sf $BASE/dsm.mesh.conf /etc/nginx/conf.d/dsm.mesh.conf +nginx -s reload +exit 0 diff --git a/contrib/ui/nas-synology-dsm6.0/spk/scripts/postuninst b/contrib/ui/nas-synology-dsm6.0/spk/scripts/postuninst new file mode 100644 index 00000000..19fa823c --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/spk/scripts/postuninst @@ -0,0 +1,8 @@ +#!/bin/sh + +rm -f /var/run/mesh.pid +LOG_SYMLINK=/var/log/mesh.log +[ -L $LOG_SYMLINK ] && rm -f $LOG_SYMLINK +rm -f /etc/nginx/conf.d/dsm.mesh.conf + +exit 0 diff --git a/contrib/ui/nas-synology-dsm6.0/spk/scripts/postupgrade b/contrib/ui/nas-synology-dsm6.0/spk/scripts/postupgrade new file mode 100644 index 00000000..c52d3c26 --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/spk/scripts/postupgrade @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 0 diff --git a/contrib/ui/nas-synology-dsm6.0/spk/scripts/preinst b/contrib/ui/nas-synology-dsm6.0/spk/scripts/preinst new file mode 100644 index 00000000..c52d3c26 --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/spk/scripts/preinst @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 0 diff --git a/contrib/ui/nas-synology-dsm6.0/spk/scripts/preuninst b/contrib/ui/nas-synology-dsm6.0/spk/scripts/preuninst new file mode 100644 index 00000000..c52d3c26 --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/spk/scripts/preuninst @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 0 diff --git a/contrib/ui/nas-synology-dsm6.0/spk/scripts/preupgrade b/contrib/ui/nas-synology-dsm6.0/spk/scripts/preupgrade new file mode 100644 index 00000000..c52d3c26 --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/spk/scripts/preupgrade @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 0 diff --git a/contrib/ui/nas-synology-dsm6.0/spk/scripts/start-stop-status b/contrib/ui/nas-synology-dsm6.0/spk/scripts/start-stop-status new file mode 100644 index 00000000..70d3afd1 --- /dev/null +++ b/contrib/ui/nas-synology-dsm6.0/spk/scripts/start-stop-status @@ -0,0 +1,120 @@ +#!/bin/sh + +BASE="/var/packages/mesh/target" +CONFIG_DIR="/var/packages/mesh/etc" +config_file="$CONFIG_DIR/mesh.conf" +LOG_FILE="$BASE/var/log/mesh.log" +export LD_LIBRARY_PATH="$BASE/lib" +cd / + +set_proxy() +{ + if [ -f /etc/proxy.conf ]; then + . /etc/proxy.conf + if [ "$proxy_enabled" = "yes" ]; then + export http_proxy="$https_host":"$https_port" + fi + fi +} + +start_service () +{ + + set_proxy + + if [ -f $config_file ]; then + mkdir -p /var/backups + echo "Backing up configuration file to /var/backups/mesh.conf.`date +%Y%m%d`" + cp $config_file /var/backups/mesh.conf.`date +%Y%m%d` + echo "Normalising and updating /etc/mesh.conf" + ${BASE}/bin/mesh -useconf -normaliseconf < /var/backups/mesh.conf.`date +%Y%m%d` > $config_file + else + echo "Generating initial configuration file $config_file" + echo "Please familiarise yourself with this file before starting RiV-mesh" + sh -c "umask 0027 && ${BASE}/bin/mesh -genconf > '$config_file'" + fi + + # Create the necessary file structure for /dev/net/tun + if ( [ ! -c /dev/net/tun ] ); then + if ( [ ! -d /dev/net ] ); then + mkdir -m 755 /dev/net + fi + mknod /dev/net/tun c 10 200 + chmod 0755 /dev/net/tun + fi + + # Load the tun module if not already loaded + if ( !(lsmod | grep -q "^tun\s") ); then + insmod /lib/modules/tun.ko + fi + + #workaround for bin error: + #Not multicasting on eth0 due to error: listen tcp [xxxx]:0: bind: cannot assign requested address + sysctl net.ipv6.ip_nonlocal_bind=1 + + # Launch the mesh in the background. + ${BASE}/bin/mesh -useconffile "$config_file" \ + -httpaddress "http://localhost:19019" \ + -wwwroot "$BASE/www" \ + -logto "$BASE/var/log/mesh.log" & + + return $? +} + +stop_service () +{ + pid=`pidof -s mesh` + if [ -z "$pid" ]; then + echo "mesh was not running" + exit 0 + fi + kill "$pid" +} + +status_service () +{ + + pid=`pidof -s mesh` + + if [[ ! -z "${pid}" ]] && [ -d /proc/${pid} ]; then + return 0 + fi + if [[ ! -z "${pid}" ]]; then + return 1 + fi + return 3 +} + +case $1 in + start) + start_service + echo "Running RiV Mesh" + exit 0 + ;; + stop) + stop_service + echo "Stopped RiV Mesh" + exit 0 + ;; + status) + status_service + sts=$? + if [ $sts -eq 0 ]; then + echo "RiV Mesh is running" + else + echo "RiV Mesh is not running" + fi + exit $sts + ;; + + log) + if [ -f $LOG_FILE ]; + then + echo $LOG_FILE + fi + exit 0 + ;; + *) + exit 1 + ;; +esac diff --git a/contrib/ui/nas-synology-dsm7.0/package/ui/login.html b/contrib/ui/nas-synology-dsm7.0/package/ui/login.html new file mode 100644 index 00000000..87f26c1f --- /dev/null +++ b/contrib/ui/nas-synology-dsm7.0/package/ui/login.html @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/contrib/ui/nas-synology-dsm7.0/spk/conf/privilege b/contrib/ui/nas-synology-dsm7.0/spk/conf/privilege new file mode 100644 index 00000000..a6d06a81 --- /dev/null +++ b/contrib/ui/nas-synology-dsm7.0/spk/conf/privilege @@ -0,0 +1,21 @@ +{ + "defaults":{ + "run-as": "package" + }, + "ctrl-script":[{ + "action": "postinst", + "run-as": "root" + }, { + "action": "postuninst", + "run-as": "root" + }, { + "action": "preuninst", + "run-as": "root" + }, { + "action": "start", + "run-as": "root" + }, { + "action": "stop", + "run-as": "root" + }] +} diff --git a/contrib/ui/nas-synology-dsm7.0/spk/scripts/start-stop-status b/contrib/ui/nas-synology-dsm7.0/spk/scripts/start-stop-status new file mode 100644 index 00000000..b4ad92d7 --- /dev/null +++ b/contrib/ui/nas-synology-dsm7.0/spk/scripts/start-stop-status @@ -0,0 +1,120 @@ +#!/bin/sh + +BASE="/var/packages/mesh/target" +CONFIG_DIR="/var/packages/mesh/etc" +config_file="$CONFIG_DIR/mesh.conf" +LOG_FILE="$BASE/var/log/mesh.log" +export LD_LIBRARY_PATH="$BASE/lib" +cd / + +set_proxy() +{ + if [ -f /etc/proxy.conf ]; then + . /etc/proxy.conf + if [ "$proxy_enabled" = "yes" ]; then + export http_proxy="$https_host":"$https_port" + fi + fi +} + +start_service () +{ + + set_proxy + + if [ -f $config_file ]; then + mkdir -p /var/backups + echo "Backing up configuration file to /var/backups/mesh.conf.`date +%Y%m%d`" + cp $config_file /var/backups/mesh.conf.`date +%Y%m%d` + echo "Normalising and updating /etc/mesh.conf" + ${BASE}/bin/mesh -useconf -normaliseconf < /var/backups/mesh.conf.`date +%Y%m%d` > $config_file + else + echo "Generating initial configuration file $config_file" + echo "Please familiarise yourself with this file before starting RiV-mesh" + sh -c "umask 0027 && ${BASE}/bin/mesh -genconf > '$config_file'" + fi + + # Create the necessary file structure for /dev/net/tun + if ( [ ! -c /dev/net/tun ] ); then + if ( [ ! -d /dev/net ] ); then + mkdir -m 755 /dev/net + fi + mknod /dev/net/tun c 10 200 + chmod 0755 /dev/net/tun + fi + + # Load the tun module if not already loaded + if ( !(lsmod | grep -q "^tun\s") ); then + insmod /lib/modules/tun.ko + fi + + #workaround for bin error: + #Not multicasting on eth0 due to error: listen tcp [xxxx]:0: bind: cannot assign requested address + sysctl net.ipv6.ip_nonlocal_bind=1 + + # Launch the server in the background. + ${BASE}/bin/mesh -useconffile "$config_file" \ + -httpaddress "http://[::]:19019" \ + -wwwroot "$BASE/www" \ + -logto "$BASE/var/log/mesh.log" & + + return $? +} + +stop_service () +{ + pid=`pidof -s mesh` + if [ -z "$pid" ]; then + echo "mesh was not running" + exit 0 + fi + kill "$pid" +} + +status_service () +{ + + pid=`pidof -s mesh` + + if [[ ! -z "${pid}" ]] && [ -d /proc/${pid} ]; then + return 0 + fi + if [[ ! -z "${pid}" ]]; then + return 1 + fi + return 3 +} + +case $1 in + start) + start_service + echo "Running RiV Mesh" + exit 0 + ;; + stop) + stop_service + echo "Stopped RiV Mesh" + exit 0 + ;; + status) + status_service + sts=$? + if [ $sts -eq 0 ]; then + echo "RiV Mesh is running" + else + echo "RiV Mesh is not running" + fi + exit $sts + ;; + + log) + if [ -f $LOG_FILE ]; + then + echo $LOG_FILE + fi + exit 0 + ;; + *) + exit 1 + ;; +esac diff --git a/contrib/ui/nas-terramaster/mesh/config.ini b/contrib/ui/nas-terramaster/mesh/config.ini new file mode 100644 index 00000000..b70eff7b --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/config.ini @@ -0,0 +1,10 @@ +{ +"path": "/module/?mod=4.Application/21.mesh.php&t=0", +"id": "mesh", +"exec": 1, +"hideTitle": 1, +"width": 900, +"height": 580, +"icon": "/images/icons/mesh.svg", +"content": "core.appNormal();" +} diff --git a/contrib/ui/nas-terramaster/mesh/etc/init.d/mesh b/contrib/ui/nas-terramaster/mesh/etc/init.d/mesh new file mode 100755 index 00000000..25259422 --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/etc/init.d/mesh @@ -0,0 +1,74 @@ +#!/bin/sh + +BASE="/usr" +CONFIG_DIR="/etc" +config_file="$CONFIG_DIR/mesh.conf" +LOG_FILE="$BASE/var/log/mesh.log" + +service_status() +{ + + pid=`pidof -s mesh` + + if [[ ! -z "${pid}" ]] && [ -d /proc/${pid} ]; then + echo "mesh running" + exit 1 + fi + echo "mesh stopped" +} + +service_start(){ + + if [ -f $config_file ]; then + mkdir -p /var/backups + echo "Backing up configuration file to /var/backups/mesh.conf.`date +%Y%m%d`" + cp $config_file /var/backups/mesh.conf.`date +%Y%m%d` + echo "Normalising and updating /etc/mesh.conf" + ${BASE}/bin/mesh -useconf -normaliseconf < /var/backups/mesh.conf.`date +%Y%m%d` > $config_file + else + echo "Generating initial configuration file $config_file" + echo "Please familiarise yourself with this file before starting RiV-mesh" + sh -c "umask 0027 && ${BASE}/bin/mesh -genconf > '$config_file'" + fi + + # Launch the server in the background. + ${BASE}/bin/mesh -useconffile "$config_file" \ + -httpaddress "http://127.0.0.1:19019" \ + -wwwroot "/usr/local/mesh/www" \ + -logto "$BASE/var/log/mesh.log" & + + service nginx reload + sleep 1 +} + +service_stop(){ + pid=`pidof -s mesh` + if [ -z "$pid" ]; then + echo "mesh was not running" + exit 0 + fi + kill "$pid" +} + +service_restart(){ + service_stop + service_start +} + +case $1 in + start) + service_start + exit 0 ;; + stop) + service_stop + exit 0 ;; + restart) + service_restart + exit 0 ;; + status) + service_status + exit 0 ;; + *) + echo "Usage: `basename $0` {start|stop|restart|status}" + exit 1 ;; +esac diff --git a/contrib/ui/nas-terramaster/mesh/etc/nginx/conf.d/mesh.conf b/contrib/ui/nas-terramaster/mesh/etc/nginx/conf.d/mesh.conf new file mode 100644 index 00000000..294000ba --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/etc/nginx/conf.d/mesh.conf @@ -0,0 +1,4 @@ +location ~ ^/mesh/ { + rewrite ^/mesh/(.*) /$1 break; + proxy_pass http://127.0.0.1:19019; +} diff --git a/contrib/ui/nas-terramaster/mesh/mesh.lang b/contrib/ui/nas-terramaster/mesh/mesh.lang new file mode 100644 index 00000000..2a5bcab3 --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/mesh.lang @@ -0,0 +1,11 @@ +[zh-cn] +name = "RiV Mesh" +auth = "mesh" +version = "%%VERSION%%" +descript = "RiV-mesh is an implementation of a fully end-to-end encrypted IPv6 network." + +[en-us] +name = "RiV Mesh" +auth = "mesh" +version = "%%VERSION%%" +descript = "RiV-mesh is an implementation of a fully end-to-end encrypted IPv6 network." diff --git a/contrib/ui/nas-terramaster/mesh/remove_list b/contrib/ui/nas-terramaster/mesh/remove_list new file mode 100644 index 00000000..45543188 --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/remove_list @@ -0,0 +1 @@ +/usr/www/mesh diff --git a/contrib/ui/nas-terramaster/mesh/usr/local/mesh/var/lib/mesh/hooks/deviceinfo b/contrib/ui/nas-terramaster/mesh/usr/local/mesh/var/lib/mesh/hooks/deviceinfo new file mode 100644 index 00000000..8af339e2 --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/usr/local/mesh/var/lib/mesh/hooks/deviceinfo @@ -0,0 +1,6 @@ +#!/bin/sh +echo vendor=TerraMaster +echo vendorOperatingSystemName=TerraMaster TOS +echo firmwareVersion=$(awk -F= '$1 ~ /version/ {print $2}' /etc/tos.conf) +#echo model= +#echo serial= diff --git a/contrib/ui/nas-terramaster/mesh/usr/local/mesh/www/assets/partner-logo.png b/contrib/ui/nas-terramaster/mesh/usr/local/mesh/www/assets/partner-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..40efc970ae1fd7a30a565ca33565c69f5f1def80 GIT binary patch literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^hk=-#5lAr1tv#|7NU@|l`Z_W&Z0zU$lgJ9>D)^mS!_#>&j6Z7y`4{VY&OAUV;m3`m~<;tC*U0pYbS z&Y3`3z|+MsgyVYhkA7yG1c@U?3_E1kR*HY02y%vMiEBhjN@7W>RdP`(kYX@0Ff!6L zFx53Q3NbRUGBUI>GSxOPwlXmA(1`6r(U6;;l9^Ts*I-~AVrXb(Vr*p!)ewF%;3iN5 NgQu&X%Q~loCIH?nO6>pu literal 0 HcmV?d00001 diff --git a/contrib/ui/nas-terramaster/mesh/usr/local/mesh/www/assets/properties.js b/contrib/ui/nas-terramaster/mesh/usr/local/mesh/www/assets/properties.js new file mode 100644 index 00000000..659a34b6 --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/usr/local/mesh/www/assets/properties.js @@ -0,0 +1,11 @@ +var ed = { + partnerId: 1599, + brand: 'RiV Mesh', + applicationName: 'RiV Mesh TerraMaster App', + nasOSName: 'TerraMaster NAS', + nasVisitEDWebsiteLogin: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteSignup: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteLoggedin: "https://github.com/RiV-chain/RiV-mesh", + signingUpMessageHtml: "", + signingUpPropositionMessageHtml: "" +}; diff --git a/contrib/ui/nas-terramaster/mesh/usr/www/css/style-mesh.css b/contrib/ui/nas-terramaster/mesh/usr/www/css/style-mesh.css new file mode 100644 index 00000000..7eb76373 --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/usr/www/css/style-mesh.css @@ -0,0 +1,17 @@ +.plex{} +.plex .header{border:none;height:150px;padding:20px 0 30px;box-sizing:border-box;} +.plex .header .logo{margin:0px auto;width:300px;height:100px;display:block;outline:none;background: url(../images/ext/plex-logo.svg) #8B6161 center center no-repeat;background-size:90%;} +.plex .introduce{width:520px;margin:0 auto;line-height:24px;font-size:16px;} +.plex .introduce *{line-height:24px;font-size:16px;} +.plex .introduce i{display: table-row;font-size:24px;font-style: normal;line-height:40px;} +.heder-info{display: table;width: 85%;margin: 0 auto;} +.logo-info{display: table-cell;width: 70%;vertical-align: middle;} +.logo-info img{width: 10%;float: left;} +.logo-info figcaption{height: 45px;float: left;line-height: 45px;font-size: 30px;margin-left: 10px;} +.v-info{display: table-cell;} +.v-info p{margin: 0;padding: 0;} +.intr{display: table;width: 85%;margin: 0 auto;margin-top: 8px;margin-bottom: 50px;} +.btn-info-no{line-height: 1;height: 30px;padding: 0 15px;background-color: rgb(255,255,255);border: 1px solid rgb(210,210,210); color: rgb(120,120,120);position: relative;z-index: 200;} +.btn-info-no:active{color: rgb(60,60,60);border-color: rgb(138,138,138);} +.btn-info-no:hover{color: rgb(60,60,60);border-color: rgb(138,138,138);} +.fieldset:first-child{padding-top: 0 !important;} \ No newline at end of file diff --git a/contrib/ui/nas-terramaster/mesh/usr/www/include/class/mesh.class.php b/contrib/ui/nas-terramaster/mesh/usr/www/include/class/mesh.class.php new file mode 100644 index 00000000..a50b7f5e --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/usr/www/include/class/mesh.class.php @@ -0,0 +1,33 @@ +fun->_exec(self::$execute." status"); + if(strstr($ret, "running")){ + return 1; + }else{ + return 0; + } + }else{ + return 0; + } + } + + function _switch($stat) + { + if($stat == 1){ + $this->_sysAutoEvent(basename(self::$execute), true); + $this->fun->_backexec(self::$execute." start"); + }else{ + $this->_sysAutoEvent(basename(self::$execute), false); + $this->fun->_exec(self::$execute." stop"); + } + sleep(1); + $ret = $this->_status(); + return $ret; + } +} diff --git a/contrib/ui/nas-terramaster/mesh/usr/www/lang/ext/mesh.lang b/contrib/ui/nas-terramaster/mesh/usr/www/lang/ext/mesh.lang new file mode 100644 index 00000000..a5a59360 --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/usr/www/lang/ext/mesh.lang @@ -0,0 +1,11 @@ +[zh-cn] +mesh = "RiV Mesh" +auth = "Riv Chain ltd" +tos_mesh_note = "RiV-mesh 是完全端到端加密 IPv6 網絡的實現" +enter = "进入" + +[en-us] +mesh = "RiV Mesh" +auth = "Riv Chain ltd" +tos_mesh_note = "RiV-mesh is an implementation of a fully end-to-end encrypted IPv6 network." +enter = "Enter" diff --git a/contrib/ui/nas-terramaster/mesh/usr/www/mod/4.Application/21.mesh.php b/contrib/ui/nas-terramaster/mesh/usr/www/mod/4.Application/21.mesh.php new file mode 100644 index 00000000..9f743d26 --- /dev/null +++ b/contrib/ui/nas-terramaster/mesh/usr/www/mod/4.Application/21.mesh.php @@ -0,0 +1,93 @@ +_status(); +$app_info = $mesh->get_app_info('mesh'); +$L = $La->extlanguage("mesh"); +$url = "http://".$_SERVER['SERVER_ADDR'].":8181/mesh/"; +?> + + + + + + + diff --git a/contrib/ui/nas-westerndigital/package/mesh/apache-mesh.conf b/contrib/ui/nas-westerndigital/package/mesh/apache-mesh.conf new file mode 100644 index 00000000..c7a70f39 --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/apache-mesh.conf @@ -0,0 +1,8 @@ +RedirectMatch 301 ^/mesh$ /mesh/ +LoadModule proxy_http_module modules/mod_proxy_http.so + + + ProxyPreserveHost On + ProxyPass "http://127.0.0.1:19019/" + ProxyPassReverse "http://127.0.0.1:19019/" + diff --git a/contrib/ui/nas-westerndigital/package/mesh/clean.sh b/contrib/ui/nas-westerndigital/package/mesh/clean.sh new file mode 100755 index 00000000..c3c9cf02 --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/clean.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +MESH_PACKAGE_LOG=/var/log/mesh.log +echo "clean.sh called" >> "$MESH_PACKAGE_LOG" + +rm -f /usr/bin/mesh +rm -f /usr/bin/meshctl + + +rm -rf /var/www/mesh +rm -f /usr/local/apache2/conf/extra/apache-mesh.conf diff --git a/contrib/ui/nas-westerndigital/package/mesh/init.sh b/contrib/ui/nas-westerndigital/package/mesh/init.sh new file mode 100755 index 00000000..c3590b6b --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/init.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +install_path="$1" +config_file=$install_path/mesh.conf +backup_config_file=/var/backups/mesh.conf + +MESH_PACKAGE_LOG=/var/log/mesh.log +echo "init.sh called" >> "$MESH_PACKAGE_LOG" + +exec 2>>/var/log/mesh.log +set -x + +mkdir -p /var/www/mesh + +# Binaries +ln -s "$install_path/bin/mesh" /usr/bin +ln -s "$install_path/bin/meshctl" /usr/bin + +# Web, probably, the app wil serve it by embedded server +ln -s "$install_path/www/mesh.png" /var/www/mesh +ln -s "$install_path/www/index.html" /var/www/mesh + +if [ -f $backup_config_file ]; then + echo "Backing up configuration file to /var/backups/mesh.conf" + echo "Normalising and updating /etc/mesh.conf" + mesh -useconf -normaliseconf < $backup_config_file > $config_file +else + echo "Generating initial configuration file $config_file" + echo "Please familiarise yourself with this file before starting RiV-mesh" + sh -c "umask 0027 && mesh -genconf > '$config_file'" + mkdir -p /var/backups +fi + +cp $config_file $backup_config_file diff --git a/contrib/ui/nas-westerndigital/package/mesh/install.sh b/contrib/ui/nas-westerndigital/package/mesh/install.sh new file mode 100755 index 00000000..b1172653 --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/install.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +INST_PATH=/mnt/HD/HD_a2/Nas_Prog/mesh +MESH_PACKAGE_LOG=/var/log/mesh.log +echo "install.sh called" >> "$MESH_PACKAGE_LOG" + +path_src="$1" +path_dst="$2" + +rm -rf "$INST_PATH" +mv "$path_src" "$path_dst" +#LOG_SYMLINK +ln -s "$INST_PATH"/var/log/mesh.log "$INST_PATH"/www/log +#already installed in start +#ln -s "$INST_PATH"/apache-mesh.conf /usr/local/apache2/conf/extra + +echo "install.sh: setting permissions to '$path_dst/mesh'" >> "$MESH_PACKAGE_LOG" +chown -R nobody:share "$path_dst/mesh" + +#( sleep 2 ; /usr/sbin/apache restart web ) & diff --git a/contrib/ui/nas-westerndigital/package/mesh/preinst.sh b/contrib/ui/nas-westerndigital/package/mesh/preinst.sh new file mode 100755 index 00000000..0d2e15f4 --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/preinst.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# Write to a different log, because main log will be overwritten by install.sh +MESH_PACKAGE_LOG=/var/log/mesh-preinst.log +echo "preinst.sh called" >> "$MESH_PACKAGE_LOG" + +path_dst="$1" +echo "path_dst=$path_dst" >> "$MESH_PACKAGE_LOG" + + +chown -R nobody:share "$path_dst" diff --git a/contrib/ui/nas-westerndigital/package/mesh/remove.sh b/contrib/ui/nas-westerndigital/package/mesh/remove.sh new file mode 100755 index 00000000..6272ba92 --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/remove.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +MESH_PACKAGE_LOG=/var/log/mesh.log +echo "remove.sh called" >> "$MESH_PACKAGE_LOG" +inst_path="$1" + +rm -f /usr/bin/mesh +rm -f /usr/bin/meshctl +rm -fr /var/www/mesh +rm -fr "$inst_path" diff --git a/contrib/ui/nas-westerndigital/package/mesh/start.sh b/contrib/ui/nas-westerndigital/package/mesh/start.sh new file mode 100755 index 00000000..8f3aa8f8 --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/start.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +MESH_PACKAGE_LOG=/var/log/mesh.log +echo "start.sh called" >> "$MESH_PACKAGE_LOG" + +pid=`pidof -s mesh` +if [ -n "$pid" ]; then + echo "start.sh: mesh already running" >> "$MESH_PACKAGE_LOG" + exit 0 +fi + +EXE_PATH=`readlink -f /usr/bin/mesh` +BIN_PATH=`dirname $EXE_PATH` +INSTALL_PATH=`dirname $BIN_PATH` +config_file=$INSTALL_PATH/mesh.conf + +ln -fs "$INSTALL_PATH"/apache-mesh.conf /usr/local/apache2/conf/extra +(/usr/sbin/apache restart web ) & + +START_COMMAND="/usr/bin/mesh -useconffile '$config_file' -httpaddress 'http://localhost:19019' -wwwroot '${INSTALL_PATH}/www' -logto '${INSTALL_PATH}/var/log/mesh.log'" +echo "start.sh: starting (START_COMMAND=$START_COMMAND)" >> "$MESH_PACKAGE_LOG" + + +(/usr/bin/mesh -useconffile "$config_file" -httpaddress "http://localhost:19019" -wwwroot "${INSTALL_PATH}/www" -logto "${INSTALL_PATH}/var/log/mesh.log") & diff --git a/contrib/ui/nas-westerndigital/package/mesh/stop.sh b/contrib/ui/nas-westerndigital/package/mesh/stop.sh new file mode 100755 index 00000000..6efa40c4 --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/stop.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +MESH_PACKAGE_LOG=/var/log/mesh.log +echo "stop.sh called" >> "$MESH_PACKAGE_LOG" + +rm -f /usr/local/apache2/conf/extra/apache-mesh.conf +(/usr/sbin/apache restart web ) & + +# ash is VERY limited, so use only basic ops +pid=`pidof -s mesh` +if [ -z "$pid" ]; then + echo "stop.sh: mesh was not running" >> "$MESH_PACKAGE_LOG" + exit 0 +fi + +echo "stop.sh: stop attempt #1" >> "$MESH_PACKAGE_LOG" +kill "$pid" +sleep 2 + +pid=`pidof -s mesh` +if [ -z "$pid" ]; then + echo "stop.sh: stopped" >> "$MESH_PACKAGE_LOG" + exit 0 +fi + +echo "stop.sh: stop attempt #2" >> "$MESH_PACKAGE_LOG" +kill "$pid" +sleep 4 + +pid=`pidof -s mesh` +if [ -z "$pid" ]; then + echo "stop.sh: stopped" >> "$MESH_PACKAGE_LOG" + exit 0 +fi + +echo "stop.sh: stop attempt #3" >> "$MESH_PACKAGE_LOG" +kill "$pid" +sleep 4 + +pid=`pidof -s mesh` +if [ -z "$pid" ]; then + echo "stop.sh: stopped" >> "$MESH_PACKAGE_LOG" + exit 0 +fi + +echo "stop.sh: hard kill" >> "$MESH_PACKAGE_LOG" +pkill -9 mesh diff --git a/contrib/ui/nas-westerndigital/package/mesh/ui/desc.xml b/contrib/ui/nas-westerndigital/package/mesh/ui/desc.xml new file mode 100644 index 00000000..fd9268ec --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/ui/desc.xml @@ -0,0 +1,7 @@ + + + Learn more here...]]> + diff --git a/contrib/ui/nas-westerndigital/package/mesh/var/lib/mesh/hooks/deviceinfo b/contrib/ui/nas-westerndigital/package/mesh/var/lib/mesh/hooks/deviceinfo new file mode 100644 index 00000000..a6c4860a --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/var/lib/mesh/hooks/deviceinfo @@ -0,0 +1,7 @@ +#!/bin/sh +echo vendor=westerndigital +echo vendorOperatingSystemName=WDMyCloud +echo firmwareVersion=$(cat /etc/version) +echo model=$(cat /etc/nas/nasdevice.xml | grep modelName | sed -e 's/<[^>]*>//g;s/^[ \t]*//') +echo serial=$(cat /etc/nas/nasdevice.xml | grep serialNumber | sed -e 's/<[^>]*>//g;s/^[ \t]*//') + diff --git a/contrib/ui/nas-westerndigital/package/mesh/var/lib/pre_upgrade.sh b/contrib/ui/nas-westerndigital/package/mesh/var/lib/pre_upgrade.sh new file mode 100644 index 00000000..1faceb4b --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/var/lib/pre_upgrade.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +log_exit(){ + echo $2 + exit $1 +} + +rm "$ED_APP_ROOT/bin/mesh +rm -rf "$ED_APP_ROOT/www" +rm -rf "$ED_APP_ROOT/ui" diff --git a/contrib/ui/nas-westerndigital/package/mesh/www/assets/partner-logo.png b/contrib/ui/nas-westerndigital/package/mesh/www/assets/partner-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7d0ae31a4a69320a0aea9773994753d6550a56eb GIT binary patch literal 2799 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 HLzDgot872$ literal 0 HcmV?d00001 diff --git a/contrib/ui/nas-westerndigital/package/mesh/www/assets/partner.css b/contrib/ui/nas-westerndigital/package/mesh/www/assets/partner.css new file mode 100755 index 00000000..9166c5e0 --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/www/assets/partner.css @@ -0,0 +1,9 @@ +.nas-apps-config-form-app-logo { + height: 110px; + background: url(logo.png) left center no-repeat; + background-size: 262px 56px; +} + +a { + color: #692782!important; +} diff --git a/contrib/ui/nas-westerndigital/package/mesh/www/assets/properties.js b/contrib/ui/nas-westerndigital/package/mesh/www/assets/properties.js new file mode 100644 index 00000000..663f0902 --- /dev/null +++ b/contrib/ui/nas-westerndigital/package/mesh/www/assets/properties.js @@ -0,0 +1,9 @@ +var ed = { + partnerId: 1950, + applicationName: 'RiV-Mesh App', + nasOSName: 'My Cloud OS', + basicEDWebsite: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteLogin: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteSignup: "https://github.com/RiV-chain/RiV-mesh", + nasVisitEDWebsiteLoggedin: "https://github.com/RiV-chain/RiV-mesh" +}; diff --git a/contrib/ui/www/assets/ajax-loader.gif b/contrib/ui/www/assets/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..d84f653789e5008da64ff04ee109471284a9e284 GIT binary patch literal 10819 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 300) { + $('#loadingScreen').hide(); + if (httpObj.status === 401) { + $('#signupScreen').hide(); + $('#statusScreen').hide(); + $('#loginScreen').hide(); + $('#loginToYourNAS').prop("href", ed.getNasAuthUrl()); + $(authNASScreen).show(); + $("#nasLogoutBlock").hide(); + } else { + console.error(httpObj); + } + } + }; + + var loginMode = function () { + $('#loadingScreen').hide(); + $('#statusScreen').hide(); + $('#signupScreen').hide(); + $('#loginScreen').show(); + }; + + var infoErrorCheckerScheduled = false; + + var updateInfo = function (response) { + info = {}; + for (var key in response) { + info[key] = response[key]; + } + for (var key in ed) { + info[key] = ed[key]; + } + }; + + var checkInfoError = function (response, forceSchedule) { + forceSchedule = typeof (forceSchedule) !== "undefined" ? forceSchedule : true; + if(isLoggedInMode) { + if (response.isAuthenticated === false) { + $('#statusAlert').html('Login failed: ' + response.authStatus); + $('#statusAlert').addClass("nas-apps-config-form-message-error"); + $('#statusAlert').show(); + } else { + $('#statusAlert').hide(); + } + } + if (response.appStatus === 'error') { + $('#applicationAlert').html(response.errorMessage + '

Please resolve error before continue'); + $('#applicationAlert').show(); + $('#loginBtn').prop('disabled', true); + $('#signupBtn').prop('disabled', true); + $('#inputPeerIP').prop('disabled', true); + $('#inputPeerPort').prop('disabled', true); + $('#inputPeerIPS').prop('disabled', true); + $('#inputPeerPortS').prop('disabled', true); + $('#inputPortConfirm').prop('disabled', true); + } else { + $('#applicationAlert').hide(); + $('#loginBtn').prop('disabled', false); + $('#signupBtn').prop('disabled', false); + $('#inputPeerIP').prop('disabled', false); + $('#inputPeerPort').prop('disabled', false); + $('#inputPeerIPS').prop('disabled', false); + $('#inputPeerPortS').prop('disabled', false); + $('#inputPortConfirm').prop('disabled', false); + } + if(infoErrorCheckerScheduled !== true || forceSchedule === true) { + $.ajax(fillAjax('getself', {})).done(function (response) { + updateInfo(response); + setTimeout(function(){checkInfoError(response, true);}, 1000); + }); + infoErrorCheckerScheduled = true; + } + }; + + var startMode = function () { + $('#loginAlert').hide(); + $('#inputPeerIP').val(''); + $('#inputPeerPort').val(''); + $.ajax(fillAjax('getself', {})).done(function (response) { + if (ed.useAuthNASRichScreen) { + $("#nasLogoutBlock").show(); + $('.nas-user-name').text(ed.getNasUser()); + } + loginMode(); + if (response.size !== 0) { + isLoggedInMode = true; + statusMode(); + } + var self = response; + checkInfoError(response); + $('#version').html((self.build_version !== null ? self.build_version : ' ') + (self.build_name !== null ? (' (' + self.build_name + ')') : '')); + $('.nas-apps-config-form-app-version').show(); + $('#username').text(self.address); + updateInfo(response); + }).fail(errorHandler); + $('#nasLoginAlert').hide(); + $('#nasInputPassword').val(''); + }; + + var waitForEvent = function (eventType, onSuccess, onError, timeout, startTime) { + startTime = typeof (startTime) === "undefined" ? new Date() : startTime; + timeout = typeof (timeout) === "undefined" ? Infinity : timeout; + setTimeout(function () { + if (((new Date()) - startTime) > timeout) { + onError("timeout"); + } else { + $.ajax(fillAjax('events', { + method: 'GET' + })).done(function (response) { + for (var k in response) { + if (response[k].sourceType === eventType) { + $.ajax(fillAjax('event/' + k, { + method: 'DELETE' + })); + if (response[k].type === 'success') + onSuccess(); + else if (response[k].type === 'error') + onError(response[k].errorMessage); + return; + } + } + waitForEvent(eventType, onSuccess, onError, timeout, startTime); + }).fail(function (httpObj) { + if (httpObj.status === 0) { + waitForEvent(eventType, onSuccess, onError, timeout, startTime); + } else { + errorHandler(httpObj); + } + }); + } + }, 500); + }; + + var loginDoneHandler = function () { + function onSuccess() { + //Show logged in screen + $('#username').text(($('#inputPeerIPS').val() === "") ? $('#inputPeerIP').val() : $('#inputPeerIPS').val()); + statusMode(); + $('#statusAlert').html($('#loginSuccess').html()); + $('#statusAlert').removeClass("nas-apps-config-form-message-error"); + $('#statusAlert').show(); + } + function onError(message) { + if (message === "timeout") { + $.ajax(fillAjax('info', {})).done(function (response) { + if (response.isAuthenticated === false) { + waitForEvent("login", onSuccess, onError, 30000); + } else { + onSuccess(); + } + }).fail(errorHandler); + } else { + if (message === "PEER_UNAVAILABLE" || message === "DN_UNRESOLVED") { + message = "Unable to connect to a peer"; + } + $('#loginAlert').html(message); + $('#loginAlert').show(); + loginMode(); + } + } + waitForEvent("login", onSuccess, onError, 30000); + }; + + $('#loginBtn').click(function (e) { + e.preventDefault(); + if ($('#loadingScreen').is(":visible")) return; + $('#inputPeerIP').val($('#inputPeerIP').val().trim()); + if ($('#inputPeerIP').val().length === 0 || $('#inputPeerPort').val().trim().length === 0) { + return; + } + $('#loginAlert').hide(); + loadingMode($('#loginLoadingMessage').text()); + + $.ajax(fillAjax('user', { + method: 'POST', + data: JSON.stringify({user: $('#inputPeerIP').val(), pass: $('#inputPeerPort').val()}) + })).done(loginDoneHandler).statusCode({202: loginDoneHandler}).fail(errorHandler); + }); + + + $("#inputPeerIP, #inputPeerPort").keypress(function (e) { + if (e.which === 13) { + $("#loginBtn").trigger("click"); + } + }); + + $('#logoutBtn').click(function (e) { + e.preventDefault(); + if ($('#loadingScreen').is(":visible")) return; + + loadingMode($('#logoutLoadingMessage').text()); + var doneHandler = function () { + $('#inputPeerIP').val(''); + $('#inputPeerPort').val(''); + setTimeout(function () { + location.reload(); + }, 5000); + }; + $.ajax(fillAjax('user', { + method: 'DELETE' + })).done(doneHandler).statusCode({202: doneHandler}).fail(errorHandler); + }); + + $('#manageBackups').click(function (e) { + e.preventDefault(); + $.ajax(fillAjax('autologin', { + async: false + })).done(function (response) { + var params = response.autologinToken; + params["tab"] = "naswizard"; + params["dname"] = info.devicename; + window.open(info.vaultUrl + "/account/login.aspx?" + $.param(params), "_blank"); + }).fail(errorHandler); + }); + + var currentLocation = function () { + var url = location.href; + // http://xxx// -> http://xxx// + if (url.slice(-1) === "/") { + return url; + // http://xxx//index.html -> http://xxx// + } else if (url.lastIndexOf("/") < url.lastIndexOf(".")) { + return url.substring(0, url.lastIndexOf("/") + 1); + // http://xxx/ -> http://xxx// + } else { + return url + "/"; + } + }; + + $('#logFileBtn').click(function (e) { + e.preventDefault(); + window.open(currentLocation().split("#")[0] + 'log', "_blank"); + }); + + $('#getDiagFileBtn').click(function (e) { + e.preventDefault(); + window.open(currentLocation().split("#")[0] + 'diagnostics.zip'); + }); + + $('#checkPeerBtn').click(function (e) { + e.preventDefault(); + window.open(info.vaultUrl + "/account/check_peer?UName=" + encodeURIComponent($('#inputPeerIP').val().trim()), "_blank"); + }); + + $('#goToSignupBtn').click(function (e) { + e.preventDefault(); + signupMode(); + }); + + $('#signupBackToLoginBtn').click(function (e) { + e.preventDefault(); + startMode(); + }); + + var signupDoneHandler = function () { + waitForEvent("register", loginDoneHandler, function (message) { + $('#loadingScreen').hide(); + $('#signupScreen').show(); + $('#signupAlert').html(message); + $('#signupAlert').show(); + }); + }; + + $('#signupBtn').click(function (e) { + e.preventDefault(); + if ($('#loadingScreen').is(":visible")) return; + + if ($('#inputPeerPortS').val() !== $('#inputPortConfirm').val()) { + $('#signupAlert').text($('#hostFormatError').text()); + $('#signupAlert').show(); + return; + } + + $('#inputPeerIPS').val($('#inputPeerIPS').val().trim()); + loadingMode($('#signupLoadingMessage').text()); + + $.ajax(fillAjax('user', { + method: 'PUT', + data: JSON.stringify({user: $('#inputPeerIPS').val(), pass: $('#inputPeerPortS').val(), c: ed.partnerId}) + })).done(signupDoneHandler).statusCode({202: signupDoneHandler}).fail(errorHandler); + }); //signupBtn.click + + $("#inputPeerIPS, #inputPeerPortS, #inputPortConfirm").keypress(function (e) { + if (e.which === 13) { + $("#signupBtn").trigger("click"); + } + }); + + var nasLoginSuccess = function () { + $('.nas-user-name').text(ed.getNasUser()); + }; + + var nasLoginFailure = function (message) { + //Show notification: IP/DN errors + if (typeof message !== 'undefined') { + $('#nasLoginAlert').html(message); + } else { + $('#nasLoginAlert').text($('#ipOrDNError').text()); + } + $(authNASScreen).show(); + $('#nasInputPassword').val(''); + $('#nasLoginAlert').show(); + $('#loadingScreen').hide(); + }; + + $('#nasLoginBtn').click(function (e) { + e.preventDefault(); + $('#nasInputUser').val($('#nasInputUser').val().trim()); + if ($('#nasInputUser').val().length === 0 || $('#nasInputPassword').val().trim().length === 0) { + return; + } + $('#nasLoginAlert').hide(); + loadingMode($('#loginLoadingMessage').text()); + ed.nasLoginCall(nasLoginSuccess, nasLoginFailure); + }); + + + $("#nasInputUser, #nasInputPassword").keypress(function (e) { + if (e.which === 13) { + $("#nasLoginBtn").trigger("click"); + return false; + } + }); + + $('#nasLogoutBtn').click(function (e) { + e.preventDefault(); + ed.nasLogoutCall(); + $("#nasLogoutBlock").hide(); + window.location.reload(); + }); + + var main = function () { + document.getElementById("dynamic_body").style.display = "block"; + $('title').text(ed.applicationName); + $('.nas-os-name').text(ed.nasOSName); + if ('nasVisitEDWebsiteLogin' in ed) { + $('.nas-visit-ed-website-login').prop("href", ed.nasVisitEDWebsiteLogin); + } else { + $('.nas-visit-ed-website-login').prop("href", basicEDWebsite); + } + if ('nasVisitEDWebsiteSignup' in ed) { + $('.nas-visit-ed-website-signup').prop("href", ed.nasVisitEDWebsiteSignup); + } else { + $('.nas-visit-ed-website-signup').prop("href", basicEDWebsite); + } + if ('nasVisitEDWebsiteLoggedin' in ed) { + $('.nas-visit-ed-website-loggedin').prop("href", ed.nasVisitEDWebsiteLoggedin); + } else { + $('.nas-visit-ed-website-loggedin').prop("href", basicEDWebsite); + } + if ('signingUpMessageHtml' in ed) { + $('#signingUpMessage').html(ed.signingUpMessageHtml); + } + if ('signingUpPropositionMessageHtml' in ed) { + $('#signingUpPropositionMessage').html(ed.signingUpPropositionMessageHtml); + } + if ('useAuthNASRichScreen' in ed && ed.useAuthNASRichScreen) { + authNASScreen = '#authNASRichScreen'; + } else { + ed.useAuthNASRichScreen = false; + } + startMode(); + }; + + main(); + +}); diff --git a/contrib/ui/www/assets/favicon.png b/contrib/ui/www/assets/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..1579e26109bd4e5183804de7b8e453bf40138d8b GIT binary patch literal 2849 zcmV++3*PjJP)Gr&F zKR@bf>z2%O*6@-u_kyldtIDO%6|J9S)wbnD_Vjdl)3Hhrfr!$>(dikfPEk=75*HWC z=6(|IF<=>d%a$z^e4lep?l}Y=c<({o)Jkjomst%#)%$O_b;Oho6W5;~4y#X$kkF#f z4})!2hKl=YMt5X2Ouq5GH72d)LG5(<-={0e%jvvZm771=Ok!eV{zT#tf!=o0rcGqm z?gXbUTbHuAwcfL|IXWxprfW}Bo(nA4HXMTIPXKd}AL#Wu(D-u9^g1nj7d&q~ys^a< zBF{U+{+q+?CCzKI>_V%mv&~MvNJnC(Cfiqpe<*R^z>P$)k}UpoTT>h7mWs^Fz5Z3 zAu8VqKCg3c`NLlR!MAyrNODS2AC}zqg*`etnxuT5qIh5vo+_?Qj7_{b5Z>844E)Vz z-p|X#KscjL;y678rQjSR&})u9e&dXKMh^dDG8*}J_KbjpT4%U&Yi|NgiOa#1B*l7) zB}al5M;zI@bt~DKutS-jTSzMJd=Z!U>mZmHJyuYAnFXB&f$7A|Qv(H|fYdkxK6A9? z9PbQ{cZ?_<%bE0&R;vfKr&*Y5c}dt+J%EzfvpfG>kz&WrI3?B@k{};`xRN9v-0#%c zVRLEhy1L}knx`rFI6*zpUo>z!^iGmJ)uX2d2dIIWgA98|$rz~VWg?EqV8pqmgKl!O-i=$wl_9WEZa?QU(pe@k`oLLrIY5l?WLJx6U&Y2&)nmJ3P<2=M0(dLtN3 zM#*S2g2`k8Y#$@iYdW2-?-|FSJxRu(chrVXrw6mi{LoV10{OS!KSTG4f$bfQV~8N| zN~`VW-w)gzVGmtCPIMpRD|)Itz{A4>CQO(B})8B~sjR;$J6 zNT<)7mXebX^6#A_aMijsLy{yyy6x?r*$q>E3ES|DG;>6|dK6q;T^SIj;>eLB?9X(` zvb10n@SD54J4*#dWZAN1Ks|z#l$5?PG6C#kgzP9!^F9Zh%gRieI18it$ zfV#Rm7IL{}a4bg7YPCW|MLBqSs3iYDy||%xfb>gS#x`=!`g+NRJXi3gKr?5~WS(YZ zWWearqnUSZZf>jw@V95r9u`hCx^1&}OO`BQWHAbBms;7Mg~0&2?+ta-Oj>} z1WHOuSaCWwFdaR%Imt9hCq#coi|~G0EUBRqE2-A4Gw4;i45x*PxD2whvl%$%48tZD z7uEzu0X>lk;QE$5lh-`%AGk?jM7z7Y;qc+Zj-_eF@N?qS*HqHZp9f2AU3Xt2UES@z zS$_on8W#PW6g*{)!1E8`#EBEkOAL4aWr($a00_8w^X9%HlxslVCD*TC&&Z+o7>#-J z=COH9W&_|6KR0@mlzvBhN8klF+=^YkZ;d_v;TZz2gwEkVpFc1B{&^F41wdW&Bqr->h}Udfi0eAMCuSdh5a&z(D$MF;!1L(Z5n1Jr7D-@Y%8 zU$bTnq@|^?2+7|2s*K{SB@@KGHP7>no!93G!oxu{0^&$Kj!T->oL-%$0F|c~uTuH2 zBUG<{B)bp`D5Trs{QFZ)sR}MiUNd1J4cG2 z)s1cMu>Y>1g-WusGYNU`z4uA#k*}0^nYe2!U5>JeYB*j!F+k*cRZ%~6!_O{Dm+IzWrYWu62Bo z)Y{UaC@Q+>LeCX;7h%d2RdG~Q6gil3Ktb6#mmrDSr(n@;S9%{X@#;QV&P1lf$*Q=& zF}>)JiuaJmE+zO(bvr3I zUqtS7US4(R_W0H{1}BeiNl<(Gi}WTW>FLD;#b)2dgtmGbDf~v)xoFTCd0OpK zM2<70)QxMeYb&(0Ss#!iM-P*Y8#gkC<;%&RE~OUBT5>p*)dXp|_nWHVKOdajPc>Xb zt`p4LGzx;lRg!ski-fnsKxL98uk_xZl>~O3$ak?269A(6;V|={4=gV~U$BIR*cHtGu9T;Z^#aTXR1nzTJK| zl#Y1;#|r$zfubY~&H87iA}VSPOYxHzQ?&m9)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
a",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="
t
",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj; +return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="
",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&>(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X
","
"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l) +}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("