From c59c652bac2e358b726a7e8f9c458dcbb4326b44 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Sep 2018 00:41:18 -0400 Subject: [PATCH 001/162] Added || true to ipfs init to help with reinstalls --- scripts/ipfs/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ipfs/install b/scripts/ipfs/install index 33a97ae1c..d24cffb35 100755 --- a/scripts/ipfs/install +++ b/scripts/ipfs/install @@ -18,7 +18,7 @@ sudo chown root:staff /usr/local/bin/ipfs rm -rf "$BASE_DIR/tmp" # Initialize IPFS -ipfs init +ipfs init || true # Configure HTTP to IPFS gateway source "$BASE_DIR/../shared/nginx/install" From 3f3cf96bf05fa1a01c93535f9676d9650bb336b7 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Sep 2018 10:31:53 -0400 Subject: [PATCH 002/162] Install script refactor script Added bash functions to reduce size of script Refactored installation components to reduce size Added comments TUI Interface for install --- scripts/install2 | 324 ++++++++++++++++------------------------------- 1 file changed, 111 insertions(+), 213 deletions(-) diff --git a/scripts/install2 b/scripts/install2 index 63021c906..6414cebc5 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -4,6 +4,73 @@ set -e TAG_CJDNS=186169f9a8631633795e4e9d70c501519a7800f4 +dialogGlobalParams="--backtitle Installation --ascii-lines" +# Ask if module is to be enabled if not defined +# askModule [default answer] +function askModule { + # Define standard behaviour (default yes) + askPrompt="[Y/n]" + nonDefaultMatch="Nn" + defaultValue=true + nonDefaultValue=false + dialogParam="" + + # Define alternative behaviour (default no) + if [ "$3" == "n" ]; then + askPrompt="[y/N]" + nonDefaultMatch="Yy" + nonDefaultValue=true + defaultValue=false + dialogParam=" --defaultno " + fi + + # This reads variable repersented by the string + eval res=\$$1 + + if [ "$(checkModule 'WITH_DIALOG')" ]; then + # Do not stop exec on non 0 return values + set +e + dialog $dialogGlobalParams $dialogParam --title "$2" --yesno "Install $2?" 6 55 + response=$? + + # Return to previous setting + set -e + case $response in + 0) res="true";; + 1) res="false";; + 255) exit;; + esac + else + if [ -z "$res" -o "$res" != "true" -a "$res" != "false" ]; then + read -p "Install $2 $askPrompt? " -n 1 -r + echo "" + if [[ $REPLY =~ ^[$nonDefaultMatch]$ ]]; then + res=$nonDefaultValue + else + res=$defaultValue + fi + fi + fi + if [ "$res" == "true" ]; then + echo -e "\e[1;32m$2 will be enabled\e[0m" + else + echo -e "\e[1;31m$2 will be skipped\e[0m" + fi + eval $1=\$res + return="$res" +} + +# Check to see if module is enabled +# checkModule +function checkModule { + eval res=\$$1 + if [ ! -z "$res" -a "$res" == "true" ]; then + echo "1" + else + echo "" + fi +} + # Get board information and set flags accordingly BOARD_FAMILY="Unknown" BOARD_NAME="Generic" @@ -112,220 +179,50 @@ if [[ -e '/etc/NetworkManager/NetworkManager.conf' ]]; then fi # Detect missing /sbin from $PATH variable on Debian distros, and add it -if [ -z $(echo $PATH | grep "/sbin") ]; then +if [ -z $(echo $PATH | grep "/sbin") ]; then # Current environment export PATH="/sbin:/usr/sbin:$PATH" # Next login echo 'export PATH="/sbin:/usr/sbin:$PATH"' | sudo tee -a /etc/profile fi +askModule "WITH_DIALOG" "Text User Interface?" "n" +if [ "$(checkModule 'WITH_DIALOG')" ]; then + sudo apt-get install dialog -y +fi + # Prompt and set missing flags -if [ -z "$WITH_MESH_POINT" -o "$WITH_MESH_POINT" != "true" -a "$WITH_MESH_POINT" != "false" ]; then - read -p "Configure Mesh Point interface (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mMesh Point interface configuration will be skipped\e[0m" - WITH_MESH_POINT=false - else - echo -e "\e[1;32mMesh Point interface will be configured\e[0m" - WITH_MESH_POINT=true - fi -fi +askModule "WITH_MESH_POINT" "Mesh Point Interface" if [ "$WITH_MESH_POINT" == false ]; then - if [ -z "$WITH_AD_HOC" -o "$WITH_AD_HOC" != "true" -a "$WITH_AD_HOC" != "false" ]; then - read -p "Configure Ad-hoc interface (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mAd-hoc interface configuration will be skipped\e[0m" - WITH_AD_HOC=false - else - echo -e "\e[1;32mAd-hoc interface will be configured\e[0m" - WITH_AD_HOC=true - fi - fi -else - echo -e "\e[1;31mAd-hoc interface configuration will be skipped\e[0m" - WITH_AD_HOC=false -fi -if [[ "$SUPPORT_HOSTAP" == "true" ]] && [ -z "$WITH_WIFI_AP" -o "$WITH_WIFI_AP" != "true" -a "$WITH_WIFI_AP" != "false" ]; then - read -p "Configure WiFi Access Point (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mWiFi Access Point configuration will be skipped\e[0m" - WITH_WIFI_AP=false - else - echo -e "\e[1;32mWiFi Access Point will be configured\e[0m" - WITH_WIFI_AP=true - fi -fi -if [ -z "$WITH_FIREWALL" -o "$WITH_FIREWALL" != "true" -a "$WITH_FIREWALL" != "false" ]; then - read -p "Configure Basic Firewall (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mInternet Firewall will be skipped\e[0m" - WITH_FIREWALL=false - else - echo -e "\e[1;32mInternet Firewall will be configured\e[0m" - WITH_FIREWALL=true - fi -fi -if [ -z "$WITH_CJDNS_IPTUNNEL" -o "$WITH_CJDNS_IPTUNNEL" != "true" -a "$WITH_CJDNS_IPTUNNEL" != "false" ]; then - read -p "Configure Internet gateway (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mInternet gateway configuration will be skipped\e[0m" - WITH_CJDNS_IPTUNNEL=false - else - echo -e "\e[1;32mInternet gateway will be configured\e[0m" - WITH_CJDNS_IPTUNNEL=true - fi + askModule "WITH_AD_HOC" "Ad-Hoc Interface" fi -if [ -z "$WITH_IPFS" -o "$WITH_IPFS" != "true" -a "$WITH_IPFS" != "false" ]; then - read -p "Install IPFS (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mIPFS installation will be skipped\e[0m" - WITH_IPFS=false - else - echo -e "\e[1;32mIPFS will be installed\e[0m" - WITH_IPFS=true - fi +if [ "$SUPPORT_HOSTAP" == "true" ]; then + askModule "WITH_WIFI_AP" "WiFi Access Point" fi +askModule "WITH_FIREWALL" "Basic Firewall" +askModule "WITH_CJDNS_IPTUNNEL" "Internet Gateway" +askModule "WITH_IPFS" "IPFS" if [ "$WITH_IPFS" == true -a "$BOARD_FAMILY" == "Raspberry Pi" ]; then - if [ -z "$WITH_IPFS_PI_STREAM" -o "$WITH_IPFS_PI_STREAM" != "true" -a "$WITH_IPFS_PI_STREAM" != "false" ]; then - read -p "Install IPFS Pi stream (y/N)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Yy]$ ]]; then - echo -e "\e[1;32mIPFS Pi stream will be installed\e[0m" - WITH_IPFS_PI_STREAM=true - else - echo -e "\e[1;31mIPFS Pi stream installation will be skipped\e[0m" - WITH_IPFS_PI_STREAM=false - fi - fi -fi -if [ -z "$WITH_SSB" -o "$WITH_SSB" != "true" -a "$WITH_SSB" != "false" ]; then - read -p "Install SSB (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mSSB installation will be skipped\e[0m" - WITH_SSB=false - else - echo -e "\e[1;32mSSB will be installed\e[0m" - WITH_SSB=true - fi -fi -if [ "$WITH_SSB" == true ]; then - if [ -z "$WITH_SSB_WEB" -o "$WITH_SSB_WEB" != "true" -a "$WITH_SSB_WEB" != "false" ]; then - read -p "Install SSB web client (Experimental) (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Yy]$ ]]; then - echo -e "\e[1;32mSSB web client will be installed\e[0m" - WITH_SSB_WEB=true - else - echo -e "\e[1;31mSSB web client installation will be skipped\e[0m" - WITH_SSB_WEB=false - fi - fi -fi -if [ -z "$WITH_YRD" -o "$WITH_YRD" != "true" -a "$WITH_YRD" != "false" ]; then - read -p "Install yrd (a cjdns command-line tool) (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31myrd installation will be skipped\e[0m" - WITH_YRD=false - else - echo -e "\e[1;32myrd will be installed\e[0m" - WITH_YRD=true - fi + askModule "WITH_IPFS_PI_STREAM" "IPFS Pi Stream" "n" fi -if [ -z "$WITH_PROMETHEUS_NODE_EXPORTER" -o "$WITH_PROMETHEUS_NODE_EXPORTER" != "true" -a "$WITH_PROMETHEUS_NODE_EXPORTER" != "false" ]; then - read -p "Install Prometheus Node Exporter (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mPrometheus Node Exporter installation will be skipped\e[0m" - WITH_PROMETHEUS_NODE_EXPORTER=false - else - echo -e "\e[1;32mPrometheus Node Exporter will be installed\e[0m" - WITH_PROMETHEUS_NODE_EXPORTER=true - fi +askModule "WITH_SSB" "SSB" +if [ "$WITH_SSB" == "true" ]; then + askModule "WITH_SSB_WEB" "SSB Web Client (Experimental)" "n" fi +askModule "WITH_YRD" "Yrd (a cjdns command-line tool)" +askModule "WITH_PROMETHEUS_NODE_EXPORTER" "Prometheus Node Exporter" if [ "$WITH_PROMETHEUS_NODE_EXPORTER" == true ]; then - if [ -z "$WITH_PROMETHEUS_SERVER" -o "$WITH_PROMETHEUS_SERVER" != "true" -a "$WITH_PROMETHEUS_SERVER" != "false" ]; then - read -p "Install Prometheus Server (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mPrometheus installation will be skipped\e[0m" - WITH_PROMETHEUS_SERVER=false - else - echo -e "\e[1;32mPrometheus Server will be installed\e[0m" - WITH_PROMETHEUS_SERVER=true - fi - fi -else - # Skip because Prometheus Node Exporter is not installed - WITH_PROMETHEUS_SERVER=false + askModule "WITH_PROMETHEUS_SERVER" "Prometheus Server" fi if [ "$WITH_PROMETHEUS_SERVER" == true ]; then - if [ -z "$WITH_GRAFANA" -o "$WITH_GRAFANA" != "true" -a "$WITH_GRAFANA" != "false" ]; then - read -p "Install Grafana (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mGrafana installation will be skipped\e[0m" - WITH_GRAFANA=false - else - echo -e "\e[1;32mGrafana will be installed\e[0m" - WITH_GRAFANA=true - fi - fi -else - # Skip because Prometheus Server is not installed - WITH_GRAFANA=false -fi -if [ -z "$WITH_H_DNS" -o "$WITH_H_DNS" != "true" -a "$WITH_H_DNS" != "false" ]; then - read -p "Configure Hyperboria-compatible Domain Name Servers (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mDNS settings will be skipped\e[0m" - WITH_H_DNS=false - else - echo -e "\e[1;32mDNS settings will be configured\e[0m" - WITH_H_DNS=true - fi + askModule "WITH_GRAFANA" "Grafana" fi -if [ -z "$WITH_H_NTP" -o "$WITH_H_NTP" != "true" -a "$WITH_H_NTP" != "false" ]; then - read -p "Configure Hyperboria-compatible Network Time Protocol server (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mNTP settings will be skipped\e[0m" - WITH_H_NTP=false - else - echo -e "\e[1;32mNTP settings will be configured\e[0m" - WITH_H_NTP=true - fi -fi -if [ -z "$WITH_EXTRA_TOOLS" -o "$WITH_EXTRA_TOOLS" != "true" -a "$WITH_EXTRA_TOOLS" != "false" ]; then - read -p "Install non-essential tools useful for network analysis (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mExtra tools will be skipped\e[0m" - WITH_EXTRA_TOOLS=false - else - echo -e "\e[1;32mExtra tools will be installed\e[0m" - WITH_EXTRA_TOOLS=true - fi -fi -if [[ "$SUPPORT_WATCHDOG" == "true" ]] && [ -z "$WITH_WATCHDOG" -o "$WITH_WATCHDOG" != "true" -a "$WITH_WATCHDOG" != "false" ]; then - read -p "Configure Hardware Watchdog (Y/n)? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Nn]$ ]]; then - echo -e "\e[1;31mHardware Watchdog configuration will be skipped\e[0m" - WITH_WATCHDOG=false - else - echo -e "\e[1;32mHardware Watchdog will be configured\e[0m" - WITH_WATCHDOG=true - fi +askModule "WITH_H_DNS" "Hyperboria Domain Name Servers" +askModule "WITH_H_NTP" "Hyperboria Network Time Protocol Server" +askModule "WITH_EXTRA_TOOLS" "Non-Essential Tools Useful for Network Analysis" +if [ "$SUPPORT_WATCHDOG" == "true" ]; then + askModule "WITH_WATCHDOG" "Hardware Watchdog" fi # Prompt for name of the mesh network @@ -414,84 +311,84 @@ fi sudo systemctl enable cjdns.service # 802.11s Mesh Point interface -if [ ! -z "$WITH_MESH_POINT" -a "$WITH_MESH_POINT" == "true" ]; then +if [ "$(checkModule 'WITH_MESH_POINT')" ]; then source mesh-point/install fi # IBSS Ad-hoc interface -if [ ! -z "$WITH_AD_HOC" -a "$WITH_AD_HOC" == "true" ]; then +if [ "$(checkModule 'WITH_AD_HOC')" ]; then source mesh-adhoc/install fi # WiFi Access Point on supported boards -if [[ "$SUPPORT_HOSTAP" == "true" ]] && [ ! -z "$WITH_WIFI_AP" -a "$WITH_WIFI_AP" == "true" ]; then +if [ "$SUPPORT_HOSTAP" == "true" -a "$(checkModule 'WITH_WIFI_AP')" ]; then source hostapd/install fi # Configure Internet firewall -if [ ! -z "$WITH_FIREWALL" -a "$WITH_FIREWALL" == "true" ]; then +if [ "$(checkModule 'WITH_FIREWALL')" ]; then source firewall/install fi # Configure Internet gateway using cjdns iptunnel -if [ ! -z "$WITH_CJDNS_IPTUNNEL" -a "$WITH_CJDNS_IPTUNNEL" == "true" ]; then +if [ "$(checkModule 'WITH_CJDNS_IPTUNNEL')" ]; then source cjdns-iptunnel/install fi # IPFS -if [ ! -x "$(command -v ipfs)" ] && [ ! -z "$WITH_IPFS" -a "$WITH_IPFS" == "true" ]; then +if [ ! -x "$(command -v ipfs)" -a "$(checkModule 'WITH_IPFS')" ]; then source ipfs/install fi # IPFS Pi Stream -if [ ! -x "$(command -v process-stream.sh)" ] && [ ! -z "$WITH_IPFS_PI_STREAM" -a "$WITH_IPFS_PI_STREAM" == "true" ]; then +if [ ! -x "$(command -v process-stream.sh)" -a "$(checkModule 'WITH_IPFS_PI_STREAM')" ]; then source ipfs-pi-stream/install fi # SSB -if [ ! -x "$(command -v sbot)" ] && [ ! -z "$WITH_SSB" -a "$WITH_SSB" == "true" ]; then +if [ ! -x "$(command -v sbot)" -a "$(checkModule 'WITH_SSB')" ]; then source ssb/install fi # SSB Web (logic inverted. Install if sbot exists only) -if [ -x "$(command -v sbot)" ] && [ ! -z "$WITH_SSB_WEB" -a "$WITH_SSB_WEB" == "true" ]; then +if [ -x "$(command -v sbot)" -a "$(checkModule 'WITH_SSB_WEB')" ]; then source ssb-web/install fi # yrd -if [ ! -x "$(command -v yrd)" ] && [ ! -z "$WITH_YRD" -a "$WITH_YRD" == "true" ]; then +if [ ! -x "$(command -v yrd)" -a "$(checkModule 'WITH_YRD')" ]; then source yrd/install fi # Prometheus Node Exporter -if [ ! -x "$(command -v node_exporter)" ] && [ ! -z "$WITH_PROMETHEUS_NODE_EXPORTER" -a "$WITH_PROMETHEUS_NODE_EXPORTER" == "true" ]; then +if [ ! -x "$(command -v node_exporter)" -a "$(checkModule 'WITH_PROMETHEUS_NODE_EXPORTER')" ]; then source prometheus-node-exporter/install fi # Prometheus Server -if [ ! -x "$(command -v /opt/prometheus/prometheus)" ] && [ ! -z "$WITH_PROMETHEUS_SERVER" -a "$WITH_PROMETHEUS_SERVER" == "true" ]; then +if [ ! -x "$(command -v /opt/prometheus/prometheus)" -a "$(checkModule 'WITH_PROMETHEUS_SERVER')" ]; then source prometheus-server/install fi # Grafana -if [ ! -x "$(command -v /usr/sbin/grafana-server)" ] && [ ! -z "$WITH_GRAFANA" -a "$WITH_GRAFANA" == "true" ]; then +if [ ! -x "$(command -v /usr/sbin/grafana-server)" -a "$(checkModule 'WITH_GRAFANA')" ]; then source grafana/install fi # Configure Hyperboria DNS -if [ ! -z "$WITH_H_DNS" -a "$WITH_H_DNS" == "true" ]; then +if [ "$(checkModule 'WITH_H_DNS')" ]; then source h-dns/install fi # Configure Hyperboria NTP -if [ ! -z "$WITH_H_NTP" -a "$WITH_H_NTP" == "true" ]; then +if [ "$(checkModule 'WITH_H_NTP')" ]; then source h-ntp/install fi # Non-essential extra tools -if [ ! -z "$WITH_EXTRA_TOOLS" -a "$WITH_EXTRA_TOOLS" == "true" ]; then +if [ "$(checkModule 'WITH_EXTRA_TOOLS')" ]; then source extra-tools/install fi # Watchdog on supported boards -if [[ "$SUPPORT_WATCHDOG" == "true" ]] && [ ! -z "$WITH_WATCHDOG" -a "$WITH_WATCHDOG" == "true" ]; then +if [ "$SUPPORT_WATCHDOG" == "true" -a "$(checkModule 'WITH_WATCHDOG')" ]; then source watchdog/install fi @@ -523,3 +420,4 @@ read -p "Installation complete. Press any key to reboot your new node. " -n 1 -r # Reboot device sudo reboot + From b10604ff3898b36926f4b32bdc06b90040e5a0b9 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Sep 2018 11:08:31 -0400 Subject: [PATCH 003/162] Cjdns Verison bump (#191) - Bump version - Update status screen for new CJDNS peerStatus - Updated other scripts using Peerstats - Updated location of cjdns package --- scripts/install2 | 14 +++++++------- scripts/ipfs/ipfs-swarm-cjdns.sh | 2 +- .../prometheus-node-exporter/nodestats-tomesh.py | 4 ++-- scripts/status | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/install2 b/scripts/install2 index 6414cebc5..0db76d395 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -2,7 +2,7 @@ set -e -TAG_CJDNS=186169f9a8631633795e4e9d70c501519a7800f4 +TAG_CJDNS=d2e55d58548d83940482fe1bbbe1fd36f7f1b4ef dialogGlobalParams="--backtitle Installation --ascii-lines" # Ask if module is to be enabled if not defined @@ -106,7 +106,7 @@ if [[ "$BOARD_HARDWARE" == 'Allwinner' || "$BOARD_HARDWARE" == 'Generic' ]]; the fi #TODO# -O2 workaround. Needs to be resolved. CJDNS_BUILD_CMD="sudo Seccomp_NO=1 CFLAGS=\"-O2 -s -static -Wall -march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -fomit-frame-pointer -marm\" ./do" - CJDNS_PACKAGE="cjdns-neon.deb" + CJDNS_PACKAGE="cjdns-neon-v4.deb" elif [[ "$BOARD_HARDWARE" == 'nanopineo2' || "$BOARD_HARDWARE" == 'sun50iw1p1' || "$BOARD_HARDWARE" == 'orangepizeroplus2-h5' || "$BOARD_HARDWARE" == 'rock64' || @@ -133,11 +133,11 @@ else elif [[ $BOARD_REVISION == *"a01041"* || $BOARD_REVISION == *"a21041"* ]]; then BOARD_NAME="2" CJDNS_BUILD_CMD="sudo NO_TEST=1 CFLAGS=\"-mfpu=neon-vfpv4 -O2\" ./do" - CJDNS_PACKAGE="cjdns-neon.deb" + CJDNS_PACKAGE="cjdns-neon-v4.deb" elif [[ $BOARD_REVISION == *"a02082"* || $BOARD_REVISION == *"a22082"* ]]; then BOARD_NAME="3" CJDNS_BUILD_CMD="sudo CFLAGS=\"-march=armv8-a+crc -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard -O2\" ./do" - CJDNS_PACKAGE="cjdns-neon.deb" + CJDNS_PACKAGE="cjdns-neon-v4.deb" # Raspberry Pi 3 has on-board WiFi that can be used as an AP SUPPORT_HOSTAP=true # Raspberry Pi 3 has hardware watchdog @@ -145,7 +145,7 @@ else elif [[ $BOARD_REVISION == *"a020d3"* ]]; then BOARD_NAME="3b+" CJDNS_BUILD_CMD="sudo CFLAGS=\"-march=armv8-a+crc -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard -O2\" ./do" - CJDNS_PACKAGE="cjdns-neon.deb" + CJDNS_PACKAGE="cjdns-neon-v4.deb" # Raspberry Pi 3 has on-board WiFi that can be used as an AP SUPPORT_HOSTAP=true # Raspberry Pi 3 has hardware watchdog @@ -263,8 +263,8 @@ fi if [ ! -z "$CJDNS_PACKAGE" ]; then if ! [ -x "/opt/cjdns/cjdroute" ]; then - echo -e "\e[1;31mInstalling cjdns Debian package\e[0m" - wget https://github.com/darkdrgn2k/ToMeshStuff/raw/master/deb/$CJDNS_PACKAGE -O /tmp/cjdns.deb + echo -e "\e[1;31mInstalling cjdns debian package\e[0m" + wget https://github.com/darkdrgn2k/ToMeshPackages/raw/master/CJDNS/$CJDNS_PACKAGE -O /tmp/cjdns.deb sudo dpkg -i /tmp/cjdns.deb #Link up folder so files are in the same place as compiled if [[ -e "/opt/cjdns" ]]; then diff --git a/scripts/ipfs/ipfs-swarm-cjdns.sh b/scripts/ipfs/ipfs-swarm-cjdns.sh index 929445618..bca0fe14e 100644 --- a/scripts/ipfs/ipfs-swarm-cjdns.sh +++ b/scripts/ipfs/ipfs-swarm-cjdns.sh @@ -30,7 +30,7 @@ while read -r cjdns_peer; do # XXX: The below command hasn't been working -- so for now only 1-hop peers are checked #peers+=$(cjdnstool query getpeers $peer | sed -e '1d;$d' |awk -F. '{ print $6".k" }') -done <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($2 == "ESTABLISHED") print $1 }' | awk -F. '{ print $6".k" }' | xargs` +done <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs` # Update peers data since ipfs just started sudo /usr/local/bin/nodeinfo-update.sh diff --git a/scripts/prometheus-node-exporter/nodestats-tomesh.py b/scripts/prometheus-node-exporter/nodestats-tomesh.py index 2ee778564..aab824812 100644 --- a/scripts/prometheus-node-exporter/nodestats-tomesh.py +++ b/scripts/prometheus-node-exporter/nodestats-tomesh.py @@ -71,7 +71,7 @@ linkstatus="" rx=-1 tx=-1 - signal=-100 + signal=-100 if words3[1].find("signal") > -1: signal=words3[3] if words3[1].find("mesh") > -1 and words3[2].find("plink") > -1: @@ -86,4 +86,4 @@ fifo.write('mesh_node_tx{sourcemac="' + mac + '",mac="' + station + '"} ' + tx + "\n") fifo.close() - time.sleep(1) \ No newline at end of file + time.sleep(1) diff --git a/scripts/status b/scripts/status index dbd4c71c4..f3d2dfa73 100755 --- a/scripts/status +++ b/scripts/status @@ -104,7 +104,7 @@ echo -e 'NODE' sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g' echo -e '---------------------------------------' echo -e 'PEERS' -read -a peers <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($2 == "ESTABLISHED") print $1 }' | awk -F. '{ print $6".k" }' | xargs` +read -a peers <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs` for peer in "${peers[@]}"; do sudo /opt/cjdns/publictoip6 $peer done From fc238c3a170bb467121e59aed066942629558613 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 21 Sep 2018 19:27:31 -0400 Subject: [PATCH 004/162] Script Cleanup, ShellCheck and Travis * Apply ShellCheck cleanup * Nginx share module more resilient to reinstall by checking not only if nginx is installed but also if the path was made. This should help identify when the shared module is not properly installed. * a few || trues to help with Re-installs * Formatting issues * Wrapped in quotes * Unused variable * Travis * Corrections to scripts, Addition of Arm64 to Grafana * Support for Pine64 * Version bump for Grafana install --- .travis.yml | 10 ++ README.md | 29 +++--- scripts/extra-tools/install | 2 - scripts/grafana/install | 22 +++-- scripts/h-dns/install | 2 - scripts/h-ntp/install | 2 - scripts/hostapd/install | 23 ++--- scripts/install | 2 +- scripts/install2 | 94 ++++++++++--------- scripts/ipfs-pi-stream/enable-camera.sh | 2 +- scripts/ipfs-pi-stream/install | 8 +- scripts/ipfs-pi-stream/process-stream.sh | 59 ++++++------ scripts/ipfs/install | 8 +- scripts/ipfs/ipfs-swarm-cjdns.sh | 10 +- scripts/prometheus-node-exporter/install | 6 +- .../nodestats-tomesh.py | 2 +- scripts/prometheus-server/install | 7 +- scripts/shared/nginx/install | 11 +-- scripts/shared/nodeinfo/install | 4 +- scripts/ssb-web/install | 11 ++- scripts/ssb-web/ssb-web-broadcast-service.sh | 10 +- scripts/ssb/ssb-broadcast-service.sh | 10 +- scripts/status | 20 ++-- 23 files changed, 192 insertions(+), 162 deletions(-) diff --git a/.travis.yml b/.travis.yml index bdc85a22d..039685f83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,16 @@ env: - DISTRO=latest script: + # Run shellcheck on branch + - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) + - echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR, BRANCH=$BRANCH" + - git clone https://github.com/tomeshnet/prototype-cjdns-pi.git + - cd prototype-cjdns-pi/scripts + - git checkout ${BRANCH} + - bash -c 'shopt -s globstar; shellcheck -x install install2 */install **/*.sh' + - cd ../.. + + # Build docker for ARM tests - cp /usr/bin/qemu-arm-static travis/${DISTRO}/ - docker build -t tomeshnet/prototype-cjdns-pi:${DISTRO} travis/${DISTRO}/ diff --git a/README.md b/README.md index 7cfe3c5c4..ae50445e7 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Many board that run [Armbian](https://www.armbian.com/) such as many models of O | `WITH_IPFS` | **80**: HTTP-to-IPFS gateway at `/ipfs/HASH` | Set to `true` if you want to install [IPFS](https://ipfs.io). | | `WITH_IPFS_PI_STREAM` | None | Set to `true` if you want to install Pi stream service to live stream your camera over IPFS. Requires a Raspberry Pi with camera module. *Will automatically start recording on boot by default.* | | `WITH_SSB` | | Set to `true` if you want to install [Scuttlebot (SSB)](https://github.com/ssbc/scuttlebot) a secure scuttlebutt daemon. | -| `WITH_SSB_WEB` | **80**: SSB web interface at `/sbot` | Set to `true` if you want to install [SSB Web Pi](https://github.com/darkdrgn2k/ssb-web-pi),which allows you to interact with the scuttlebot backend with a web interface. | +| `WITH_SSB_WEB` | **80**: SSB web interface at `/sbot` | Set to `true` if you want to install [SSB Web Pi](https://github.com/darkdrgn2k/ssb-web-pi),which allows you to interact with the scuttlebot backend with a web interface. | | `WITH_PROMETHEUS_NODE_EXPORTER` | **9100**: Node Exporter UI | Set to `true` if you want to install [Prometheus Node Exporter](https://github.com/prometheus/node_exporter) to report network metrics. | | `WITH_PROMETHEUS_SERVER` | **9090**: Prometheus Server UI | Set to `true` if you want to install [Prometheus Server](https://github.com/prometheus/prometheus) to collect network metrics. *Requires Prometheus Node Exporter.* | | `WITH_GRAFANA` | **3000**: Grafana UI (login: admin/admin) | Set to `true` if you want to install [Grafana](https://grafana.com) to display network metrics. *Requires Prometheus Server.* | @@ -103,19 +103,20 @@ List of tested hardware: | Hardware | Base OS | [CJDNS Benchmark](https://github.com/phillymesh/cjdns-optimizations) (salsa20/poly1305, switching) | iPerf3 | USB | Ethernet | Notes | | :-------------------------|:----------------|:--------------------------------------------------------------------------------------------------------------|:-------|:----|:---------|:---------| -| Raspberry Pi 3b+ | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 405k, 119k | ~90 Mbps | 2 | 10/100/1000 | Eth only 320mbps. Cjdns speed unstable. Dual band | -| Raspberry Pi 3b | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 350k, 100k | 89 Mbps | 2 | 10/100 | | -| Raspberry Pi 2 | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 145k, 55k | 39 Mbps | 2 | 10/100 | | -| Raspberry Pi 1 A+ | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 35k, - | ~9 Mbps | 1 | None | | -| Raspberry Pi 1 B+ | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 51k, 22k | ~9 Mbps | 2 | 10/100 | | -| Raspberry Pi Zero | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 68k, 30k | ~9 Mbps | 1* | None | *Need OTG Cable No FPV | -| Orange Pi Lite | [Armbian Nightly](https://dl.armbian.com/orangepilite/nightly/) | 160k, 74k | 67 Mbps | 2 | None | | -| Orange Pi One | [Armbian Nightly](https://dl.armbian.com/orangepione/nightly/) | 160k, 74k | 67 Mbps | 1 | 10/100 | | -| Orange Pi Zero | [Armbian Nightly](https://dl.armbian.com/orangepizero/nightly/) | 160k, 74k | 67 Mbps | 1 (+2*) | 10/100 | *USB Headers | -| Orange Pi Zero Plus 2 H5 | [Armbian Nightly](https://dl.armbian.com/orangepizeroplus2-h5/nightly/) | 190k, 130K | 80 Mbps | 0 (+2*) | None | *USB Headers | -| NanoPi Neo 2 | [Armbian Nightly](https://dl.armbian.com/nanopineo2/nightly/) | 160k, 95K | 67 Mbps | 1 (+2*) | 10/100/1000 | *USB Headers, Gigabit Eth | -| Rock64 | [Armbian Nightly](https://dl.armbian.com/rock64/nightly/) | 255k, 168K | 94 Mbps | 3 | 10/100/1000 | 1 USB 3.0, Gigabit Eth | -| EspressoBin | [Armbian](https://dl.armbian.com/espressobin/) | 186k, 128K | 73 Mbps | 2 | 10/100/1000 | 1 USB 3.0, 3x Gigabit Eth, Sata, mPCIE. Use stable and apt-get upgrade after boot | +| Raspberry Pi 3b+ | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 405k, 119k | ~90 Mbps| 2 | 10/100/1000 | Eth only 320mbps. Cjdns speed unstable. Dual band | +| Raspberry Pi 3b | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 350k, 100k | 89 Mbps | 2 | 10/100 | | +| Raspberry Pi 2 | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 145k, 55k | 39 Mbps | 2 | 10/100 | | +| Raspberry Pi 1 A+ | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 35k, - | ~9 Mbps | 1 | None | | +| Raspberry Pi 1 B+ | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 51k, 22k | ~8 Mbps | 2 | 10/100 | | +| Raspberry Pi Zero | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 68k, 30k | ~9 Mbps | 1* | None | *Need OTG Cable No FPV | +| Orange Pi Lite | [Armbian](https://dl.armbian.com/orangepilite/) | 160k, 74k | 67 Mbps | 2 | None | | +| Orange Pi One | [Armbian](https://dl.armbian.com/orangepione/) | 160k, 74k | 67 Mbps | 1 | 10/100 | | +| Orange Pi Zero | [Armbian](https://dl.armbian.com/orangepizero/) | 160k, 74k | 67 Mbps | 1 (+2*) | 10/100 | *USB Headers | +| Orange Pi Zero Plus 2 H5 | [Armbian](https://dl.armbian.com/orangepizeroplus2-h5/) | 190k, 130K | 80 Mbps | 0 (+2*) | None | *USB Headers | +| NanoPi Neo 2 | [Armbian](https://dl.armbian.com/nanopineo2/) | 160k, 95K | 67 Mbps | 1 (+2*) | 10/100/1000 | *USB Headers, Gigabit Eth | +| Rock64 | [Armbian](https://dl.armbian.com/rock64/) | 255k, 168K | 94 Mbps | 3 | 10/100/1000 | 1 USB 3.0, Gigabit Eth | +| Pine64 | [Armbian](https://dl.armbian.com/pine/nightly/) | 227k, 151k | 78 Mbps | 2 | 10/100/1000 | Gigabit Eth | +| EspressoBin | [Armbian](https://dl.armbian.com/espressobin/) | 186k, 128K | 73 Mbps | 2 | 10/100/1000 | 1 USB 3.0, 3x Gigabit Eth, Sata, mPCIE. Use stable and apt-get upgrade after boot | ## Development diff --git a/scripts/extra-tools/install b/scripts/extra-tools/install index 11bfe36f7..e6abbdd40 100755 --- a/scripts/extra-tools/install +++ b/scripts/extra-tools/install @@ -2,7 +2,5 @@ set -e -BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - # Install non-essential tools useful for network analysis sudo apt-get install vim socat oping bmon iperf3 -y diff --git a/scripts/grafana/install b/scripts/grafana/install index 208f089ed..0461342e1 100755 --- a/scripts/grafana/install +++ b/scripts/grafana/install @@ -2,18 +2,24 @@ set -e +GRAFANA_VERSION=5.1.4 + BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Install Grafana dependencies sudo apt-get install libfontconfig1 fontconfig-config fonts-dejavu-core ttf-bitstream-vera fonts-liberation sqlite3 -y # Download and install unofficial build of Grafana for ARM -URL="https://bintray.com/fg2it/deb/download_file?file_path=main%2Fg%2Fgrafana_4.3.2_armhf.deb" -if $(uname -m | grep -Eq ^armv6); then - URL="https://bintray.com/fg2it/deb-rpi-1b/download_file?file_path=main%2Fg%2Fgrafana_4.3.2_armhf.deb" +URL="https://bintray.com/fg2it/deb/download_file?file_path=main%2Fg%2Fgrafana_${GRAFANA_VERSION}_armhf.deb" +if uname -m | grep -Eq ^armv6; then + # Raspberry Pi 1 + URL="https://bintray.com/fg2it/deb-rpi-1b/download_file?file_path=main%2Fg%2Fgrafana_${GRAFANA_VERSION}_armhf.deb" +elif uname -m | grep -Eq ^aarch64; then + URL="https://bintray.com/fg2it/deb-arm64/download_file?file_path=main%2Fg%2Fgrafana_${GRAFANA_VERSION}_arm64.deb" fi -mkdir "$BASE_DIR/tmp" -wget ${URL} -O "$BASE_DIR/tmp/go-grafana.tar.gz" + +mkdir "$BASE_DIR/tmp" || true +wget "${URL}" -O "$BASE_DIR/tmp/go-grafana.tar.gz" sudo dpkg -i "$BASE_DIR/tmp/go-grafana.tar.gz" rm -rf "$BASE_DIR/tmp" @@ -28,9 +34,9 @@ sleep 30 # Add data source and dashboard # Check if port grafana is being listend in on if so configure if not notify and continue -if [ ! -z "$(netstat --tcp -n | grep :3000)" ]; then - curl --user admin:admin -X POST -H 'Content-Type: application/json' --data-binary @$BASE_DIR/datasource.json http://localhost:3000/api/datasources - curl --user admin:admin -X POST -H 'Content-Type: application/json' --data-binary @$BASE_DIR/dashboard.json http://localhost:3000/api/dashboards/db +if netstat --tcp -n -l | grep -q :3000; then + curl --user admin:admin -X POST -H 'Content-Type: application/json' --data-binary "@$BASE_DIR/datasource.json" http://localhost:3000/api/datasources + curl --user admin:admin -X POST -H 'Content-Type: application/json' --data-binary "@$BASE_DIR/dashboard.json" http://localhost:3000/api/dashboards/db else echo -e "\e[1;31mGrafana is taking longer than normal to start\e[0m" echo -e "\e[1;31mSkipping configuration and continuing install\e[0m" diff --git a/scripts/h-dns/install b/scripts/h-dns/install index b8cd20484..3400489a7 100755 --- a/scripts/h-dns/install +++ b/scripts/h-dns/install @@ -6,8 +6,6 @@ H_DNS_SERVER_0="fc4d:c8e5:9efe:9ac2:8e72:fcf7:6ce8:39dc" H_DNS_SERVER_1="fc6e:691e:dfaa:b992:a10a:7b49:5a1a:5e09" H_DNS_SERVER_2="fc16:b44c:2bf9:467:8098:51c6:5849:7b4f" -BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - # Configure Hyperboria DNS sudo sed -i '/dns-nameservers /d' /etc/network/interfaces echo "" | sudo tee --append /etc/network/interfaces > /dev/null diff --git a/scripts/h-ntp/install b/scripts/h-ntp/install index bfe29acbb..8de9eda79 100755 --- a/scripts/h-ntp/install +++ b/scripts/h-ntp/install @@ -5,8 +5,6 @@ set -e H_NTP_SERVER1="fc4d:c8e5:9efe:9ac2:8e72:fcf7:6ce8:39dc" H_NTP_SERVER2="fc41:47b9:dd78:ff21:1b24:dab8:3f81:168e" -BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - # Install NTP if [ ! -x "$(command -v ntpd)" ]; then sudo apt-get install ntp -y diff --git a/scripts/hostapd/install b/scripts/hostapd/install index 1b8d78c88..1659b1fc5 100755 --- a/scripts/hostapd/install +++ b/scripts/hostapd/install @@ -57,12 +57,12 @@ echo "" if [[ $REPLY =~ ^[Nn]$ ]]; then USE_EAP=false while [ "${#APPASS}" -lt 8 ] || [ "${#APPASS}" -gt 63 ]; do - read -p "Set WPA2-PSK password (8-63 characters): " APPASS; + read -r -p "Set WPA2-PSK password (8-63 characters): " APPASS; done else USE_EAP=true while [ "${#APPASS}" -lt 8 ] || [ "${#APPASS}" -gt 63 ]; do - read -p "Set WPA-EAP password (8-63 characters) for user \"guest\": " APPASS; + read -r -p "Set WPA-EAP password (8-63 characters) for user \"guest\": " APPASS; done fi @@ -95,11 +95,11 @@ fi # Use Hyperboria DNS addressses if h-dns is enabled sudo cp "$BASE_DIR/dnsmasq.conf" /etc/dnsmasq.conf -if [ ! -z "$WITH_H_DNS" -a "$WITH_H_DNS" == "true" ]; then +if [ ! -z "$WITH_H_DNS" ] && [ "$WITH_H_DNS" == "true" ]; then echo "server=$H_DNS_SERVER_0" | sudo tee --append /etc/dnsmasq.conf echo "server=$H_DNS_SERVER_1" | sudo tee --append /etc/dnsmasq.conf echo "server=$H_DNS_SERVER_2" | sudo tee --append /etc/dnsmasq.conf -elif [ ! -z "$WITH_CJDNS_IPTUNNEL" -a "$WITH_CJDNS_IPTUNNEL" ]; then +elif [ ! -z "$WITH_CJDNS_IPTUNNEL" ] && [ "$WITH_CJDNS_IPTUNNEL" ]; then echo "server=$I_DNS_SERVER_0" | sudo tee --append /etc/dnsmasq.conf echo "server=$I_DNS_SERVER_1" | sudo tee --append /etc/dnsmasq.conf fi @@ -127,20 +127,21 @@ sudo systemctl daemon-reload sudo systemctl enable hostapd.service # Find onboard adapter by driver and lock to wlan-ap -for wlan in $(ls -1Atu /sys/class/net | grep wlan); do - driver="$(basename $(readlink /sys/class/net/$wlan/device/driver))" - mac="$(cat /sys/class/net/$wlan/address)" +for wlan in $(find /sys/class/net -maxdepth 1 -name 'wlan*' | xargs -0 basename); do + driverPath=$(readlink "/sys/class/net/$wlan/device/driver") + driver=$(basename "$driverPath") +# mac="$(cat /sys/class/net/$wlan/address)" if [[ "$driver" == "xradio_wlan" || "$driver" == "brcm80211" || "$driver" == "brcmfmac" ]]; then - echo SUBSYSTEM==\"net\", ACTION==\"add\", DRIVERS==\"$driver\", ATTR{dev_id}==\"0x0\", ATTR{type}==\"1\", KERNEL==\"wlan*\", NAME=\"wlan-ap\" | + echo "SUBSYSTEM==\"net\", ACTION==\"add\", DRIVERS==\"$driver\", ATTR{dev_id}==\"0x0\", ATTR{type}==\"1\", KERNEL==\"wlan*\", NAME=\"wlan-ap\"" | sudo tee /etc/udev/rules.d/70-persistent-net.rules fi done # dnsmasq for some reason won't bind to the hostapd on Orange Pi, restarting it works -if [[ -z "$(cat /etc/rc.local | grep dnsmasq)" ]]; then +if ! grep -q dnsmasq /etc/rc.local; then sudo sed -i 's/^exit 0/service dnsmasq restart\nexit 0/' /etc/rc.local fi -if [[ -z "$(cat /etc/rc.local | grep rfkill)" ]]; then +if ! grep -q rfkill /etc/rc.local; then sudo sed -i 's/^exit 0/rfkill unblock wifi \&\& service hostapd restart\nexit 0/' /etc/rc.local -fi +fi \ No newline at end of file diff --git a/scripts/install b/scripts/install index 5fead4dc1..71e7653ad 100755 --- a/scripts/install +++ b/scripts/install @@ -12,7 +12,7 @@ if [ -z "$TAG_PROTOTYPE_CJDNS_PI" ]; then TAG_PROTOTYPE_CJDNS_PI=master fi -if ! [ -z "`ps xa | awk '{print $5}' | grep dpkg | grep -v grep`" ]; then +if ps xa | awk '{print $5}' | grep -q dpkg; then echo -e "\e[1;31mDPKG is running in the background.\e[0m" read -p "Would you like to KILL it to continue (Y/n)? " -n 1 -r echo "" diff --git a/scripts/install2 b/scripts/install2 index 0db76d395..9a631b1dd 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -25,23 +25,25 @@ function askModule { fi # This reads variable repersented by the string - eval res=\$$1 + eval "res=\$$1" if [ "$(checkModule 'WITH_DIALOG')" ]; then + # Do not stop exec on non 0 return values set +e + # shellcheck disable=SC2086 dialog $dialogGlobalParams $dialogParam --title "$2" --yesno "Install $2?" 6 55 response=$? - # Return to previous setting set -e + case $response in 0) res="true";; 1) res="false";; 255) exit;; esac else - if [ -z "$res" -o "$res" != "true" -a "$res" != "false" ]; then + if [ -z "$res" ] || [ "$res" != "true" ] && [ "$res" != "false" ]; then read -p "Install $2 $askPrompt? " -n 1 -r echo "" if [[ $REPLY =~ ^[$nonDefaultMatch]$ ]]; then @@ -56,15 +58,14 @@ function askModule { else echo -e "\e[1;31m$2 will be skipped\e[0m" fi - eval $1=\$res - return="$res" + eval "$1=\$res" } # Check to see if module is enabled # checkModule function checkModule { - eval res=\$$1 - if [ ! -z "$res" -a "$res" == "true" ]; then + eval "res=\$$1" + if [ ! -z "$res" ] && [ "$res" == "true" ]; then echo "1" else echo "" @@ -78,7 +79,7 @@ BOARD_REVISION="?" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 ./do" ##TODO## Possibly use /sys/firmware/devicetree/base/model -BOARD_HARDWARE=$(cat /proc/cpuinfo | grep Hardware | awk '{print $3}' | head -n 1) +BOARD_HARDWARE=$(grep Hardware /proc/cpuinfo | awk '{print $3}' | head -n 1) # Flag to identify if board can support on-board AP. Default to false. SUPPORT_HOSTAP=false @@ -87,7 +88,7 @@ CJDNS_PACKAGE="" # If board cannot be determined from /proc/cpuinfo its most likely an arbmian board so you can use the armbian generated ID file if [[ -z "$BOARD_HARDWARE" ]]; then - BOARD_HARDWARE="$(grep "BOARD=" /etc/armbian-image-release | awk -F \= '{print $2}' | tr -d \" | sed 's/Orange Pi //g')" + BOARD_HARDWARE="$(grep "BOARD=" /etc/armbian-image-release | awk -F '=' '{print $2}' | tr -d \" | sed 's/Orange Pi //g')" fi if [[ "$BOARD_HARDWARE" == 'Allwinner' || "$BOARD_HARDWARE" == 'Generic' ]]; then @@ -95,11 +96,11 @@ if [[ "$BOARD_HARDWARE" == 'Allwinner' || "$BOARD_HARDWARE" == 'Generic' ]]; the sudo service unattended-upgrades stop || true sudo killall unattended-upgrade || true BOARD_FAMILY="Orange Pi" - BOARD_NAME=$(grep BOARD_NAME /etc/armbian-image-release | awk -F \= '{print $2}' | tr -d \" | sed 's/Orange Pi //g') + BOARD_NAME=$(grep BOARD_NAME /etc/armbian-image-release | awk -F '=' '{print $2}' | tr -d \" | sed 's/Orange Pi //g') BOARD_REVISION="experimental" if [[ "$BOARD_NAME" == "Zero" ]]; then # AP is supported if board already supports XRadio - if [ "$(lsmod | grep xradio_wlan)" ]; then + if lsmod | grep -q xradio_wlan; then SUPPORT_HOSTAP=true fi SUPPORT_WATCHDOG=true @@ -110,12 +111,13 @@ if [[ "$BOARD_HARDWARE" == 'Allwinner' || "$BOARD_HARDWARE" == 'Generic' ]]; the elif [[ "$BOARD_HARDWARE" == 'nanopineo2' || "$BOARD_HARDWARE" == 'sun50iw1p1' || "$BOARD_HARDWARE" == 'orangepizeroplus2-h5' || "$BOARD_HARDWARE" == 'rock64' || + "$BOARD_HARDWARE" == 'Pine64+' || "$BOARD_HARDWARE" == 'espressobin' ]]; then # Stop unattended upgrade that will block apt-get requests on some armbian boards sudo service unattended-upgrades stop || true sudo killall unattended-upgrade || true BOARD_FAMILY="" - BOARD_NAME=$(grep BOARD_NAME /etc/armbian-image-release | awk -F \= '{print $2}' | tr -d \" | sed 's/Orange Pi //g') + BOARD_NAME=$(grep BOARD_NAME /etc/armbian-image-release | awk -F '=' '{print $2}' | tr -d \" | sed 's/Orange Pi //g') BOARD_REVISION="experimental" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 CFLAGS=\"-s -static -Wall -march=armv8-a+crc+crypto -fomit-frame-pointer\" ./do" if [[ "$BOARD_HARDWARE" == "orangepizeroplus2-h5" ]]; then @@ -123,7 +125,7 @@ elif [[ "$BOARD_HARDWARE" == 'nanopineo2' || "$BOARD_HARDWARE" == 'sun50iw1p1' | fi else BOARD_FAMILY="Raspberry Pi" - BOARD_REVISION=`sed -rn 's/Revision\s+\:\s+([0-9a-z_\-\s\,\(\)]+)/\1/p' /proc/cpuinfo` + BOARD_REVISION="$(sed -rn 's/Revision\s+\:\s+([0-9a-z_\-\s\,\(\)]+)/\1/p' /proc/cpuinfo)" if [[ $BOARD_REVISION == *"900092"* || $BOARD_REVISION == *"900093"* || $BOARD_REVISION == *"9000c1"* ]]; then BOARD_NAME="Zero" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 NO_TEST=1 CFLAGS=\"-s -mfpu=vfp -O2\" ./do" @@ -172,18 +174,18 @@ fi # Disable NetworkManager management of wlan0 so it doesn't pause it to scan every 60 seconds if [[ -e '/etc/NetworkManager/NetworkManager.conf' ]]; then - if [[ -z "$(grep "\[keyfile\]" /etc/NetworkManager/NetworkManager.conf)" ]]; then + if ! grep -q "\[keyfile\]" /etc/NetworkManager/NetworkManager.conf; then echo "[keyfile]" | sudo tee --append /etc/NetworkManager/NetworkManager.conf > /dev/null echo "unmanaged-devices=interface-name:wlan0" | sudo tee --append /etc/NetworkManager/NetworkManager.conf > /dev/null fi fi - + # Detect missing /sbin from $PATH variable on Debian distros, and add it -if [ -z $(echo $PATH | grep "/sbin") ]; then +if ! echo "$PATH" | grep -q "/sbin" ; then # Current environment export PATH="/sbin:/usr/sbin:$PATH" # Next login - echo 'export PATH="/sbin:/usr/sbin:$PATH"' | sudo tee -a /etc/profile + echo "export PATH=\"/sbin:/usr/sbin:$PATH\"" | sudo tee -a /etc/profile fi askModule "WITH_DIALOG" "Text User Interface?" "n" @@ -203,7 +205,7 @@ fi askModule "WITH_FIREWALL" "Basic Firewall" askModule "WITH_CJDNS_IPTUNNEL" "Internet Gateway" askModule "WITH_IPFS" "IPFS" -if [ "$WITH_IPFS" == true -a "$BOARD_FAMILY" == "Raspberry Pi" ]; then +if [ "$WITH_IPFS" == true ] && [ "$BOARD_FAMILY" == "Raspberry Pi" ]; then askModule "WITH_IPFS_PI_STREAM" "IPFS Pi Stream" "n" fi askModule "WITH_SSB" "SSB" @@ -228,15 +230,16 @@ fi # Prompt for name of the mesh network ##TODO## This should be moved up to to mesh point question read -p "Enter the name of your mesh network (default: tomesh): " -r -export MESH_NAME=`echo $REPLY | sed 's/ //g'` +MESH_NAME="${REPLY// }" if [ "${#MESH_NAME}" == 0 ]; then - export MESH_NAME="tomesh" + MESH_NAME="tomesh" fi +export MESH_NAME # Get tools if ! [ "$(which nodejs)" ]; then # Check for armv6 and install nodejs manually instead since it will not install via repo - if $(uname -m | grep -Eq ^armv6); then + if uname -m | grep -Eq ^armv6; then wget -O /tmp/node-v6.11.0-linux-armv6l.tar.gz https://nodejs.org/dist/v6.11.0/node-v6.11.0-linux-armv6l.tar.gz sudo tar xfz /tmp/node-v6.11.0-linux-armv6l.tar.gz --strip 1 -C / rm -rf /tmp/node-v6.11.0-linux-armv6l.tar.gz @@ -278,17 +281,17 @@ else echo -e "\e[1;31mCompiling cjdns from source\e[0m" if ! [ -d "/opt/cjdns" ]; then sudo apt-get install -y python - here=`pwd` + here="$(pwd)" sudo git clone https://github.com/cjdelisle/cjdns.git /opt/cjdns cd /opt/cjdns sudo git checkout $TAG_CJDNS - cd $here + cd "$here" fi # Build cjdns if ! [ -x "/opt/cjdns/cjdroute" ]; then - here=`pwd` - cd /opt/cjdns && eval $CJDNS_BUILD_CMD && cd $here + here="$(pwd)" + cd /opt/cjdns && eval "$CJDNS_BUILD_CMD" && cd "$here" fi # Install cjdns to /usr/bin @@ -321,7 +324,7 @@ if [ "$(checkModule 'WITH_AD_HOC')" ]; then fi # WiFi Access Point on supported boards -if [ "$SUPPORT_HOSTAP" == "true" -a "$(checkModule 'WITH_WIFI_AP')" ]; then +if [ "$SUPPORT_HOSTAP" == "true" ] && [ "$(checkModule 'WITH_WIFI_AP')" ]; then source hostapd/install fi @@ -336,39 +339,42 @@ if [ "$(checkModule 'WITH_CJDNS_IPTUNNEL')" ]; then fi # IPFS -if [ ! -x "$(command -v ipfs)" -a "$(checkModule 'WITH_IPFS')" ]; then +if [ ! -x "$(command -v ipfs)" ] && [ "$(checkModule 'WITH_IPFS')" ]; then source ipfs/install fi + # IPFS Pi Stream -if [ ! -x "$(command -v process-stream.sh)" -a "$(checkModule 'WITH_IPFS_PI_STREAM')" ]; then +if [ ! -x "$(command -v process-stream.sh)" ] && [ "$(checkModule 'WITH_IPFS_PI_STREAM')" ]; then source ipfs-pi-stream/install fi + # SSB -if [ ! -x "$(command -v sbot)" -a "$(checkModule 'WITH_SSB')" ]; then +if [ ! -x "$(command -v sbot)" ] && [ "$(checkModule 'WITH_SSB')" ]; then source ssb/install fi # SSB Web (logic inverted. Install if sbot exists only) -if [ -x "$(command -v sbot)" -a "$(checkModule 'WITH_SSB_WEB')" ]; then +if [ -x "$(command -v sbot)" ] && [ "$(checkModule 'WITH_SSB_WEB')" ]; then source ssb-web/install fi # yrd -if [ ! -x "$(command -v yrd)" -a "$(checkModule 'WITH_YRD')" ]; then +if [ ! -x "$(command -v yrd)" ] && [ "$(checkModule 'WITH_YRD')" ]; then source yrd/install fi + # Prometheus Node Exporter -if [ ! -x "$(command -v node_exporter)" -a "$(checkModule 'WITH_PROMETHEUS_NODE_EXPORTER')" ]; then +if [ ! -x "$(command -v node_exporter)" ] && [ "$(checkModule 'WITH_PROMETHEUS_NODE_EXPORTER')" ]; then source prometheus-node-exporter/install fi # Prometheus Server -if [ ! -x "$(command -v /opt/prometheus/prometheus)" -a "$(checkModule 'WITH_PROMETHEUS_SERVER')" ]; then +if [ ! -x "$(command -v /opt/prometheus/prometheus)" ] && [ "$(checkModule 'WITH_PROMETHEUS_SERVER')" ]; then source prometheus-server/install fi # Grafana -if [ ! -x "$(command -v /usr/sbin/grafana-server)" -a "$(checkModule 'WITH_GRAFANA')" ]; then +if [ ! -x "$(command -v /usr/sbin/grafana-server)" ] && [ "$(checkModule 'WITH_GRAFANA')" ]; then source grafana/install fi @@ -388,7 +394,7 @@ if [ "$(checkModule 'WITH_EXTRA_TOOLS')" ]; then fi # Watchdog on supported boards -if [ "$SUPPORT_WATCHDOG" == "true" -a "$(checkModule 'WITH_WATCHDOG')" ]; then +if [ "$SUPPORT_WATCHDOG" == "true" ] && [ "$(checkModule 'WITH_WATCHDOG')" ]; then source watchdog/install fi @@ -401,17 +407,18 @@ source shared/nodeinfo/install # Print node status on login cp ~/.profile ~/.bash_profile -echo "" >> ~/.bash_profile -echo "# export mesh network name" >> ~/.bash_profile -echo "export MESH_NAME=$MESH_NAME" >> ~/.bash_profile -echo "" >> ~/.bash_profile -echo "# print mesh node status" >> ~/.bash_profile -echo "status" >> ~/.bash_profile - +{ + echo "" + echo "# export mesh network name" + echo "export MESH_NAME=$MESH_NAME" + echo "" + echo "# print mesh node status" + echo "status" +} >> ~/.bash_profile # Rename node based on cjdns address oldhostname=$(hostname) newhostname=$(sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g' | sed "s/.*:/$MESH_NAME-/g") -sudo echo $newhostname | sudo tee /etc/hostname > /dev/null +sudo echo "$newhostname" | sudo tee /etc/hostname > /dev/null sudo sed -i -e "s/$oldhostname/$newhostname/" /etc/hosts echo -e "Your node's new hostname is $newhostname" @@ -420,4 +427,3 @@ read -p "Installation complete. Press any key to reboot your new node. " -n 1 -r # Reboot device sudo reboot - diff --git a/scripts/ipfs-pi-stream/enable-camera.sh b/scripts/ipfs-pi-stream/enable-camera.sh index da3e13068..010c0b460 100755 --- a/scripts/ipfs-pi-stream/enable-camera.sh +++ b/scripts/ipfs-pi-stream/enable-camera.sh @@ -1,4 +1,4 @@ -#/bin/bash +#!/usr/bin/env bash # Enable camera on Raspberry Pi # set_config_var taken from raspi-config diff --git a/scripts/ipfs-pi-stream/install b/scripts/ipfs-pi-stream/install index 41d86f409..e6bf203fa 100755 --- a/scripts/ipfs-pi-stream/install +++ b/scripts/ipfs-pi-stream/install @@ -5,20 +5,20 @@ set -e BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Enable camera on the Raspberry Pi -sudo $BASE_DIR/enable-camera.sh +sudo "$BASE_DIR/enable-camera.sh" # Install ffmpeg and supporting tools sudo apt-get -y install ffmpeg lsof inotify-tools nginx # Add user to be able to modify nginx directories -sudo usermod -a -G $USER www-data +sudo usermod -a -G "$USER" www-data sudo chmod g+rw /var/www/html # TODO: why is this needed? sudo chmod a+rw /var/www/html -sudo cp -f $BASE_DIR/process-stream.sh /usr/bin/process-stream.sh -sudo cp -f $BASE_DIR/process-stream.service /etc/systemd/system/process-stream.service +sudo cp -f "$BASE_DIR/process-stream.sh" /usr/bin/process-stream.sh +sudo cp -f "$BASE_DIR/process-stream.service" /etc/systemd/system/process-stream.service sudo systemctl daemon-reload sudo systemctl enable process-stream diff --git a/scripts/ipfs-pi-stream/process-stream.sh b/scripts/ipfs-pi-stream/process-stream.sh index 6f979f01f..4dd5ada99 100755 --- a/scripts/ipfs-pi-stream/process-stream.sh +++ b/scripts/ipfs-pi-stream/process-stream.sh @@ -14,7 +14,7 @@ function startFFmpeg() { while true; do mv ~/ffmpeg.log ~/ffmpeg.1 echo 1 > ~/stream-reset - ffmpeg -f video4linux2 -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -hls_time ${HLS_TIME} ${what}.m3u8 > ~/ffmpeg 2>&1 + ffmpeg -f video4linux2 -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -hls_time "${HLS_TIME}" "${what}.m3u8" > ~/ffmpeg 2>&1 sleep 0.5 done } @@ -22,11 +22,12 @@ function startFFmpeg() { # Create directory for HLS content currentpath="$HOME/live" -sudo umount $currentpath -rm -rf $currentpath -mkdir $currentpath -sudo mount -t tmpfs tmpfs $currentpath -cd $currentpath +sudo umount "${currentpath}" +rm -rf "${currentpath}" +mkdir "${currentpath}" +sudo mount -t tmpfs tmpfs "${currentpath}" +# shellcheck disable=SC2164 +cd "${currentpath}" what="$(date +%Y%m%d%H%M)-LIVE" @@ -34,23 +35,25 @@ what="$(date +%Y%m%d%H%M)-LIVE" startFFmpeg & while true; do +#TODO# Fix this one +# shellcheck disable=SC2086,SC2012 nextfile=$(ls -tr ${what}*.ts 2>/dev/null | tail -n 1) if ! [ -z "${nextfile}" ]; then # Check if the next file on the list is still being written to by ffmpeg - if ! [ -z "$(lsof ${nextfile} | grep ffmpeg)" ]; then + if lsof "${nextfile}" | grep -1 ffmpeg; then # Wait for file to finish writing # If not finished in 45 seconds something is wrong, timeout - inotifywait -e close_write $nextfile -t 45 + inotifywait -e close_write "${nextfile}" -t 45 fi # Grab the timecode from the m3u8 file so we can add it to the log - timecode=`grep -B1 ${nextfile} ${what}.m3u8 | head -n1 | awk -F : '{print $2}' | tr -d ,` + timecode=$(grep -B1 "${nextfile}" "${what}.m3u8" | head -n1 | awk -F : '{print $2}' | tr -d ,) attempts=5 until [[ "${timecode}" || ${attempts} -eq 0 ]]; do # Wait and retry sleep 0.5 - timecode=`grep -B1 ${nextfile} ${what}.m3u8 | head -n1 | awk -F : '{print $2}' | tr -d ,` + timecode=$(grep -B1 "${nextfile}" "${what}.m3u8" | head -n1 | awk -F : '{print $2}' | tr -d ,) attempts=$((attempts-1)) done @@ -58,49 +61,51 @@ while true; do # Set approximate timecode timecode="${HLS_TIME}.000000" fi - - reset_stream="$(cat ~/stream-reset)" + + reset_stream=$(cat ~/stream-reset) reset_stream_marker='' - if [[ "${reset_stream}" -eq '1' ]]; then + if [[ ${reset_stream} -eq '1' ]]; then reset_stream_marker=" #EXT-X-DISCONTINUITY" fi - + echo 0 > ~/stream-reset # Current UTC date for the log - time=`date "+%F-%H-%M-%S"` + time=$(date "+%F-%H-%M-%S") # Add ts file to IPFS - ret=`ipfs add ${nextfile} 2>/dev/null > ~/tmp.txt; echo $?` + ret=$(ipfs add "${nextfile}" 2>/dev/null > ~/tmp.txt; echo $?) attempts=5 until [[ ${ret} -eq 0 || ${attempts} -eq 0 ]]; do # Wait and retry sleep 1 - ret=`ipfs add ${nextfile} 2>/dev/null > ~/tmp.txt; echo $?` + ret=$(ipfs add "${nextfile}" 2>/dev/null > ~/tmp.txt; echo $?) attempts=$((attempts-1)) done if [[ ${ret} -eq 0 ]]; then # Update the log with the future name (hash already there) - echo $(cat ~/tmp.txt) ${time}.ts ${timecode}${reset_stream_marker} >> ~/process-stream.log + echo "$(cat ~/tmp.txt) ${time}.ts ${timecode}${reset_stream_marker}" >> ~/process-stream.log # Remove nextfile and tmp.txt - rm -f ${nextfile} ~/tmp.txt + rm -f "${nextfile}" ~/tmp.txt # Write the m3u8 file with the new IPFS hashes from the log totalLines="$(wc -l ~/process-stream.log | awk '{print $1}')" - + sequence=0 - if (( "${totalLines}" > ${M3U8_SIZE} )); then - sequence=`expr ${totalLines} - ${M3U8_SIZE}` + if ((totalLines>M3U8_SIZE)); then + sequence=$((totalLines-M3U8_SIZE)) fi - echo "#EXTM3U" > current.m3u8 - echo "#EXT-X-VERSION:3" >> current.m3u8 - echo "#EXT-X-TARGETDURATION:${HLS_TIME}" >> current.m3u8 - echo "#EXT-X-MEDIA-SEQUENCE:${sequence}" >> current.m3u8 + { + echo "#EXTM3U" + echo "#EXT-X-VERSION:3" + echo "#EXT-X-TARGETDURATION:${HLS_TIME}" + echo "#EXT-X-MEDIA-SEQUENCE:${sequence}" + } > current.m3u8 tail -n ${M3U8_SIZE} ~/process-stream.log | awk '{print $6"#EXTINF:"$5",\n'${IPFS_GATEWAY}'/ipfs/"$2}' | sed 's/#EXT-X-DISCONTINUITY#/#EXT-X-DISCONTINUITY\n#/g' >> current.m3u8 # Add m3u8 file to IPFS and IPNS publish m3u8hash=$(ipfs add current.m3u8 | awk '{print $2}') - ipfs name publish --timeout=5s $m3u8hash & + ipfs name publish --timeout=5s "${m3u8hash}" & # Copy files to web server cp current.m3u8 /var/www/html/live.m3u8 diff --git a/scripts/ipfs/install b/scripts/ipfs/install index d24cffb35..cdcb45992 100755 --- a/scripts/ipfs/install +++ b/scripts/ipfs/install @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# shellcheck disable=SC1091 +true set -e @@ -21,12 +23,14 @@ rm -rf "$BASE_DIR/tmp" ipfs init || true # Configure HTTP to IPFS gateway +# shellcheck source=../shared/nginx/install source "$BASE_DIR/../shared/nginx/install" sudo cp "$BASE_DIR/ipfs-http-gateway.conf" /etc/nginx/site-path-enabled/ipfs-http-gateway.conf sudo systemctl restart nginx.service +# shellcheck source=../shared/nodeinfo/install source "$BASE_DIR/../shared/nodeinfo/install" -sudo cp $BASE_DIR/nodeinfo-ipfs /opt/tomesh/nodeinfo.d/ipfs +sudo cp "$BASE_DIR/nodeinfo-ipfs" /opt/tomesh/nodeinfo.d/ipfs # add cjdns bootstrap address ipfs bootstrap add "$IPFS_PEER" @@ -35,7 +39,7 @@ ipfs bootstrap add "$IPFS_PEER" sudo apt-get install -y jq # Move file -sudo cp $BASE_DIR/ipfs-swarm-cjdns.sh /usr/local/bin/ +sudo cp "$BASE_DIR/ipfs-swarm-cjdns.sh" /usr/local/bin/ sudo chmod +x /usr/local/bin/ipfs-swarm-cjdns.sh # Configure systemd to start ipfs.service on system boot diff --git a/scripts/ipfs/ipfs-swarm-cjdns.sh b/scripts/ipfs/ipfs-swarm-cjdns.sh index bca0fe14e..f66f67f1f 100644 --- a/scripts/ipfs/ipfs-swarm-cjdns.sh +++ b/scripts/ipfs/ipfs-swarm-cjdns.sh @@ -12,12 +12,12 @@ if [[ ${attempts} -eq 0 ]]; then fi while read -r cjdns_peer; do - cjdns_addr=$(sudo /opt/cjdns/publictoip6 $cjdns_peer) + cjdns_addr=$(sudo /opt/cjdns/publictoip6 "$cjdns_peer") # See if they have IPFS enabled - res=$(curl http://[${cjdns_addr}]/nodeinfo.json -s) - if [ ! -x "$res" ]; then - id=$(echo ${res} | jq -r -M '.services.ipfs.ID') + res=$(curl http://["${cjdns_addr}"]/nodeinfo.json -s) + if [ ! -x "${res}" ]; then + id=$(echo "${res}" | jq -r -M '.services.ipfs.ID') # Value is found if [[ ! ${id} == "null" ]] && [[ ! "${id}" == "" ]]; then # Connect to neighbouring ipfs @@ -30,7 +30,7 @@ while read -r cjdns_peer; do # XXX: The below command hasn't been working -- so for now only 1-hop peers are checked #peers+=$(cjdnstool query getpeers $peer | sed -e '1d;$d' |awk -F. '{ print $6".k" }') -done <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs` +done <<< "$(sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs)" # Update peers data since ipfs just started sudo /usr/local/bin/nodeinfo-update.sh diff --git a/scripts/prometheus-node-exporter/install b/scripts/prometheus-node-exporter/install index f2a184407..cb84fb797 100755 --- a/scripts/prometheus-node-exporter/install +++ b/scripts/prometheus-node-exporter/install @@ -8,9 +8,9 @@ BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Download and install Prometheus Node Exporter ARM_VERSION=v7 -if $(uname -m | grep -Eq ^armv6); then +if uname -m | grep -Eq ^armv6; then ARM_VERSION=v6 -elif ! [ -z $(uname -m | grep aarch64)]; then +elif uname -m | grep -q aarch64; then ARM_VERSION=64 fi if [[ ! -f "/usr/local/bin/node_exporter" ]]; then @@ -22,7 +22,7 @@ if [[ ! -f "/usr/local/bin/node_exporter" ]]; then rm -rf "$BASE_DIR/tmp" fi -sudo mkdir /var/lib/node_exporter/ +sudo mkdir /var/lib/node_exporter/ sudo mkdir /opt/tomesh/ || true sudo cp "$BASE_DIR/nodestats-tomesh.py" "/opt/tomesh/nodestats-tomesh.py" diff --git a/scripts/prometheus-node-exporter/nodestats-tomesh.py b/scripts/prometheus-node-exporter/nodestats-tomesh.py index aab824812..3927ff598 100644 --- a/scripts/prometheus-node-exporter/nodestats-tomesh.py +++ b/scripts/prometheus-node-exporter/nodestats-tomesh.py @@ -34,7 +34,7 @@ if int.find("Interface") > -1: words = int.split() currentitn=words[1] - + # Read mac address from system file with open("/sys/class/net/" + currentitn + "/address") as f: mac = f.readlines() diff --git a/scripts/prometheus-server/install b/scripts/prometheus-server/install index c663c98fd..7e70ba170 100755 --- a/scripts/prometheus-server/install +++ b/scripts/prometheus-server/install @@ -8,17 +8,18 @@ BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Download and install Prometheus Server ARM_VERSION=v7 -if $(uname -m | grep -Eq ^armv6); then +if uname -m | grep -Eq ^armv6; then ARM_VERSION=v6 -elif ! [ -z $(uname -m | grep aarch64)]; then +elif uname -m | grep aarch64; then ARM_VERSION=64 fi + mkdir "$BASE_DIR/tmp" wget "https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.linux-arm${ARM_VERSION}.tar.gz" -O "$BASE_DIR/tmp/prometheus.tar.gz" tar xvfz "$BASE_DIR/tmp/prometheus.tar.gz" -C "$BASE_DIR/tmp" --strip 1 mv "$BASE_DIR/tmp/prometheus.yml" "$BASE_DIR/tmp/prometheus.yml.orig" CJDNS_IPV6=$(sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g') -cat "$BASE_DIR/tmp/prometheus.yml.orig" | sed "s|localhost:9090|[${CJDNS_IPV6}]:9100|" > "$BASE_DIR/tmp/prometheus.yml" +sed "s|localhost:9090|[${CJDNS_IPV6}]:9100|" "$BASE_DIR/tmp/prometheus.yml.orig" > "$BASE_DIR/tmp/prometheus.yml" sudo cp -r "$BASE_DIR/tmp" /opt/prometheus rm -rf "$BASE_DIR/tmp" diff --git a/scripts/shared/nginx/install b/scripts/shared/nginx/install index f76aa1960..56257eb26 100755 --- a/scripts/shared/nginx/install +++ b/scripts/shared/nginx/install @@ -1,17 +1,16 @@ -#!/bin/sh +#!/usr/bin/env bash set -e -if [ ! -x "$(command -v nginx)" ]; then +if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; then LAST_BASE="$BASE_DIR" BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" sudo apt-get install nginx -y - sudo cp "$BASE_DIR/main.conf" /etc/nginx/sites-available/main.conf - sudo ln -s /etc/nginx/sites-available/main.conf /etc/nginx/sites-enabled/main.conf + sudo cp -f "$BASE_DIR/main.conf" /etc/nginx/sites-available/main.conf + sudo ln -s /etc/nginx/sites-available/main.conf /etc/nginx/sites-enabled/main.conf || true sudo rm /etc/nginx/sites-enabled/default || true - sudo mkdir /etc/nginx/site-path-enabled + sudo mkdir /etc/nginx/site-path-enabled || true BASE_DIR="$LAST_BASE" - fi diff --git a/scripts/shared/nodeinfo/install b/scripts/shared/nodeinfo/install index 08a5927e5..fef9fe66c 100755 --- a/scripts/shared/nodeinfo/install +++ b/scripts/shared/nodeinfo/install @@ -9,8 +9,8 @@ sudo apt-get install -y jq sudo mkdir -p /opt/tomesh/nodeinfo.d -sudo cp $BASE_DIR/nodeinfo.json /opt/tomesh/nodeinfo.json -sudo cp $BASE_DIR/nodeinfo-update.sh /usr/local/bin/nodeinfo-update.sh +sudo cp "$BASE_DIR/nodeinfo.json" /opt/tomesh/nodeinfo.json +sudo cp "$BASE_DIR/nodeinfo-update.sh" /usr/local/bin/nodeinfo-update.sh sudo sed -i -e "s/__REPO__/$(git remote get-url origin | awk -F / '{print $5}'| cut -d '.' -f1)/g" /opt/tomesh/nodeinfo.json sudo sed -i -e "s/__BRANCH__/$(git rev-parse --abbrev-ref HEAD)/g" /opt/tomesh/nodeinfo.json diff --git a/scripts/ssb-web/install b/scripts/ssb-web/install index 94447d274..65d09beeb 100644 --- a/scripts/ssb-web/install +++ b/scripts/ssb-web/install @@ -1,10 +1,13 @@ #!/usr/bin/env bash +# shellcheck disable=SC1091 +true set -e BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Install nginx and php +# shellcheck source=../shared/nginx/install source "$BASE_DIR/../shared/nginx/install" sudo apt-get install -y php-fpm socat @@ -32,17 +35,17 @@ sudo systemctl start ssb-web-broadcast.service # Set permissions to let nginx access it # TODO find a better solution, maybe add user to nginx group? -chmod a+rwX $ssbPath -chmod -R a+rwX $ssbPath +chmod a+rwX "$ssbPath" +chmod -R a+rwX "$ssbPath" # Link .ssb to nginx's home directory becuse that is where sbot looks for it if [ -e "/var/www/.ssb" ]; then sudo rm -rf /var/www/.ssb fi -sudo ln -s $ssbPath /var/www/ +sudo ln -s "$ssbPath" /var/www/ # Create nginx site at /sbot -sudo cp $BASE_DIR/ssb-web.conf /etc/nginx/site-path-enabled/ssb-web.conf +sudo cp "$BASE_DIR/ssb-web.conf" "/etc/nginx/site-path-enabled/ssb-web.conf" # Pull and install client if [ -e "$BASE_DIR/tmp" ]; then diff --git a/scripts/ssb-web/ssb-web-broadcast-service.sh b/scripts/ssb-web/ssb-web-broadcast-service.sh index 65b92b50b..b9b0bfa5d 100755 --- a/scripts/ssb-web/ssb-web-broadcast-service.sh +++ b/scripts/ssb-web/ssb-web-broadcast-service.sh @@ -2,12 +2,12 @@ while true; do while read -r id; do - for int in $(ls -1Atu /sys/class/net ); do - ip=$(ip addr show $int | grep -v inet6 | grep -v '127.0.0.1' |grep inet | head -n 1 | awk '{print $2}' | awk -F "/" '{print $1}') + for int in $(find /sys/class/net -maxdepth 1 -print0 | xargs -0 -l basename); do + ip=$(ip addr show "$int" | grep -v inet6 | grep -v '127.0.0.1' |grep inet | head -n 1 | awk '{print $2}' | awk -F "/" '{print $1}') if ! [ -z "$ip" ]; then - echo -n "net:$ip:8008~shs:$id" | sudo socat -T 1 - UDP4-DATAGRAM:255.255.255.255:8008,broadcast,so-bindtodevice=$int & + echo -n "net:$ip:8008~shs:$id" | sudo socat -T 1 - "UDP4-DATAGRAM:255.255.255.255:8008,broadcast,so-bindtodevice=$int" & fi done - done <<< $(sudo cat /var/www/backend/keys/* | grep id | grep -v "#" | awk '{print $2}' | tr -d '"' | sed 's/.ed25519//' | sed 's/@//') + done <<< "$(sudo cat /var/www/backend/keys/* | grep id | grep -v "#" | awk '{print $2}' | tr -d '"' | sed 's/.ed25519//' | sed 's/@//')" sleep 5 -done \ No newline at end of file +done diff --git a/scripts/ssb/ssb-broadcast-service.sh b/scripts/ssb/ssb-broadcast-service.sh index b099496e0..9cb659402 100755 --- a/scripts/ssb/ssb-broadcast-service.sh +++ b/scripts/ssb/ssb-broadcast-service.sh @@ -1,14 +1,14 @@ -#!/bin/sh +#!/bin/bash while true; do id=$(sbot whoami | grep id | awk -F "\"" '{print $4}' | sed 's/.ed25519//' | sed 's/@//') if ! [ -z "$id" ]; then - for int in $(ls -1Atu /sys/class/net); do - ip=$(ip addr show $int | grep -v inet6 | grep -v '127.0.0.1' |grep inet | head -n 1 | awk '{print $2}' | awk -F "/" '{print $1}') + for int in $(find /sys/class/net -maxdepth 1 -print0 | xargs -0 -l basename); do + ip=$(ip addr show "${int}" | grep -v inet6 | grep -v '127.0.0.1' |grep inet | head -n 1 | awk '{print $2}' | awk -F "/" '{print $1}') if ! [ -z "$ip" ]; then - echo -n "net:$ip:8008~shs:$id" | sudo socat -T 1 - UDP4-DATAGRAM:255.255.255.255:8008,broadcast,so-bindtodevice=$int & + echo -n "net:$ip:8008~shs:$id" | sudo socat -T 1 - "UDP4-DATAGRAM:255.255.255.255:8008,broadcast,so-bindtodevice=${int}" & fi done fi sleep 5 -done \ No newline at end of file +done diff --git a/scripts/status b/scripts/status index f3d2dfa73..b76270929 100755 --- a/scripts/status +++ b/scripts/status @@ -10,7 +10,7 @@ echo " | || (_) | | | | | | __\__ | | | |" echo " \__\___/|_| |_| |_|\___|___|_| |_|" echo -e '---------------------------------------' -if [ $(systemctl status cjdns.service | grep 'Active: ' | awk '{ print $2 }') = 'active' ]; then +if [ "$(systemctl status cjdns.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then echo -e "cjdns Service ................ $ACTIVE" else echo -e "cjdns Service .............. $INACTIVE" @@ -44,56 +44,56 @@ if [ "$(which mesh-adhoc)" ]; then fi fi if [ "$(which hostapd)" ]; then - if [ $(systemctl status hostapd.service | grep 'Active: ' | awk '{ print $2 }') = 'active' ] && [ -n "$(ps aux | grep hostapd | grep -v grep)" ]; then + if [ "$(systemctl status hostapd.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ] && [ -n "$(ps aux | grep hostapd | grep -v grep)" ]; then echo -e "WiFi Access Point ............ $ACTIVE" else echo -e "WiFi Access Point .......... $INACTIVE" fi fi if [ "$(which ipfs)" ]; then - if [ $(systemctl status ipfs.service | grep 'Active: ' | awk '{ print $2 }') = 'active' ]; then + if [ "$(systemctl status ipfs.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then echo -e "IPFS Service ................. $ACTIVE" else echo -e "IPFS Service ............... $INACTIVE" fi fi if [ "$(which sbot)" ]; then - if [ $(systemctl status ssb.service | grep 'Active: ' | awk '{ print $2 }') = 'active' ]; then + if [ "$(systemctl status ssb.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then echo -e "ScuttleBot Service ........... $ACTIVE" else echo -e "ScuttleBot Service ......... $INACTIVE" fi fi if [ "$(which ffmpeg)" ]; then - if [ ! -z "ps aux | grep ffmpeg | grep -v grep" ] && [ $(systemctl status process-stream.service | grep 'Active: ' | awk '{ print $2 }') = 'active' ]; then + if [ ! -z "$(ps aux | grep ffmpeg | grep -v grep)" ] && [ "$(systemctl status process-stream.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then echo -e "IPFS Pi Stream Service ....... $ACTIVE" else echo -e "IPFS Pi Stream Service ..... $INACTIVE" fi fi if [ "$(which node_exporter)" ]; then - if [ $(systemctl status prometheus-node-exporter.service | grep 'Active: ' | awk '{ print $2 }') = 'active' ]; then + if [ "$(systemctl status prometheus-node-exporter.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then echo -e "Prometheus Node Exporter ..... $ACTIVE" else echo -e "Prometheus Node Exporter ... $INACTIVE" fi fi if [ "$(which /opt/prometheus/prometheus)" ]; then - if [ $(systemctl status prometheus-server.service | grep 'Active: ' | awk '{ print $2 }') = 'active' ]; then + if [ "$(systemctl status prometheus-server.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then echo -e "Prometheus Server ............ $ACTIVE" else echo -e "Prometheus Server .......... $INACTIVE" fi fi if [ "$(which /usr/sbin/grafana-server)" ]; then - if [ $(systemctl status grafana-server.service | grep 'Active: ' | awk '{ print $2 }') = 'active' ]; then + if [ "$(systemctl status grafana-server.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then echo -e "Grafana ...................... $ACTIVE" else echo -e "Grafana .................... $INACTIVE" fi fi if [ "$(which yrd)" ]; then - if [ $(systemctl status yrd.service | grep 'Active: ' | awk '{ print $2 }') = 'active' ]; then + if [ "$(systemctl status yrd.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then echo -e "yrd .......................... $ACTIVE" else echo -e "yrd ........................ $INACTIVE" @@ -106,6 +106,6 @@ echo -e '---------------------------------------' echo -e 'PEERS' read -a peers <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs` for peer in "${peers[@]}"; do - sudo /opt/cjdns/publictoip6 $peer + sudo /opt/cjdns/publictoip6 "$peer" done echo -e '---------------------------------------' From 6a8f15ba8b9a07011f760ba9537418f774ffb1b3 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 11 Oct 2018 14:05:24 -0400 Subject: [PATCH 005/162] Corrected IPERF3 port number --- scripts/firewall/rules.v6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index e0f171763..586b85d9d 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -13,6 +13,6 @@ -A INPUT -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -i tun0 -j cjdns --A cjdns -p tcp -m multiport --dports 80,443,9100,22,5021,4001 -j ACCEPT +-A cjdns -p tcp -m multiport --dports 80,443,9100,22,5201,4001 -j ACCEPT -A cjdns -j REJECT --reject-with icmp6-port-unreachable COMMIT From 07fb9ff7520e8b37cf0d32ff920d97a59456b712 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 11 Oct 2018 15:17:01 -0400 Subject: [PATCH 006/162] Initial install script --- scripts/yggdrasil/install | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 scripts/yggdrasil/install diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install new file mode 100644 index 000000000..c93ccd60c --- /dev/null +++ b/scripts/yggdrasil/install @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -e + +YGGDRASIL_VERSION=0.2.6 + +BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Download and install yggdrasil routing engine + +ARM_VERSION=armhf +if uname -m | grep -q aarch64; then + ARM_VERSION=arm64 +fi + +if [[ ! -f "/usr/local/bin/node_exporter" ]]; then + mkdir "$BASE_DIR/tmp" + wget "https://236-115685026-gh.circle-artifacts.com/0/yggdrasil-${YGGDRASIL_VERSION}-${ARM_VERSION}.deb" -o "$BASE_DIR/tmp/yggdrasil.deb" + dpkg -i yggdrasil.deb +fi \ No newline at end of file From f7b24f0f140e1a506f3c2030d8f83944c0ab8850 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 11 Oct 2018 16:46:32 -0400 Subject: [PATCH 007/162] Update rules.v6 --- scripts/firewall/rules.v6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 586b85d9d..9c87b5c61 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -7,7 +7,7 @@ -A INPUT -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -i tun0 -j cjdns --A INPUT -p tcp -m multiport --dports 80,443,9100,22,5021,4001 +-A INPUT -p tcp -m multiport --dports 80,443,9100,22,5201,4001 -A INPUT -j REJECT --reject-with icmp6-port-unreachable -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT From 537203781bdeb1a975f731688fa02b261b305eb9 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 14 Oct 2018 22:24:23 -0400 Subject: [PATCH 008/162] Fix incorrect match of / during find --- scripts/ssb/ssb-broadcast-service.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ssb/ssb-broadcast-service.sh b/scripts/ssb/ssb-broadcast-service.sh index 9cb659402..b23b32d18 100755 --- a/scripts/ssb/ssb-broadcast-service.sh +++ b/scripts/ssb/ssb-broadcast-service.sh @@ -3,7 +3,7 @@ while true; do id=$(sbot whoami | grep id | awk -F "\"" '{print $4}' | sed 's/.ed25519//' | sed 's/@//') if ! [ -z "$id" ]; then - for int in $(find /sys/class/net -maxdepth 1 -print0 | xargs -0 -l basename); do + for int in $(find /sys/class/net/* -maxdepth 1 -print0 | xargs -0 -l basename); do ip=$(ip addr show "${int}" | grep -v inet6 | grep -v '127.0.0.1' |grep inet | head -n 1 | awk '{print $2}' | awk -F "/" '{print $1}') if ! [ -z "$ip" ]; then echo -n "net:$ip:8008~shs:$id" | sudo socat -T 1 - "UDP4-DATAGRAM:255.255.255.255:8008,broadcast,so-bindtodevice=${int}" & From b5d020c6f067022a5cb53ce78e4647ede5273583 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 14 Oct 2018 22:24:45 -0400 Subject: [PATCH 009/162] Fixed incorrect match of / in find --- scripts/ssb-web/ssb-web-broadcast-service.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ssb-web/ssb-web-broadcast-service.sh b/scripts/ssb-web/ssb-web-broadcast-service.sh index b9b0bfa5d..6d86a2375 100755 --- a/scripts/ssb-web/ssb-web-broadcast-service.sh +++ b/scripts/ssb-web/ssb-web-broadcast-service.sh @@ -2,7 +2,7 @@ while true; do while read -r id; do - for int in $(find /sys/class/net -maxdepth 1 -print0 | xargs -0 -l basename); do + for int in $(find /sys/class/net/* -maxdepth 1 -print0 | xargs -0 -l basename); do ip=$(ip addr show "$int" | grep -v inet6 | grep -v '127.0.0.1' |grep inet | head -n 1 | awk '{print $2}' | awk -F "/" '{print $1}') if ! [ -z "$ip" ]; then echo -n "net:$ip:8008~shs:$id" | sudo socat -T 1 - "UDP4-DATAGRAM:255.255.255.255:8008,broadcast,so-bindtodevice=$int" & From 4704fa9c0c6dad2f9bd4e8468f7e16dfc090a937 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 14 Oct 2018 22:27:08 -0400 Subject: [PATCH 010/162] Opened port 8008 for ssb peering --- scripts/firewall/rules.v4 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/firewall/rules.v4 b/scripts/firewall/rules.v4 index 6c3814643..40386a29d 100644 --- a/scripts/firewall/rules.v4 +++ b/scripts/firewall/rules.v4 @@ -16,6 +16,7 @@ -A INPUT -p tcp -m tcp --dport 3000 -j ACCEPT -A INPUT -p tcp -m tcp --dport 5201 -j ACCEPT -A INPUT -p tcp -m tcp --dport 4001 -j ACCEPT +-A INPUT -p tcp -m udp --dport 8008 -j ACCEPT -A INPUT -i wlan+ -j ACCEPT -A INPUT -j DROP COMMIT From 016b7bc9e3438e139ee2eb5ab0da232445a1bb2d Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 14 Oct 2018 22:38:42 -0400 Subject: [PATCH 011/162] Fixed ipv6 rules Removed duplication of rules Removed redundant CJDNS target --- scripts/firewall/rules.v6 | 7 ------- 1 file changed, 7 deletions(-) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 9c87b5c61..916b17727 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -6,13 +6,6 @@ -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT --A INPUT -i tun0 -j cjdns -A INPUT -p tcp -m multiport --dports 80,443,9100,22,5201,4001 -A INPUT -j REJECT --reject-with icmp6-port-unreachable --A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT --A INPUT -p ipv6-icmp -j ACCEPT --A INPUT -i lo -j ACCEPT --A INPUT -i tun0 -j cjdns --A cjdns -p tcp -m multiport --dports 80,443,9100,22,5201,4001 -j ACCEPT --A cjdns -j REJECT --reject-with icmp6-port-unreachable COMMIT From b4a98465209f94245a29de92a739a1fa0dd4d95e Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 14 Oct 2018 22:59:43 -0400 Subject: [PATCH 012/162] Updated meshpoint script to scan all interfaces Old mesh point scanned only phy0 and phy1, Update scans all interfaces, checks if they are wireless, determines the phy id, then checks for meshpoint. This way any phyx can be mesh point not just 0 and 1 --- scripts/mesh-point/mesh-point | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/scripts/mesh-point/mesh-point b/scripts/mesh-point/mesh-point index e5344ec31..700ce7f39 100755 --- a/scripts/mesh-point/mesh-point +++ b/scripts/mesh-point/mesh-point @@ -6,30 +6,35 @@ function isMeshable { # Check to see if driver reports missing mesh point support if [ -z "$(iw phy phy$1 info | grep 'mesh point')" ]; then result='' # Indicate interface is not meshable - # XRADIO driver reports Mesh Point support incorrectly (there is no support for it) - elif [ "$(basename $(readlink /sys/class/net/$interface/device/driver))" == 'xradio_wlan' ]; then + # XRADIO driver reports Mesh Point but does not actually work + elif [ "$(basename $(readlink /sys/class/net/$interface/device/driver))" == 'xradio_wlan' ]; then result='' # Indicate interface is actually not meshable else - result='1' # Indicate interface is meshable + result='1' # Indicate interface is meshable fi echo $result } - set -e # Set wireless regulatory domain sudo iw reg set CA -# Select physical device that supports 802.11s Mesh Point -if ! [ -z $(isMeshable 0) ]; then - mesh_phy=phy0 - mesh_dev=$(iw dev | grep phy#0 -A 1 | grep Interface | awk '{print $2}') -elif ! [ -z $(isMeshable 1) ]; then - mesh_phy=phy1 - mesh_dev=$(iw dev | grep phy#1 -A 1 | grep Interface | awk '{print $2}') -else +# Find first meshpoint device you can +for int in $(find /sys/class/net/* -maxdepth 1 -print0 | xargs -0 -l basename); do + if [ -d "/sys/class/net/$int/wireless" ]; then + phy=$(iw dev "$int" info | grep wiphy | awk '{print $2}') + if [ ! -z "$phy" ]; then + if ! [ -z $(isMeshable "$phy") ]; then + mesh_dev="$int" + fi + fi + fi +done + +# If no device found exit with error +if [ -z "$mesh_dev" ]; then exit 1 fi From 1e2176a6ae6769f0190c024a4e4ec4f43c0b94b9 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 15 Oct 2018 08:44:55 -0400 Subject: [PATCH 013/162] clearified meshpoint meaning in comment --- scripts/mesh-point/mesh-point | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mesh-point/mesh-point b/scripts/mesh-point/mesh-point index 700ce7f39..751adc862 100755 --- a/scripts/mesh-point/mesh-point +++ b/scripts/mesh-point/mesh-point @@ -21,7 +21,7 @@ set -e # Set wireless regulatory domain sudo iw reg set CA -# Find first meshpoint device you can +# Find first 802.11s Mesh Point capable device you can for int in $(find /sys/class/net/* -maxdepth 1 -print0 | xargs -0 -l basename); do if [ -d "/sys/class/net/$int/wireless" ]; then phy=$(iw dev "$int" info | grep wiphy | awk '{print $2}') From ad7e7856b91f742dbd55dd755d4f605de8330b55 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 15 Oct 2018 09:13:53 -0400 Subject: [PATCH 014/162] Added missing accept keyword --- scripts/firewall/rules.v6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 916b17727..6ea9d2e9f 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -6,6 +6,6 @@ -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT --A INPUT -p tcp -m multiport --dports 80,443,9100,22,5201,4001 +-A INPUT -j ACCEPT -p tcp -m multiport --dports 80,443,9100,22,5201,4001 -A INPUT -j REJECT --reject-with icmp6-port-unreachable COMMIT From 287847638b9c93eb3306704c64e37e2685faea97 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 15 Oct 2018 09:22:24 -0400 Subject: [PATCH 015/162] Seperated and sorted ipv6 ports --- scripts/firewall/rules.v6 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 6ea9d2e9f..a7f13c5c7 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -6,6 +6,11 @@ -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT --A INPUT -j ACCEPT -p tcp -m multiport --dports 80,443,9100,22,5201,4001 +-A INPUT -j ACCEPT -p tcp --dport 22 +-A INPUT -j ACCEPT -p tcp --dport 80 +-A INPUT -j ACCEPT -p tcp --dport 443 +-A INPUT -j ACCEPT -p tcp --dport 5201 +-A INPUT -j ACCEPT -p tcp --dport 4001 +-A INPUT -j ACCEPT -p tcp --dport 9100 -A INPUT -j REJECT --reject-with icmp6-port-unreachable COMMIT From baef2bef3ef885c3db20fe5f0bc990b6840a75ec Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 15 Oct 2018 09:23:14 -0400 Subject: [PATCH 016/162] Sorted ipv4 ports in firewall --- scripts/firewall/rules.v4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/firewall/rules.v4 b/scripts/firewall/rules.v4 index 40386a29d..2d22d5457 100644 --- a/scripts/firewall/rules.v4 +++ b/scripts/firewall/rules.v4 @@ -11,12 +11,12 @@ -A INPUT -p udp -m udp --dport 53 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT --A INPUT -p tcp -m tcp --dport 9100 -j ACCEPT --A INPUT -p tcp -m tcp --dport 9090 -j ACCEPT -A INPUT -p tcp -m tcp --dport 3000 -j ACCEPT --A INPUT -p tcp -m tcp --dport 5201 -j ACCEPT -A INPUT -p tcp -m tcp --dport 4001 -j ACCEPT +-A INPUT -p tcp -m tcp --dport 5201 -j ACCEPT -A INPUT -p tcp -m udp --dport 8008 -j ACCEPT +-A INPUT -p tcp -m tcp --dport 9090 -j ACCEPT +-A INPUT -p tcp -m tcp --dport 9100 -j ACCEPT -A INPUT -i wlan+ -j ACCEPT -A INPUT -j DROP COMMIT From e5c53f995c4a6ff180685562fc8985ecbccdaaa9 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 15 Oct 2018 09:32:16 -0400 Subject: [PATCH 017/162] Updated grammer in meshpoint comment --- scripts/mesh-point/mesh-point | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mesh-point/mesh-point b/scripts/mesh-point/mesh-point index 751adc862..95c7b81fc 100755 --- a/scripts/mesh-point/mesh-point +++ b/scripts/mesh-point/mesh-point @@ -21,7 +21,7 @@ set -e # Set wireless regulatory domain sudo iw reg set CA -# Find first 802.11s Mesh Point capable device you can +# Find first 802.11s Mesh Point capable device for int in $(find /sys/class/net/* -maxdepth 1 -print0 | xargs -0 -l basename); do if [ -d "/sys/class/net/$int/wireless" ]; then phy=$(iw dev "$int" info | grep wiphy | awk '{print $2}') From 6204e556dbc4d455071b33d739db5f8d8c86639c Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 15 Oct 2018 09:41:35 -0400 Subject: [PATCH 018/162] Added prometheus and grafana ports --- scripts/firewall/rules.v6 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index a7f13c5c7..3f1aadd4f 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -9,8 +9,10 @@ -A INPUT -j ACCEPT -p tcp --dport 22 -A INPUT -j ACCEPT -p tcp --dport 80 -A INPUT -j ACCEPT -p tcp --dport 443 +-A INPUT -j ACCEPT -p tcp --dport 3000 -A INPUT -j ACCEPT -p tcp --dport 5201 -A INPUT -j ACCEPT -p tcp --dport 4001 +-A INPUT -j ACCEPT -p tcp --dport 9090 -A INPUT -j ACCEPT -p tcp --dport 9100 -A INPUT -j REJECT --reject-with icmp6-port-unreachable COMMIT From 59bef187870dce313ea3c5d1d6355a1ae0ac78c9 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 5 Nov 2018 20:51:20 -0500 Subject: [PATCH 019/162] Update FAQ.md --- FAQ.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/FAQ.md b/FAQ.md index 04df30bb9..d7673731f 100644 --- a/FAQ.md +++ b/FAQ.md @@ -122,3 +122,7 @@ To install * After install remove `HT40+` from `/usr/bin/mesh-adhoc` If you have success using ad-hoc with on board cards please let us know your experience. + +So far: +3b+ seemed to have worked but 3b did not +Got 3b working by killing wpa_supplicant first (reproducable?) From 426933f74dec3725bfc1eecc17ad7bfacacd6f29 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 13 Nov 2018 00:11:47 -0500 Subject: [PATCH 020/162] Deleted to avoid conflict --- scripts/ssb-web/ssb-web-broadcast-service.sh | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100755 scripts/ssb-web/ssb-web-broadcast-service.sh diff --git a/scripts/ssb-web/ssb-web-broadcast-service.sh b/scripts/ssb-web/ssb-web-broadcast-service.sh deleted file mode 100755 index 6d86a2375..000000000 --- a/scripts/ssb-web/ssb-web-broadcast-service.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -while true; do - while read -r id; do - for int in $(find /sys/class/net/* -maxdepth 1 -print0 | xargs -0 -l basename); do - ip=$(ip addr show "$int" | grep -v inet6 | grep -v '127.0.0.1' |grep inet | head -n 1 | awk '{print $2}' | awk -F "/" '{print $1}') - if ! [ -z "$ip" ]; then - echo -n "net:$ip:8008~shs:$id" | sudo socat -T 1 - "UDP4-DATAGRAM:255.255.255.255:8008,broadcast,so-bindtodevice=$int" & - fi - done - done <<< "$(sudo cat /var/www/backend/keys/* | grep id | grep -v "#" | awk '{print $2}' | tr -d '"' | sed 's/.ed25519//' | sed 's/@//')" - sleep 5 -done From 185212f84e24d4839aa6ab05469512d10c0f5fb2 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 13 Nov 2018 00:12:46 -0500 Subject: [PATCH 021/162] Patchfoo Module (#200) * Added patchfoo module * Added patchfoo to readme * added nginx to install * /patchfoo fix * Updated ssb-web-pi nginx script * Update and rename ssb-web-broadcast.service to ssb-web-pi-broadcast.service * Rename ssb-web-broadcast-service.sh to ssb-web-pi-broadcast-service.sh --- README.md | 5 ++- scripts/install | 3 +- scripts/install2 | 14 +++++-- scripts/ssb-patchfoo/install | 42 +++++++++++++++++++ scripts/ssb-patchfoo/ssb-patchfoo.conf | 9 ++++ scripts/{ssb-web => ssb-web-pi}/install | 12 +++--- .../ssb-web-pi-broadcast.service} | 6 +-- .../ssb-web-pi.conf} | 6 +-- scripts/{ssb-web => ssb-web-pi}/uninstall | 0 9 files changed, 78 insertions(+), 19 deletions(-) create mode 100755 scripts/ssb-patchfoo/install create mode 100644 scripts/ssb-patchfoo/ssb-patchfoo.conf rename scripts/{ssb-web => ssb-web-pi}/install (82%) rename scripts/{ssb-web/ssb-web-broadcast.service => ssb-web-pi/ssb-web-pi-broadcast.service} (56%) rename scripts/{ssb-web/ssb-web.conf => ssb-web-pi/ssb-web-pi.conf} (77%) rename scripts/{ssb-web => ssb-web-pi}/uninstall (100%) diff --git a/README.md b/README.md index ae50445e7..ef7c1258b 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Many board that run [Armbian](https://www.armbian.com/) such as many models of O The installation script can also install many optional features such as distributed applications and network analysis tools that are useful but non-essential to run a node. You can use flags to selectively enable them, or use the following command to install all optional features: ``` - $ wget https://raw.githubusercontent.com/tomeshnet/prototype-cjdns-pi/master/scripts/install && chmod +x install && WITH_MESH_POINT=true WITH_AD_HOC=false WITH_WIFI_AP=true WITH_FIREWALL=true WITH_CJDNS_IPTUNNEL=true WITH_IPFS=true WITH_SSB=true WITH_SSB_WEB=true WITH_PROMETHEUS_NODE_EXPORTER=true WITH_PROMETHEUS_SERVER=true WITH_GRAFANA=true WITH_H_DNS=true WITH_H_NTP=true WITH_EXTRA_TOOLS=true WITH_YRD=true ./install + $ wget https://raw.githubusercontent.com/tomeshnet/prototype-cjdns-pi/master/scripts/install && chmod +x install && WITH_MESH_POINT=true WITH_AD_HOC=false WITH_WIFI_AP=true WITH_FIREWALL=true WITH_CJDNS_IPTUNNEL=true WITH_IPFS=true WITH_SSB=true WITH_SSB_WEB_PI=false WITH_PROMETHEUS_NODE_EXPORTER=true WITH_PROMETHEUS_SERVER=true WITH_GRAFANA=true WITH_H_DNS=true WITH_H_NTP=true WITH_EXTRA_TOOLS=true WITH_YRD=true ./install ``` ## Optional Features @@ -58,7 +58,8 @@ Many board that run [Armbian](https://www.armbian.com/) such as many models of O | `WITH_IPFS` | **80**: HTTP-to-IPFS gateway at `/ipfs/HASH` | Set to `true` if you want to install [IPFS](https://ipfs.io). | | `WITH_IPFS_PI_STREAM` | None | Set to `true` if you want to install Pi stream service to live stream your camera over IPFS. Requires a Raspberry Pi with camera module. *Will automatically start recording on boot by default.* | | `WITH_SSB` | | Set to `true` if you want to install [Scuttlebot (SSB)](https://github.com/ssbc/scuttlebot) a secure scuttlebutt daemon. | -| `WITH_SSB_WEB` | **80**: SSB web interface at `/sbot` | Set to `true` if you want to install [SSB Web Pi](https://github.com/darkdrgn2k/ssb-web-pi),which allows you to interact with the scuttlebot backend with a web interface. | +| `WITH_SSB_PATCHFOO` | **80**: SSB web interface at `/patchfoo` | Set to `true` if you want to install [Patchfoo](https://github.com/ssbc/patchfoo), allows you to interact with the scuttlebot backend with a web interface. | +| `WITH_SSB_WEB_PI` | **80**: SSB web interface at `/ssb-web-pi` | Set to `true` if you want to install [SSB Web Pi](https://github.com/darkdrgn2k/ssb-web-pi), interact with scuttlebot api via a web interface. **EXPERIMENTAL** | | `WITH_PROMETHEUS_NODE_EXPORTER` | **9100**: Node Exporter UI | Set to `true` if you want to install [Prometheus Node Exporter](https://github.com/prometheus/node_exporter) to report network metrics. | | `WITH_PROMETHEUS_SERVER` | **9090**: Prometheus Server UI | Set to `true` if you want to install [Prometheus Server](https://github.com/prometheus/prometheus) to collect network metrics. *Requires Prometheus Node Exporter.* | | `WITH_GRAFANA` | **3000**: Grafana UI (login: admin/admin) | Set to `true` if you want to install [Grafana](https://grafana.com) to display network metrics. *Requires Prometheus Server.* | diff --git a/scripts/install b/scripts/install index 71e7653ad..4cee27572 100755 --- a/scripts/install +++ b/scripts/install @@ -52,7 +52,8 @@ export WITH_EXTRA_TOOLS export WITH_WATCHDOG export WITH_YRD export WITH_SSB -export WITH_SSB_WEB +export WITH_SSB_PATCHFOO +export WITH_SSB_WEB_PI export WITH_IPFS_PI_STREAM # Run the actual installation script ./install2 diff --git a/scripts/install2 b/scripts/install2 index 9a631b1dd..3b4127a51 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -210,7 +210,8 @@ if [ "$WITH_IPFS" == true ] && [ "$BOARD_FAMILY" == "Raspberry Pi" ]; then fi askModule "WITH_SSB" "SSB" if [ "$WITH_SSB" == "true" ]; then - askModule "WITH_SSB_WEB" "SSB Web Client (Experimental)" "n" + askModule "WITH_SSB_PATCHFOO" "SSB PatchFoo Web Client" + askModule "WITH_SSB_WEB_PI" "SSB Web Pi Client (Experimental)" "n" fi askModule "WITH_YRD" "Yrd (a cjdns command-line tool)" askModule "WITH_PROMETHEUS_NODE_EXPORTER" "Prometheus Node Exporter" @@ -353,9 +354,14 @@ if [ ! -x "$(command -v sbot)" ] && [ "$(checkModule 'WITH_SSB')" ]; then source ssb/install fi -# SSB Web (logic inverted. Install if sbot exists only) -if [ -x "$(command -v sbot)" ] && [ "$(checkModule 'WITH_SSB_WEB')" ]; then - source ssb-web/install +# SSB patchfoo (only install if sbot exists) +if [ -x "$(command -v sbot)" ] && [ "$(checkModule 'WITH_SSB_PATCHFOO')" ]; then + source ssb-patchfoo/install +fi + +# SSB Web (only install if sbot exists) +if [ -x "$(command -v sbot)" ] && [ "$(checkModule 'WITH_SSB_WEB_PI')" ]; then + source ssb-web-pi/install fi # yrd diff --git a/scripts/ssb-patchfoo/install b/scripts/ssb-patchfoo/install new file mode 100755 index 000000000..32760b61a --- /dev/null +++ b/scripts/ssb-patchfoo/install @@ -0,0 +1,42 @@ +#!/bin/bash +# shellcheck disable=SC1091 +true + +BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +CURRENT_DIR="$(pwd)" + +# Install nginx +# shellcheck source=../shared/nginx/install +source "$BASE_DIR/../shared/nginx/install" + +sleep 5 +# shellcheck disable=SC2164 +cd ~/.ssb/node_modules + +# Install dependencies +npm install asyncmemo hashlru pull-stream pull-cat multicb hyperscript pull-paramap ssb-contact ssb-sort stream-to-pull-stream emoji-server pull-paginate ssb-mentions busboy mime-types pull-identify-filetype human-time pull-hyperscript jpeg-autorotate pull-catch diff pull-split pull-utf8-decoder ssb-web-resolver highlight.js pull-box-stream base64-url ssb-backlinks ssb-private + +# Install patchfoo and enable plugin +git clone https://github.com/ssbc/patchfoo.git patchfoo +sbot plugins.install ssb-private +sbot plugins.install ssb-backlinks +sbot plugins.enable patchfoo + +# Stop ssb service to process plugin +sudo systemctl stop ssb + +# Disable the git-ssb prerequisite +# Comment out two lines in patchwork that create a prerequisite for git-ssb +# but don't seem to serve any purpose. Git-ssb is not available on npm +sed -i 's#var Git#//var Git#' patchfoo/lib/app.js patchfoo/lib/app.js +sed -i 's#this.git = new Git(this.sbot, this.config)#//this.git = new Git(this.sbot, this.config)#' patchfoo/lib/app.js + +# Start service again to start patchfoo +sudo systemctl start ssb + +# Install nginx reverse proxy file +sudo cp "$BASE_DIR/ssb-patchfoo.conf" /etc/nginx/site-path-enabled/ssb-patchfoo.conf + +# shellcheck disable=SC2164 +cd "$CURRENT_DIR" \ No newline at end of file diff --git a/scripts/ssb-patchfoo/ssb-patchfoo.conf b/scripts/ssb-patchfoo/ssb-patchfoo.conf new file mode 100644 index 000000000..5ca513fda --- /dev/null +++ b/scripts/ssb-patchfoo/ssb-patchfoo.conf @@ -0,0 +1,9 @@ + location /patchfoo { + proxy_pass http://127.0.0.1:8027/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + sub_filter "=\"/" "=\"/patchfoo/"; + sub_filter_once off; + } diff --git a/scripts/ssb-web/install b/scripts/ssb-web-pi/install similarity index 82% rename from scripts/ssb-web/install rename to scripts/ssb-web-pi/install index 65d09beeb..463053179 100644 --- a/scripts/ssb-web/install +++ b/scripts/ssb-web-pi/install @@ -25,13 +25,13 @@ ssbPath="$HOME/.ssb" # Install broadcast service for users of sbot currentUser=$USER -sudo cp "$BASE_DIR/ssb-web-broadcast-service.sh" "/usr/local/bin/ssb-web-broadcast-service.sh" -sudo cp "$BASE_DIR/ssb-web-broadcast.service" /etc/systemd/system/ssb-web-broadcast.service -sudo sed -i "s|__USER__|${currentUser}|g" /etc/systemd/system/ssb-web-broadcast.service +sudo cp "$BASE_DIR/ssb-web-pi-broadcast-service.sh" "/usr/local/bin/ssb-web-pi-broadcast-service.sh" +sudo cp "$BASE_DIR/ssb-web-pi-broadcast.service" /etc/systemd/system/ssb-web-pi-broadcast.service +sudo sed -i "s|__USER__|${currentUser}|g" /etc/systemd/system/ssb-web-pi-broadcast.service sudo systemctl daemon-reload -sudo systemctl enable ssb-web-broadcast.service -sudo systemctl start ssb-web-broadcast.service +sudo systemctl enable ssb-web-pi-broadcast.service +sudo systemctl start ssb-web-pi-broadcast.service # Set permissions to let nginx access it # TODO find a better solution, maybe add user to nginx group? @@ -45,7 +45,7 @@ fi sudo ln -s "$ssbPath" /var/www/ # Create nginx site at /sbot -sudo cp "$BASE_DIR/ssb-web.conf" "/etc/nginx/site-path-enabled/ssb-web.conf" +sudo cp "$BASE_DIR/ssb-web-pi.conf" "/etc/nginx/site-path-enabled/ssb-web-pi.conf" # Pull and install client if [ -e "$BASE_DIR/tmp" ]; then diff --git a/scripts/ssb-web/ssb-web-broadcast.service b/scripts/ssb-web-pi/ssb-web-pi-broadcast.service similarity index 56% rename from scripts/ssb-web/ssb-web-broadcast.service rename to scripts/ssb-web-pi/ssb-web-pi-broadcast.service index c9625f007..815fcb204 100644 --- a/scripts/ssb-web/ssb-web-broadcast.service +++ b/scripts/ssb-web-pi/ssb-web-pi-broadcast.service @@ -1,5 +1,5 @@ [Unit] -Description=Scuttlebot Web Broadcast Service +Description=Scuttlebot Broadcast Service for ssb-web-pi Wants=network.target After=ssb.service @@ -7,10 +7,10 @@ After=ssb.service User=__USER__ Group=__USER__ Type=simple -ExecStart=/usr/local/bin/ssb-web-broadcast-service.sh +ExecStart=/usr/local/bin/ssb-web-broadcast-pi-service.sh ExecStop=/bin/kill -s QUIT $MAINPID Restart=on-failure RestartSec=10s [Install] -WantedBy=multi-user.target \ No newline at end of file +WantedBy=multi-user.target diff --git a/scripts/ssb-web/ssb-web.conf b/scripts/ssb-web-pi/ssb-web-pi.conf similarity index 77% rename from scripts/ssb-web/ssb-web.conf rename to scripts/ssb-web-pi/ssb-web-pi.conf index 6e3d400b3..4301851f0 100644 --- a/scripts/ssb-web/ssb-web.conf +++ b/scripts/ssb-web-pi/ssb-web-pi.conf @@ -1,4 +1,4 @@ -location /sbot { +location /ssb-web-pi { alias /var/www/sbot; index index.html index.htm index.nginx-debian.html index.php; try_files $uri $uri/ =404; @@ -6,7 +6,7 @@ location /sbot { try_files $uri =404; fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME /var/www/$fastcgi_script_name; + fastcgi_param SCRIPT_FILENAME $request_filename; include fastcgi_params; } -} \ No newline at end of file +} diff --git a/scripts/ssb-web/uninstall b/scripts/ssb-web-pi/uninstall similarity index 100% rename from scripts/ssb-web/uninstall rename to scripts/ssb-web-pi/uninstall From 6a2ef14d6cbaefa9da46971891c6ca8f2f01e539 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 13 Nov 2018 00:14:16 -0500 Subject: [PATCH 022/162] Restored ssb-web-broadcast-service.sh --- scripts/ssb-web-pi/ssb-web-pi-broadcast-service.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 scripts/ssb-web-pi/ssb-web-pi-broadcast-service.sh diff --git a/scripts/ssb-web-pi/ssb-web-pi-broadcast-service.sh b/scripts/ssb-web-pi/ssb-web-pi-broadcast-service.sh new file mode 100644 index 000000000..6d86a2375 --- /dev/null +++ b/scripts/ssb-web-pi/ssb-web-pi-broadcast-service.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +while true; do + while read -r id; do + for int in $(find /sys/class/net/* -maxdepth 1 -print0 | xargs -0 -l basename); do + ip=$(ip addr show "$int" | grep -v inet6 | grep -v '127.0.0.1' |grep inet | head -n 1 | awk '{print $2}' | awk -F "/" '{print $1}') + if ! [ -z "$ip" ]; then + echo -n "net:$ip:8008~shs:$id" | sudo socat -T 1 - "UDP4-DATAGRAM:255.255.255.255:8008,broadcast,so-bindtodevice=$int" & + fi + done + done <<< "$(sudo cat /var/www/backend/keys/* | grep id | grep -v "#" | awk '{print $2}' | tr -d '"' | sed 's/.ed25519//' | sed 's/@//')" + sleep 5 +done From cb7c2750a992ead33d34becc2a6e01357c0988fc Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 13 Nov 2018 00:16:51 -0500 Subject: [PATCH 023/162] Cjdns iptunnel ipv6 (#223) * Added server side ipv6 addressing * Update cjdns-setup * correct ipv6 address definition * Added routing for ipv6 and ipv4 in client mode --- scripts/cjdns-iptunnel/cjdns-setup | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/scripts/cjdns-iptunnel/cjdns-setup b/scripts/cjdns-iptunnel/cjdns-setup index 1e1d0b3f9..f91cd0574 100755 --- a/scripts/cjdns-iptunnel/cjdns-setup +++ b/scripts/cjdns-iptunnel/cjdns-setup @@ -2,23 +2,32 @@ set -e +SUBNET4="10.1.0." +SUBNET6="fe80::" + +# Enable forwarding for ipv4 and ipv6 +echo 1 > /proc/sys/net/ipv4/ip_forward +echo 1 > /proc/sys/net/ipv6/conf/all/forwarding + # Configure as cjdns iptunnel server if server file is present (this is simply a newline-separated list # of cjdns public keys in /etc/cjdns.iptunnel.server, each key indicating an allowed iptunnel client) if [ -e /etc/cjdns.iptunnel.server ]; then - # Add subnet and route for cjdns tun0 interface - ifconfig tun0 10.1.0.1/24 - route add -net 10.1.0.0/24 tun0 || true + + # Add subnet and route for cjdns tun0 interface + ip add add "${SUBNET4}1/24" dev tun0 || true + route add -net "${SUBNET4}0/24" tun0 || true + ip addr add "${SUBNET6}1/64" dev tun0 || true # Define local IP range for assigning to iptunnel clients (10.1.0.2 to 10.1.0.254) - SUBNET="10.1.0." CLIENT=2 LAST=254 # Add each client to cjdns iptunnel allowed connections while read -r PUBLIC_KEY; do if [[ "${PUBLIC_KEY}" =~ ^[0-z]{52}\.k && ${CLIENT} -le ${LAST} ]]; then - ASSIGNED_IP="${SUBNET}${CLIENT}" - /opt/cjdns/tools/cexec "IpTunnel_allowConnection('${PUBLIC_KEY}',null,null,null,0,null,'${ASSIGNED_IP}')" + ASSIGNED_IP4="${SUBNET4}${CLIENT}" + ASSIGNED_IP6="${SUBNET6}${CLIENT}" + /opt/cjdns/tools/cexec "IpTunnel_allowConnection('${PUBLIC_KEY}',0,null,'${ASSIGNED_IP6}',0,null,'${ASSIGNED_IP4}')" ((CLIENT++)) fi done < /etc/cjdns.iptunnel.server @@ -26,6 +35,7 @@ if [ -e /etc/cjdns.iptunnel.server ]; then # Configure as cjdns iptunnel client if client file is present (this is simply a newline-separated list # of cjdns public keys in /etc/cjdns.iptunnel.client, each key indicating an iptunnel exit server) elif [ -e /etc/cjdns.iptunnel.client ]; then + # Add each server to cjdns iptunnel connect-to's while read -r PUBLIC_KEY; do if [[ "${PUBLIC_KEY}" =~ ^[0-z]{52}\.k ]]; then @@ -33,7 +43,12 @@ elif [ -e /etc/cjdns.iptunnel.client ]; then fi done < /etc/cjdns.iptunnel.client - # Route NAT traffic through to cjdns tun0 interface to use iptunnel exit server + # Remove NAT from eth0 if it exists iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE || true + + # Route NAT traffic through to cjdns tun0 interface to use iptunnel exit server iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE + + # Add default ipv6 router over tun0 + ip -6 route add default dev tun0 fi \ No newline at end of file From c5316942d9622a143b3a242819144dc4fd375e04 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 18 Nov 2018 16:40:32 -0500 Subject: [PATCH 024/162] Corrected paths and sudo --- scripts/yggdrasil/install | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index c93ccd60c..d322b72dd 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -15,6 +15,6 @@ fi if [[ ! -f "/usr/local/bin/node_exporter" ]]; then mkdir "$BASE_DIR/tmp" - wget "https://236-115685026-gh.circle-artifacts.com/0/yggdrasil-${YGGDRASIL_VERSION}-${ARM_VERSION}.deb" -o "$BASE_DIR/tmp/yggdrasil.deb" - dpkg -i yggdrasil.deb -fi \ No newline at end of file + wget "https://236-115685026-gh.circle-artifacts.com/0/yggdrasil-${YGGDRASIL_VERSION}-${ARM_VERSION}.deb" -O "$BASE_DIR/tmp/yggdrasil.deb" + sudo dpkg -i "$BASE_DIR/tmp/yggdrasil.deb" +fi From ba3b2578050bb115c00259a054839918ce9e6249 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 18 Nov 2018 16:41:53 -0500 Subject: [PATCH 025/162] Updated status to include Yggdrasil and Cjdns --- scripts/status | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/scripts/status b/scripts/status index b76270929..d760b92b0 100755 --- a/scripts/status +++ b/scripts/status @@ -99,13 +99,24 @@ if [ "$(which yrd)" ]; then echo -e "yrd ........................ $INACTIVE" fi fi -echo -e '---------------------------------------' -echo -e 'NODE' -sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g' -echo -e '---------------------------------------' -echo -e 'PEERS' -read -a peers <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs` -for peer in "${peers[@]}"; do - sudo /opt/cjdns/publictoip6 "$peer" -done -echo -e '---------------------------------------' +if [ "$(which cjdroute)" ]; then + echo -e '---------------------------------------' + echo -e 'CJDNS NODE' + sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g' + echo -e '---------------------------------------' + echo -e 'PEERS' + read -a peers <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs` + for peer in "${peers[@]}"; do + sudo /opt/cjdns/publictoip6 "$peer" + done + echo -e '---------------------------------------' +fi + +if [ "$(which yggdrasil)" ]; then + echo -e '---------------------------------------' + echo -e 'YGGDRASIL NODE' + echo -e '---------------------------------------' + echo -e 'PEERS' + yggdrasilctl getPeers + echo -e '---------------------------------------' +fi From 13de2788df33a77f5d981c424bc6a0114a7be675 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 23 Nov 2018 11:56:16 -0500 Subject: [PATCH 026/162] Removed unnecessary sudo (#226) Fixes #225 --- scripts/status | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/status b/scripts/status index b76270929..6a2ac26e1 100755 --- a/scripts/status +++ b/scripts/status @@ -104,8 +104,8 @@ echo -e 'NODE' sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g' echo -e '---------------------------------------' echo -e 'PEERS' -read -a peers <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs` +read -a peers <<< `nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs` for peer in "${peers[@]}"; do - sudo /opt/cjdns/publictoip6 "$peer" + /opt/cjdns/publictoip6 "$peer" done echo -e '---------------------------------------' From 2f69576907b9b8077bac2d49cf248fee9e3e0384 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 23 Nov 2018 11:57:46 -0500 Subject: [PATCH 027/162] Expire Password on Raspberry PI (#224) * Force password change after first reboot * Added check if password was already changed Fixes #198 --- scripts/install2 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/scripts/install2 b/scripts/install2 index 3b4127a51..8be58cd4e 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -83,8 +83,11 @@ BOARD_HARDWARE=$(grep Hardware /proc/cpuinfo | awk '{print $3}' | head -n 1) # Flag to identify if board can support on-board AP. Default to false. SUPPORT_HOSTAP=false +# Flag to identify if board can support on-board hardware watchdog. SUPPORT_WATCHDOG=false + CJDNS_PACKAGE="" +CHANGE_PASSWORD="" # If board cannot be determined from /proc/cpuinfo its most likely an arbmian board so you can use the armbian generated ID file if [[ -z "$BOARD_HARDWARE" ]]; then @@ -126,6 +129,16 @@ elif [[ "$BOARD_HARDWARE" == 'nanopineo2' || "$BOARD_HARDWARE" == 'sun50iw1p1' | else BOARD_FAMILY="Raspberry Pi" BOARD_REVISION="$(sed -rn 's/Revision\s+\:\s+([0-9a-z_\-\s\,\(\)]+)/\1/p' /proc/cpuinfo)" + + # Check for default password is still set for user pi + # If it is force password before reboot + # shellcheck disable=SC2016 + DEFAULT='oAHCmfg/$uJxKZP0oOHCaz5CzamfdyDb12tKfm9RsXP1M2MmzonMyChiudpmw2gEMHEdEefrkvnQ2O4vKdXzMUXexH3bF91' + # shellcheck disable=SC2143,SC2086 + if [ "$(sudo grep pi: /etc/shadow | grep $DEFAULT)" ]; then + CHANGE_PASSWORD="pi" + fi + if [[ $BOARD_REVISION == *"900092"* || $BOARD_REVISION == *"900093"* || $BOARD_REVISION == *"9000c1"* ]]; then BOARD_NAME="Zero" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 NO_TEST=1 CFLAGS=\"-s -mfpu=vfp -O2\" ./do" @@ -427,6 +440,12 @@ newhostname=$(sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sudo echo "$newhostname" | sudo tee /etc/hostname > /dev/null sudo sed -i -e "s/$oldhostname/$newhostname/" /etc/hosts +if [[ "$CHANGE_PASSWORD" == "pi" ]]; then + sudo passwd -e "$CHANGE_PASSWORD" + echo -e "You will need to change the password next login." +fi + +echo -e "" echo -e "Your node's new hostname is $newhostname" read -p "Installation complete. Press any key to reboot your new node. " -n 1 -r From 9f8b013e4b680c159080c1a2778c63759672777a Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 23 Nov 2018 13:41:22 -0500 Subject: [PATCH 028/162] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 039685f83..cc121e006 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,6 @@ script: - docker build -t tomeshnet/prototype-cjdns-pi:${DISTRO} travis/${DISTRO}/ # Validate install script download and make executable - - docker run tomeshnet/prototype-cjdns-pi:${DISTRO} /bin/sh -c "wget https://raw.githubusercontent.com/tomeshnet/prototype-cjdns-pi/master/scripts/install; chmod +x install" + - docker run tomeshnet/prototype-cjdns-pi:${DISTRO} /bin/sh -c "wget https://raw.githubusercontent.com/tomeshnet/prototype-cjdns-pi/master/scripts/install; chmod +x install; UNATTENDED=true ./install" # TODO Test installation From 2de6d0d3d3f536d9c73887ebd143b3b8d02c248b Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 23 Nov 2018 13:41:54 -0500 Subject: [PATCH 029/162] Update install --- scripts/install | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/install b/scripts/install index 4cee27572..630849ff2 100755 --- a/scripts/install +++ b/scripts/install @@ -55,5 +55,7 @@ export WITH_SSB export WITH_SSB_PATCHFOO export WITH_SSB_WEB_PI export WITH_IPFS_PI_STREAM + +export UNATTENDED # Run the actual installation script ./install2 From 02a8baddf638b6adb0bc53cd357e07eb3898c27f Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 23 Nov 2018 19:47:29 -0500 Subject: [PATCH 030/162] Add HLS Player for IPFS Live Stream Repo (#228) Add HLS player from ipfs-live-stream Updated readme about player --- README.md | 2 +- scripts/ipfs-pi-stream/install | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ef7c1258b..314278028 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Many board that run [Armbian](https://www.armbian.com/) such as many models of O | `WITH_FIREWALL` | None | Set to `true` if you want to enable a basic firewall on your node.| | `WITH_CJDNS_IPTUNNEL` | None | Set to `true` if you want to use the cjdns iptunnel feature to set up an Internet gateway for your node. To configure as a server (exit Internet traffic for other nodes), create **/etc/cjdns.iptunnel.server** containing a newline-separated list of cjdns public keys of allowed clients. To configure as a client (use an exit server to access the Internet), create **/etc/cjdns.iptunnel.client** containing a newline-separated list of cjdns public keys of the gateway servers. You can only configure as one or the other, not both. | | `WITH_IPFS` | **80**: HTTP-to-IPFS gateway at `/ipfs/HASH` | Set to `true` if you want to install [IPFS](https://ipfs.io). | -| `WITH_IPFS_PI_STREAM` | None | Set to `true` if you want to install Pi stream service to live stream your camera over IPFS. Requires a Raspberry Pi with camera module. *Will automatically start recording on boot by default.* | +| `WITH_IPFS_PI_STREAM` | None | Set to `true` if you want to install Pi stream service to live stream your camera over IPFS. Requires a Raspberry Pi with camera module. Player interface at `/video-player` *Warning: By default the camera will start broadcasting after first reboot.* | | `WITH_SSB` | | Set to `true` if you want to install [Scuttlebot (SSB)](https://github.com/ssbc/scuttlebot) a secure scuttlebutt daemon. | | `WITH_SSB_PATCHFOO` | **80**: SSB web interface at `/patchfoo` | Set to `true` if you want to install [Patchfoo](https://github.com/ssbc/patchfoo), allows you to interact with the scuttlebot backend with a web interface. | | `WITH_SSB_WEB_PI` | **80**: SSB web interface at `/ssb-web-pi` | Set to `true` if you want to install [SSB Web Pi](https://github.com/darkdrgn2k/ssb-web-pi), interact with scuttlebot api via a web interface. **EXPERIMENTAL** | diff --git a/scripts/ipfs-pi-stream/install b/scripts/ipfs-pi-stream/install index e6bf203fa..2fe8f085a 100755 --- a/scripts/ipfs-pi-stream/install +++ b/scripts/ipfs-pi-stream/install @@ -24,3 +24,21 @@ sudo systemctl enable process-stream # Add hourly job to clear out old data echo "41 * * * * $USER /usr/local/bin/ipfs repo gc" | sudo tee --append /etc/crontab + +# Install the ipfs video player +mkdir "$BASE_DIR/tmp" +current_dir="$(pwd)" + +git clone https://github.com/tomeshnet/ipfs-live-streaming.git "$BASE_DIR/tmp/ipfs-live-streaming" +cd "$BASE_DIR/tmp/ipfs-live-streaming" +git checkout b9be352582317e5336ddd7183ecf49042dafb33e +cd "$current_dir" + +VIDEO_PLAYER_PATH="$BASE_DIR/tmp/live-streaming/terraform/shared/video-player" +sed -i s#__IPFS_GATEWAY_SELF__#/ipfs/# "$VIDEO_PLAYER_PATH/js/common.js" +sed -i s#__IPFS_GATEWAY_ORIGIN__#https://ipfs.io/ipfs/# "$VIDEO_PLAYER_PATH/js/common.js" +IPFS_ID=$(ipfs id | grep ID | head -n 1 | awk -F\" '{print $4}') +sed -i "s#live.m3u8#/ipns/$IPFS_ID#" "$VIDEO_PLAYER_PATH/js/common.js" +sed -i s#__M3U8_HTTP_URLS__#\ # "$VIDEO_PLAYER_PATH/js/common.js" +cp -r "$VIDEO_PLAYER_PATH" /var/www/html/video-player +rm -rf "$BASE_DIR/tmp" \ No newline at end of file From 0534255df95339468c6bf9e75a661bd7fea764f2 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 23 Nov 2018 19:50:29 -0500 Subject: [PATCH 031/162] Roll back change --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cc121e006..f17295ea4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,6 @@ script: - docker build -t tomeshnet/prototype-cjdns-pi:${DISTRO} travis/${DISTRO}/ # Validate install script download and make executable - - docker run tomeshnet/prototype-cjdns-pi:${DISTRO} /bin/sh -c "wget https://raw.githubusercontent.com/tomeshnet/prototype-cjdns-pi/master/scripts/install; chmod +x install; UNATTENDED=true ./install" + # - docker run tomeshnet/prototype-cjdns-pi:${DISTRO} /bin/sh -c "wget https://raw.githubusercontent.com/tomeshnet/prototype-cjdns-pi/master/scripts/install; chmod +x install; ./install" # TODO Test installation From 8537300bfe28db9168008d27939ebcb809b160c5 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 25 Nov 2018 15:08:10 -0500 Subject: [PATCH 032/162] Corrected incorrect binary path --- scripts/yggdrasil/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index d322b72dd..110419c55 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -13,7 +13,7 @@ if uname -m | grep -q aarch64; then ARM_VERSION=arm64 fi -if [[ ! -f "/usr/local/bin/node_exporter" ]]; then +if [[ ! -f "/usr/bin/yggdrasil" ]]; then mkdir "$BASE_DIR/tmp" wget "https://236-115685026-gh.circle-artifacts.com/0/yggdrasil-${YGGDRASIL_VERSION}-${ARM_VERSION}.deb" -O "$BASE_DIR/tmp/yggdrasil.deb" sudo dpkg -i "$BASE_DIR/tmp/yggdrasil.deb" From 9201a816211c34f67d5e40d0749d59a0692feec4 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 25 Nov 2018 19:53:49 -0500 Subject: [PATCH 033/162] Remove has password changed --- scripts/install2 | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/install2 b/scripts/install2 index 8be58cd4e..f498ac999 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -133,11 +133,9 @@ else # Check for default password is still set for user pi # If it is force password before reboot # shellcheck disable=SC2016 - DEFAULT='oAHCmfg/$uJxKZP0oOHCaz5CzamfdyDb12tKfm9RsXP1M2MmzonMyChiudpmw2gEMHEdEefrkvnQ2O4vKdXzMUXexH3bF91' + # shellcheck disable=SC2143,SC2086 - if [ "$(sudo grep pi: /etc/shadow | grep $DEFAULT)" ]; then - CHANGE_PASSWORD="pi" - fi + CHANGE_PASSWORD="pi" if [[ $BOARD_REVISION == *"900092"* || $BOARD_REVISION == *"900093"* || $BOARD_REVISION == *"9000c1"* ]]; then BOARD_NAME="Zero" From dd2b2c1943e18b2ac45976bb95cff6a0e8bb1cff Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 26 Nov 2018 15:05:43 -0500 Subject: [PATCH 034/162] Node welcome page (#230) * Create home page with list of service --- scripts/grafana/install | 4 ++++ scripts/install2 | 31 +++++++++++++++++-------------- scripts/ipfs-pi-stream/install | 8 ++++++-- scripts/ipfs/install | 4 ++++ scripts/shared/nginx/index.html | 9 +++++++++ scripts/shared/nginx/install | 6 ++++++ scripts/shared/nginx/uninstall | 1 + scripts/ssb-patchfoo/install | 4 ++++ scripts/ssb-web-pi/install | 4 ++++ 9 files changed, 55 insertions(+), 16 deletions(-) create mode 100644 scripts/shared/nginx/index.html diff --git a/scripts/grafana/install b/scripts/grafana/install index 0461342e1..1509c1939 100755 --- a/scripts/grafana/install +++ b/scripts/grafana/install @@ -41,3 +41,7 @@ else echo -e "\e[1;31mGrafana is taking longer than normal to start\e[0m" echo -e "\e[1;31mSkipping configuration and continuing install\e[0m" fi + +# Add entry into nginx home screen +APP="

Grafana

The open platform for beautiful analytics and monitoring.
Go
" +sudo sed -i "s#<\!--APPLIST-->#$APP\n<\!--APPLIST-->#" "/var/www/html/index.html" diff --git a/scripts/install2 b/scripts/install2 index 8be58cd4e..c62b098b8 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -208,6 +208,15 @@ fi # Prompt and set missing flags +# Prompt for name of the mesh network +##TODO## Add dialog option +read -p "Enter the name of your mesh network (default: tomesh): " -r +MESH_NAME="${REPLY// }" +if [ "${#MESH_NAME}" == 0 ]; then + MESH_NAME="tomesh" +fi +export MESH_NAME + askModule "WITH_MESH_POINT" "Mesh Point Interface" if [ "$WITH_MESH_POINT" == false ]; then askModule "WITH_AD_HOC" "Ad-Hoc Interface" @@ -241,15 +250,6 @@ if [ "$SUPPORT_WATCHDOG" == "true" ]; then askModule "WITH_WATCHDOG" "Hardware Watchdog" fi -# Prompt for name of the mesh network -##TODO## This should be moved up to to mesh point question -read -p "Enter the name of your mesh network (default: tomesh): " -r -MESH_NAME="${REPLY// }" -if [ "${#MESH_NAME}" == 0 ]; then - MESH_NAME="tomesh" -fi -export MESH_NAME - # Get tools if ! [ "$(which nodejs)" ]; then # Check for armv6 and install nodejs manually instead since it will not install via repo @@ -327,6 +327,10 @@ fi sudo systemctl enable cjdns.service +# Define new hostname +NEWHOSTNAME=$(sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g' | sed "s/.*:/$MESH_NAME-/g") +export NEWHOSTNAME + # 802.11s Mesh Point interface if [ "$(checkModule 'WITH_MESH_POINT')" ]; then source mesh-point/install @@ -436,9 +440,8 @@ cp ~/.profile ~/.bash_profile } >> ~/.bash_profile # Rename node based on cjdns address oldhostname=$(hostname) -newhostname=$(sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g' | sed "s/.*:/$MESH_NAME-/g") -sudo echo "$newhostname" | sudo tee /etc/hostname > /dev/null -sudo sed -i -e "s/$oldhostname/$newhostname/" /etc/hosts +sudo echo "$NEWHOSTNAME" | sudo tee /etc/hostname > /dev/null +sudo sed -i -e "s/$oldhostname/$NEWHOSTNAME/" /etc/hosts if [[ "$CHANGE_PASSWORD" == "pi" ]]; then sudo passwd -e "$CHANGE_PASSWORD" @@ -446,8 +449,8 @@ if [[ "$CHANGE_PASSWORD" == "pi" ]]; then fi echo -e "" -echo -e "Your node's new hostname is $newhostname" - +echo -e "Your node's new hostname is $NEWHOSTNAME" +echo -e "" read -p "Installation complete. Press any key to reboot your new node. " -n 1 -r # Reboot device diff --git a/scripts/ipfs-pi-stream/install b/scripts/ipfs-pi-stream/install index 2fe8f085a..27da31a5c 100755 --- a/scripts/ipfs-pi-stream/install +++ b/scripts/ipfs-pi-stream/install @@ -34,11 +34,15 @@ cd "$BASE_DIR/tmp/ipfs-live-streaming" git checkout b9be352582317e5336ddd7183ecf49042dafb33e cd "$current_dir" -VIDEO_PLAYER_PATH="$BASE_DIR/tmp/live-streaming/terraform/shared/video-player" +VIDEO_PLAYER_PATH="$BASE_DIR/tmp/ipfs-live-streaming/terraform/shared/video-player" sed -i s#__IPFS_GATEWAY_SELF__#/ipfs/# "$VIDEO_PLAYER_PATH/js/common.js" sed -i s#__IPFS_GATEWAY_ORIGIN__#https://ipfs.io/ipfs/# "$VIDEO_PLAYER_PATH/js/common.js" IPFS_ID=$(ipfs id | grep ID | head -n 1 | awk -F\" '{print $4}') sed -i "s#live.m3u8#/ipns/$IPFS_ID#" "$VIDEO_PLAYER_PATH/js/common.js" sed -i s#__M3U8_HTTP_URLS__#\ # "$VIDEO_PLAYER_PATH/js/common.js" cp -r "$VIDEO_PLAYER_PATH" /var/www/html/video-player -rm -rf "$BASE_DIR/tmp" \ No newline at end of file +rm -rf "$BASE_DIR/tmp" + +# Add entry into nginx home screen +APP="

IPFS Pi Stream Player

IPFS Video player for Pi Stream.
Stream at /ipns/$IPFS_ID
Go
" +sudo sed -i "s#<\!--APPLIST-->#$APP\n<\!--APPLIST-->#" "/var/www/html/index.html" diff --git a/scripts/ipfs/install b/scripts/ipfs/install index cdcb45992..36de1de93 100755 --- a/scripts/ipfs/install +++ b/scripts/ipfs/install @@ -48,3 +48,7 @@ sudo sed -i "s|__USER_HOME__|${HOME}|" /etc/systemd/system/ipfs.service sudo systemctl daemon-reload sudo systemctl enable ipfs.service sudo systemctl start ipfs.service + +# Add entry into nginx home screen +APP="

IPFS

A peer-to-peer hypermedia protocol to make the web faster, safer, and more open.
Go
" +sudo sed -i "s#<\!--APPLIST-->#$APP\n<\!--APPLIST-->#" "/var/www/html/index.html" \ No newline at end of file diff --git a/scripts/shared/nginx/index.html b/scripts/shared/nginx/index.html new file mode 100644 index 000000000..0c390e988 --- /dev/null +++ b/scripts/shared/nginx/index.html @@ -0,0 +1,9 @@ + + +

Welcome to Node __NODENAME__

+ +Services running on this node.
+
+ + + diff --git a/scripts/shared/nginx/install b/scripts/shared/nginx/install index 56257eb26..1d81e8243 100755 --- a/scripts/shared/nginx/install +++ b/scripts/shared/nginx/install @@ -12,5 +12,11 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th sudo ln -s /etc/nginx/sites-available/main.conf /etc/nginx/sites-enabled/main.conf || true sudo rm /etc/nginx/sites-enabled/default || true sudo mkdir /etc/nginx/site-path-enabled || true + + # Install welcome page + sudo cp "$BASE_DIR/index.html" "/var/www/html/index.html" + sudo sed -i "s/__NODENAME__/$NEWHOSTNAME/" "/var/www/html/index.html" + BASE_DIR="$LAST_BASE" + fi diff --git a/scripts/shared/nginx/uninstall b/scripts/shared/nginx/uninstall index 6d2a44639..89208895f 100644 --- a/scripts/shared/nginx/uninstall +++ b/scripts/shared/nginx/uninstall @@ -5,3 +5,4 @@ sudo rm -rf /etc/nginx/sites-enabled/main.conf || true sudo rm /etc/nginx/sites-enabled/default || true sudo rm -rf /etc/nginx/site-path-enabled || true sudo apt-get remove nginx -y +sudo rm -rf /var/www/html/index.html \ No newline at end of file diff --git a/scripts/ssb-patchfoo/install b/scripts/ssb-patchfoo/install index 32760b61a..1b5e2c0a0 100755 --- a/scripts/ssb-patchfoo/install +++ b/scripts/ssb-patchfoo/install @@ -38,5 +38,9 @@ sudo systemctl start ssb # Install nginx reverse proxy file sudo cp "$BASE_DIR/ssb-patchfoo.conf" /etc/nginx/site-path-enabled/ssb-patchfoo.conf +# Add entry into nginx home screen +APP="

Patch Foo

Plain SSB web UI.
Go
" +sudo sed -i "s#<\!--APPLIST-->#$APP\n<\!--APPLIST-->#" "/var/www/html/index.html" + # shellcheck disable=SC2164 cd "$CURRENT_DIR" \ No newline at end of file diff --git a/scripts/ssb-web-pi/install b/scripts/ssb-web-pi/install index 463053179..f4fa91328 100644 --- a/scripts/ssb-web-pi/install +++ b/scripts/ssb-web-pi/install @@ -70,3 +70,7 @@ sudo chmod a+rwX /var/www/backend sudo chmod -R a+rwX /var/www/backend sudo chown www-data.www-data /var/www/sbot sudo chown -R www-data.www-data /var/www/sbot + +# Add entry into nginx home screen +APP="

SSB Web Pi

Very experimental interface for SSB.
Go
" +sudo sed -i "s#<\!--APPLIST-->#$APP\n<\!--APPLIST-->#" "/var/www/html/index.html" From e81a008a94141e1a30721880221507dcdf0e687c Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 26 Nov 2018 15:07:19 -0500 Subject: [PATCH 035/162] Update process-stream.sh --- scripts/ipfs-pi-stream/process-stream.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ipfs-pi-stream/process-stream.sh b/scripts/ipfs-pi-stream/process-stream.sh index 4dd5ada99..994de3dce 100755 --- a/scripts/ipfs-pi-stream/process-stream.sh +++ b/scripts/ipfs-pi-stream/process-stream.sh @@ -14,7 +14,7 @@ function startFFmpeg() { while true; do mv ~/ffmpeg.log ~/ffmpeg.1 echo 1 > ~/stream-reset - ffmpeg -f video4linux2 -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -hls_time "${HLS_TIME}" "${what}.m3u8" > ~/ffmpeg 2>&1 + ffmpeg -f video4linux2 -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -hls_time "${HLS_TIME}" "${what}.m3u8" > ~/ffmpeg.log 2>&1 sleep 0.5 done } From 446a070db468bbbc66fdf5df48294487d439c0be Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 26 Nov 2018 15:16:29 -0500 Subject: [PATCH 036/162] Prevent ipns caching --- scripts/ipfs/ipfs-http-gateway.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/ipfs/ipfs-http-gateway.conf b/scripts/ipfs/ipfs-http-gateway.conf index 632524d5e..2ccb3b304 100644 --- a/scripts/ipfs/ipfs-http-gateway.conf +++ b/scripts/ipfs/ipfs-http-gateway.conf @@ -12,4 +12,7 @@ proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; + # Prevent Caching + expires 0; + add_header Cache-Control private; } From 5f433b026804e2016b34b7e1c70674a98753783f Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 29 Nov 2018 21:33:30 -0500 Subject: [PATCH 037/162] Added multicast address for yagdrissil --- scripts/firewall/rules.v6 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 3f1aadd4f..dd759c7bb 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -14,5 +14,6 @@ -A INPUT -j ACCEPT -p tcp --dport 4001 -A INPUT -j ACCEPT -p tcp --dport 9090 -A INPUT -j ACCEPT -p tcp --dport 9100 +-A INPUT -j ACCEPT -p udp --dport 9001 -d ff02::114 -A INPUT -j REJECT --reject-with icmp6-port-unreachable COMMIT From 6df9e00d93512f3c978d42c1560da04eff88e1fa Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 29 Nov 2018 21:36:49 -0500 Subject: [PATCH 038/162] Updated peer lookup --- scripts/status | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/status b/scripts/status index a49b8f3d6..0a00d6103 100755 --- a/scripts/status +++ b/scripts/status @@ -114,10 +114,12 @@ if [ "$(which cjdroute)" ]; then fi if [ "$(which yggdrasil)" ]; then + MYIP=$(yggdrasilctl getPEers | grep "0 0" | awk '{print $1}') echo -e '---------------------------------------' echo -e 'YGGDRASIL NODE' + echo -e $MYIP echo -e '---------------------------------------' echo -e 'PEERS' - yggdrasilctl getPeers + yggdrasilctl getPeers | grep -v "$MYIP" | awk '{print $1}' | grep -v "bytes_recvd" echo -e '---------------------------------------' fi From f721d9fdfae3a31d054f96c68c8e602af0972e91 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 30 Nov 2018 08:05:08 -0500 Subject: [PATCH 039/162] Update interface name --- scripts/yggdrasil/install | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index 110419c55..c020b3670 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -18,3 +18,6 @@ if [[ ! -f "/usr/bin/yggdrasil" ]]; then wget "https://236-115685026-gh.circle-artifacts.com/0/yggdrasil-${YGGDRASIL_VERSION}-${ARM_VERSION}.deb" -O "$BASE_DIR/tmp/yggdrasil.deb" sudo dpkg -i "$BASE_DIR/tmp/yggdrasil.deb" fi + +# Change configuration to have yaggdrasil's tun interface called ygg0 +sudo sed -i "s/IfName: auto/IfName: ygg0/" /etc/yggdrasil.conf From 468a9126089e0fb956489a72a27e40ac74ed241f Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 30 Nov 2018 08:06:37 -0500 Subject: [PATCH 040/162] added ygg0 to nat --- scripts/hostapd/nat.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/hostapd/nat.sh b/scripts/hostapd/nat.sh index c04184a2d..af01cc5eb 100755 --- a/scripts/hostapd/nat.sh +++ b/scripts/hostapd/nat.sh @@ -7,5 +7,6 @@ ip6tables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmt # Forward all IPv4 traffic from the internal network to the eth0 device and mask with the eth0 external IP address iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE -# Forward all IPv6 traffic from the internal network to the tun0 device and mask with the tun0 external IP address +# Allow all IPv6 traffic routed out tun0 an ygg0 to be masked with their respective external IP address ip6tables -t nat -A POSTROUTING -o tun0 -j MASQUERADE +ip6tables -t nat -A POSTROUTING -o ygg0 -j MASQUERADE From f7de27c76b7052d27b22d3aaa730131f5a056496 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 30 Nov 2018 08:07:59 -0500 Subject: [PATCH 041/162] removed uneeded cjdns group --- scripts/firewall/rules.v6 | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index dd759c7bb..172d6f3bf 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -2,7 +2,6 @@ :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -:cjdns - [0:0] -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT From 5aad8f800dad90f924c18ad0d2a241494bcce37d Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 30 Nov 2018 08:21:18 -0500 Subject: [PATCH 042/162] Lock port to specific value --- scripts/yggdrasil/install | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index c020b3670..b06ef6f72 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -21,3 +21,8 @@ fi # Change configuration to have yaggdrasil's tun interface called ygg0 sudo sed -i "s/IfName: auto/IfName: ygg0/" /etc/yggdrasil.conf + +# Change port to 12345 for firewall +YGGDRASIL_PORT=$(sudo cat /etc/yggdrasil.conf | grep \ Listen\: | awk '{print $2}' | tr -d \") +YGGDRASIL_PORT=$(printf "%q" $YGGDRASIL_PORT) # Escape for sed +sudo sed -i "s/$YGGDRASIL_PORT/\[::\]:12345/" /etc/yggdrasil.conf From 73f846fe3c15d536313e5f5adecf1fe3938d1347 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 30 Nov 2018 08:22:18 -0500 Subject: [PATCH 043/162] Add yggdrasil to ports --- scripts/firewall/rules.v6 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 172d6f3bf..e86005e16 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -13,6 +13,7 @@ -A INPUT -j ACCEPT -p tcp --dport 4001 -A INPUT -j ACCEPT -p tcp --dport 9090 -A INPUT -j ACCEPT -p tcp --dport 9100 +-A INPUT -j ACCEPT -p udp --dport 12345 -A INPUT -j ACCEPT -p udp --dport 9001 -d ff02::114 -A INPUT -j REJECT --reject-with icmp6-port-unreachable COMMIT From e652a6207282b3a76412fcb8e74f3ad7ba485c5c Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 30 Nov 2018 08:42:20 -0500 Subject: [PATCH 044/162] Remove whitespace and version bump --- scripts/yggdrasil/install | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index b06ef6f72..4bde352a3 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -2,7 +2,9 @@ set -e -YGGDRASIL_VERSION=0.2.6 +YGGDRASIL_VERSION=0.2.7 +YGGDRASIL_HOST=259-115685026 + BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -15,8 +17,9 @@ fi if [[ ! -f "/usr/bin/yggdrasil" ]]; then mkdir "$BASE_DIR/tmp" - wget "https://236-115685026-gh.circle-artifacts.com/0/yggdrasil-${YGGDRASIL_VERSION}-${ARM_VERSION}.deb" -O "$BASE_DIR/tmp/yggdrasil.deb" + wget "https://${YGGDRASIL_HOST}-gh.circle-artifacts.com/0/yggdrasil-${YGGDRASIL_VERSION}-${ARM_VERSION}.deb" -O "$BASE_DIR/tmp/yggdrasil.deb" sudo dpkg -i "$BASE_DIR/tmp/yggdrasil.deb" + rm -rf "$BASE_DIR/tmp" fi # Change configuration to have yaggdrasil's tun interface called ygg0 From 5d1d68d04de9a3a2706202311853ad70de8b8773 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 14:45:03 -0500 Subject: [PATCH 045/162] shellcheck changes --- scripts/yggdrasil/install | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index 4bde352a3..4d652d1da 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -26,6 +26,6 @@ fi sudo sed -i "s/IfName: auto/IfName: ygg0/" /etc/yggdrasil.conf # Change port to 12345 for firewall -YGGDRASIL_PORT=$(sudo cat /etc/yggdrasil.conf | grep \ Listen\: | awk '{print $2}' | tr -d \") -YGGDRASIL_PORT=$(printf "%q" $YGGDRASIL_PORT) # Escape for sed +YGGDRASIL_PORT=$(sudo cat /etc/yggdrasil.conf | grep \ Listen: | awk '{print $2}' | tr -d \") +YGGDRASIL_PORT=$(printf "%q" "$YGGDRASIL_PORT") # Escape for sed sudo sed -i "s/$YGGDRASIL_PORT/\[::\]:12345/" /etc/yggdrasil.conf From 361caefa346cbe8a8650d3f48aa3ade148bf3582 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 14:50:21 -0500 Subject: [PATCH 046/162] Uninstall script for yaggdrasil --- scripts/yggdrasil/uninstall | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 scripts/yggdrasil/uninstall diff --git a/scripts/yggdrasil/uninstall b/scripts/yggdrasil/uninstall new file mode 100644 index 000000000..72c896d53 --- /dev/null +++ b/scripts/yggdrasil/uninstall @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -e + +sudo apt-get remove -y yggdrasil + +if [ -f "/etc/yggdrasil.conf " ]; then + echo "Found /etc/yggdrasil.conf " + read -p "Keep your yggdrasil identity (Y/n)? " -n 1 -r + echo "" + if [[ $REPLY =~ ^[Nn]$ ]]; then + echo -e "\e[1;31mRemoving /etc/yggdrasil.conf\e[0m" + sudo rm -f /etc/yggdrasil.conf + else + echo -e "\e[1;32mKeeping /etc/yggdrasil.conf\e[0m" + fi +fi From 20a4acc5e076d3a97c785bdcfe446c9468a84818 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 14:51:29 -0500 Subject: [PATCH 047/162] added WITH_YGGDRASIL variable --- scripts/install | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/install b/scripts/install index 630849ff2..c73439405 100755 --- a/scripts/install +++ b/scripts/install @@ -39,6 +39,7 @@ cd prototype-cjdns-pi/scripts git checkout $TAG_PROTOTYPE_CJDNS_PI # Export environment variables +export WITH_YGGDRASIL export WITH_MESH_POINT export WITH_AD_HOC export WITH_WIFI_AP From 99f1030ae06d6f12485d9d91a041bf33d0091a8e Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 14:55:21 -0500 Subject: [PATCH 048/162] Added WITH_YGGDRASIL --- scripts/install2 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/install2 b/scripts/install2 index 8be58cd4e..fccc3929d 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -208,6 +208,8 @@ fi # Prompt and set missing flags +askModule "WITH_YGGDRASIL" "Yggdrasil routing engine" + askModule "WITH_MESH_POINT" "Mesh Point Interface" if [ "$WITH_MESH_POINT" == false ]; then askModule "WITH_AD_HOC" "Ad-Hoc Interface" @@ -327,6 +329,11 @@ fi sudo systemctl enable cjdns.service +# Install yggdrasil +if [ "$(checkModule 'WITH_YGGDRASIL')" ]; then + source mesh-yggdrasil/install +fi + # 802.11s Mesh Point interface if [ "$(checkModule 'WITH_MESH_POINT')" ]; then source mesh-point/install From ef900d1b4af831897aaec98fbbfb85260e02456b Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 14:55:47 -0500 Subject: [PATCH 049/162] remove of yggdrasil --- scripts/uninstall | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/uninstall b/scripts/uninstall index 338e75d5f..e7cad5d52 100755 --- a/scripts/uninstall +++ b/scripts/uninstall @@ -39,6 +39,7 @@ source "$BASE_DIR/watchdog/uninstall" source "$BASE_DIR/yrd/uninstall" source "$BASE_DIR/shared/nodeinfo/uninstall" source "$BASE_DIR/shared/nginx/uninstall" +source "$BASE_DIR/yggdrasil/uninstall" sudo systemctl daemon-reload From 8aa24de89035a8a723113b492d61bf38e03f47ee Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 15:28:20 -0500 Subject: [PATCH 050/162] correct path --- scripts/install2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install2 b/scripts/install2 index 832bfd113..d470dbff4 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -335,7 +335,7 @@ export NEWHOSTNAME # Install yggdrasil if [ "$(checkModule 'WITH_YGGDRASIL')" ]; then - source mesh-yggdrasil/install + source yggdrasil/install fi # 802.11s Mesh Point interface From 5a948cbfbb3da266ec990afaa8eb86c29bd4d86f Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 15:39:52 -0500 Subject: [PATCH 051/162] Corrected spelling mistake --- scripts/hostapd/nat.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/hostapd/nat.sh b/scripts/hostapd/nat.sh index af01cc5eb..d5fbf0349 100755 --- a/scripts/hostapd/nat.sh +++ b/scripts/hostapd/nat.sh @@ -7,6 +7,6 @@ ip6tables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmt # Forward all IPv4 traffic from the internal network to the eth0 device and mask with the eth0 external IP address iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE -# Allow all IPv6 traffic routed out tun0 an ygg0 to be masked with their respective external IP address +# Allow all IPv6 traffic routed out tun0 and ygg0 to be masked with their respective external IP address ip6tables -t nat -A POSTROUTING -o tun0 -j MASQUERADE ip6tables -t nat -A POSTROUTING -o ygg0 -j MASQUERADE From cb41dfa772878952c78b51943a614fa12ca9b0a2 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 15:41:49 -0500 Subject: [PATCH 052/162] Corrected capitalization --- scripts/status | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/status b/scripts/status index 0a00d6103..501d35f4d 100755 --- a/scripts/status +++ b/scripts/status @@ -114,7 +114,7 @@ if [ "$(which cjdroute)" ]; then fi if [ "$(which yggdrasil)" ]; then - MYIP=$(yggdrasilctl getPEers | grep "0 0" | awk '{print $1}') + MYIP=$(yggdrasilctl getPeers | grep "0 0" | awk '{print $1}') echo -e '---------------------------------------' echo -e 'YGGDRASIL NODE' echo -e $MYIP From 82fbfe21bd525a972c7d4628df5dc087b690f162 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 15:53:51 -0500 Subject: [PATCH 053/162] Update install --- scripts/yggdrasil/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index 4d652d1da..f1744543a 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -22,7 +22,7 @@ if [[ ! -f "/usr/bin/yggdrasil" ]]; then rm -rf "$BASE_DIR/tmp" fi -# Change configuration to have yaggdrasil's tun interface called ygg0 +# Change configuration to have yggdrasil's tun interface called ygg0 sudo sed -i "s/IfName: auto/IfName: ygg0/" /etc/yggdrasil.conf # Change port to 12345 for firewall From ed3d806fc61ec16d2789f5537034b3a7f00d0cc4 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 16:18:29 -0500 Subject: [PATCH 054/162] Update status --- scripts/status | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/status b/scripts/status index 501d35f4d..e94227296 100755 --- a/scripts/status +++ b/scripts/status @@ -15,6 +15,12 @@ if [ "$(systemctl status cjdns.service | grep 'Active: ' | awk '{ print $2 }')" else echo -e "cjdns Service .............. $INACTIVE" fi +if [ "$(systemctl status yggdrasil.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then + echo -e "Yggdrasil Service ............ $ACTIVE" +else + echo -e "Yggdrasil Service .......... $INACTIVE" +fi + if [ "$(which mesh-point)" ]; then ints=$(iw dev | grep Interface | awk '{print $2}') while read -r line; do From f352abda562c5be634cccf1f408d764209579b64 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 16:21:50 -0500 Subject: [PATCH 055/162] Better way of finding the ipaddress for yggdrasil --- scripts/status | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/status b/scripts/status index e94227296..0970c40ab 100755 --- a/scripts/status +++ b/scripts/status @@ -120,7 +120,7 @@ if [ "$(which cjdroute)" ]; then fi if [ "$(which yggdrasil)" ]; then - MYIP=$(yggdrasilctl getPeers | grep "0 0" | awk '{print $1}') + MYIP=$(ifconfig ygg0 | grep inet6 | grep 202 | awk '{print $2}') echo -e '---------------------------------------' echo -e 'YGGDRASIL NODE' echo -e $MYIP From 932cb01563aa22d1d891b53a7fe5a0170b6b273f Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 1 Dec 2018 16:24:04 -0500 Subject: [PATCH 056/162] Update status --- scripts/status | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/status b/scripts/status index 0970c40ab..5622bfc6a 100755 --- a/scripts/status +++ b/scripts/status @@ -111,7 +111,7 @@ if [ "$(which cjdroute)" ]; then echo -e 'CJDNS NODE' sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g' echo -e '---------------------------------------' - echo -e 'PEERS' + echo -e 'CJDNS PEERS' read -a peers <<< `sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs` for peer in "${peers[@]}"; do sudo /opt/cjdns/publictoip6 "$peer" @@ -125,7 +125,7 @@ if [ "$(which yggdrasil)" ]; then echo -e 'YGGDRASIL NODE' echo -e $MYIP echo -e '---------------------------------------' - echo -e 'PEERS' + echo -e 'YGGDRASIL PEERS' yggdrasilctl getPeers | grep -v "$MYIP" | awk '{print $1}' | grep -v "bytes_recvd" echo -e '---------------------------------------' fi From 83de250e580569e40d8a43c95191ecd575dd94f6 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 15 Dec 2018 09:47:03 -0500 Subject: [PATCH 057/162] Pi stream for SDR (#253) dded contrib file to compile and install SDR driver. Added image placeholder for audio only streams Added commented line to change from Pi Camera to SDR --- contrib/pi-stream/install-srd-drivers.sh | 16 ++++++++++++++++ scripts/ipfs-pi-stream/audio.jpg | Bin 0 -> 32269 bytes scripts/ipfs-pi-stream/install | 5 ++++- scripts/ipfs-pi-stream/process-stream.sh | 7 +++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 contrib/pi-stream/install-srd-drivers.sh create mode 100644 scripts/ipfs-pi-stream/audio.jpg diff --git a/contrib/pi-stream/install-srd-drivers.sh b/contrib/pi-stream/install-srd-drivers.sh new file mode 100644 index 000000000..af10b7773 --- /dev/null +++ b/contrib/pi-stream/install-srd-drivers.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# Install SDR drivers +sudo apt-get install -y cmake git libusb-1.0-0-dev +git clone git://git.osmocom.org/rtl-sdr.git +cd rtl-sdr +mkdir build +cd build +cmake ../ -DINSTALL_UDEV_RULES=ON +make +sudo make install +sudo ldconfig + +# Make drivers work +sudo cp ../rtl-sdr.rules /etc/udev/rules.d/ +echo blacklist dvb_usb_rtl28xxu | sudo tee /etc/modprobe.d/blacklist-rtl.conf > /dev/null diff --git a/scripts/ipfs-pi-stream/audio.jpg b/scripts/ipfs-pi-stream/audio.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9850d25138c04a8585071467e1c0867ccdf05848 GIT binary patch literal 32269 zcmbTdcT^K^^gcKcAbRx|NG~G2gpL9N3Q7~CgQ0_fV(3i)6Oa;60g(V`jLeLeE?v2Lg_#w?#>U3L#LjUQ!odPz zgHV9T*Hcl`QB%`FE?>F~`TsmFS^;KS3TMhN5XB9El9>X;OmXp(;u8Q+P*eP`0sQZS zf|5Kx8Za##{iQ1aB?SmXNd@|Ew&W{A$>#tnW@?t}lIk?9CQraOydifZQ}Su~?^m|5 znGO;Kq@Maj(a~RJ=iubJc}q}8SVUSz_MV))g2n?)Eo~iLJu`C)ORI;EtR0=6J$H6- zb@TP}4+so;1&@9m6C3yDZG384dPZi}`w!Wl3JQyg(IusyzgJb))YjEEG`4sA?8M@_ zx_gF(NB)eCjZaK2EaI2`F0ZVvt?%sa?H?TeJ32n006_m^4*B~*FZX_+_eoB628y&xtDUt1|&mjF(0qKRCJO7#V zzbyKHXHeAtFN^+9gZ@u@E+zp65CwU`K+J$Da8~vtRysX!zhLZmv{pbeT3e5{7s5wR z4Ke2X6fe~YK)4ZMekN+IKFV=!#&n&acp9lqwSksqVX1hNvHikrwN4(x>#M?+$p^&| zkH>p&xvF#UbN0ja0@ykQvpwX!VDfn-`_dbH#&kH4axdQ|GJWyKPV2wCTN`@=&P9sU z*fgU{$;xYNuC3t*B|2&_H!w)rdl;HzrpC#prsxT)0Vl&s&q}=jdG5o`d&E3ylAoE* zJnzR+_09eZ!0zK)%8AZvl_)&}hTwr$%OB&sVf=aE<01bd5aQo{f!yY{T1-D$uJ}N{ z2qXyEx41*06qwJ)0YUoW$_y$?pE0yDHYLK`p0Y^X4LINnya1Gj@V82@(@1E^Z>H!` z00$uD&{a^S90d8tlC86!N50?s9=C({xyzI4WEZ9RfDMtTMOljZCDT+!g(d%$vRiV} zdCbvMvl&r~&od&yJm)TeGfg_ft|8?WIK6S~$E2ZLIyukdWNg1V(mk;SR+qvD0~)HNZ- z6k2iz1!WKhYwDX2T4O2wR7SWdMYdG7OCd17*LzdkaZH*%KL&V?eB<kS69yL|D4!)$V5Fp(`(0ebz13OLCv zXS=cp5eB%-K{UA~FsdcLgHniKruWAQ{P1kq4I3^669hcewIi(`Rwlx52%h}>Q&xgS zGSUbt%o`hT9xqkN^r5xmSbiWB|C}+PQUPI#{HxoQwO)@^6 zlyNQbJk(v*<;`iz@N7CBiq~!yT*y8AI^p!duSkH%L|KRf&&9uO_$NahZ=~#sR@Dp8 zT~0&imvCL-HiMa%O8Eq>$oI*YOr~*N(-bN!rI;#}+8j-dw-jdTyv`jwWTF|hXrc*` z=KB;SnFJSk0O8#?QKOMkKP+fwyXkqIWS9PzQ^}N`y>t`iffb(5*0VgtrhcH%ghU_Y zJsmKFS_@6fQVhil!}jv-n+~`ryXNOX3d&^Dy=QYYK*uKWmIsBswD+iAIM3#e3r45t zXshDy3*C_#9{ti~?Rg!?Q80-F6FNa_xjUK>E^N1S0WWPk;XH@kS7-)CbmiKK1>GA) zBdOLEh~s4~Nu(;5-B%Z2JDv$54(5*%1{)0P*wBX=YadJBcHn0G;a><6%m%s^-tu>nIiK;e4fFHqswtmm^Bd)py~{ae|Vm)lN4UD+didvANUtqc#n zK7PC5vJOfD0}Otfq~M`>zqSHS&~dicHFb{e0~uXlcwpWe)sxJMBIu7NMpx(=*Z(Uv z%4^oeah|*4A`=@{vegQCIx1>ZfeJg{VT@k&b-J~)5^nB)YerNY=SRHfYXwPq0W6S2 zNvx1DML$jCFW>He1;xTN5z0*@^EhsVBQ%EUN#l}vJT2f{?6&En1v*Sv=+h81@jcqaT@j_Av08&oR~7sz$``U74{Wd!1YS1km#{BJ>$qVOw^A75GYjBhUj%p-JT$pow0%DFFH9`Z?@llPoSMpDHfRGxrrWwt1MswMGi zDLaP&*gfvzsozk%02Cr3_tEuj2jJYHdn-wQb*k^LfahkD5lnhkhlPUj;K(ty9O(xh z2SpqlZ7Znulvvn70RY1BACDSTBIJsh5rL&Jxz>|&SA>YQFr7B+Wsx8ZRwn-BQ38b$ zgO|4VY<5r=no+x%${S@Tsdl{(+8(`&R2Upt%yzx|m9sy@%+<9AOtrVE?~VAB1!3ba zDWuTV*VT-#0%Yr#gHDEwue+%1rxz~$Nxvx$fBdtACr&!L47dqt7Cvf~ z?q=4uw>CLB9TL-(Zf^251maZ{Os1x?Z7+Z{EwxTbTi|jlAv-fTur3+f!61nZ{Vd_t zN|Ihl3uf)^FEib{GO0eov@#hPp}rm}thVZ%I3mD)ZG5j+9PQ?V2u^%|CXDm^?YP_* zS~@w;oQ%G6S8}-MIw#G?h_4z9DYzP{9c0-1=FaqaRJ!nj)rQ*e3?500hmrw%`Pqd`N+Yu=kk zua#P+ zFxLn#?QnIAr=TbZpuT;OC(g}SO+;@y^1cp~Ljw zUs4>3i$vvZ!}!X*7?lklTmZt{_;O9ftFhnsK`95@hMtTHyy^GM*7Q0=35hKScLted zwdf#NQzlQv;U($_(C%ioYZvd#ms>7xCKMBq)w2zyiYu5hne?qKDZ-=g$?v;?c~Fwu z6HdJJr}Tuvl?uJo6i#ZL1BjDj!-?^cdx)BOu23O~iu#1OO( z3O{AUIDE>gxv3KsZ|lF-c@uyv$=%A)D-bLf$r$E9ydo2Zhsg8{K8T4XCB0CQG#0`r zB<)`uNuiizU}~Z%86#B0FIPNp9e(b5B&TXHAfdd56HoFycu*M`)NlRj#8}Hnfu4~@ z{($Cv4#jAiTtEC8x;#`!4u^pZ(eTNk#q_;(0MViJ2qvD;(&GqWPM!qa5x*`ncLeZj z>hpr4O7v#^bwjDSG%#oxa0@&V{I5vq+|`0k%QMfvuwSr9k$z#^S#a_rb{JVb z1fSnIDC&0XZYyx8r+modneMqNskQ=ALaO8rXL$F~xV;|F(dF&PHkQl|xCeMg=x*yH zY3FwkBpJ)Ai(-`c#9*$6!@ec+soGxDe0EHn(s|D!w%mSn=7nw?Oid4{gH8r$M){VQ zP48a$5vA-_=A+Y|dN(XXBso9!t_~JXVF)mKF)EsVT0(lso%|8F#V1f=o9ll9ADZ9d zoyHHP6_}TN0LaI&-`SoZ&s))2xw1ADa-dmcm~TTBa{OfIQ!GbB8}6prkKtGTyl?!32HXXVHc@CZVu;)GI*aPrwo*d=H1}b>bvK^LRd4VsE21~hAe1v60#AQ zfc!ktcbi~PQ_0*HDqJ?aW)#qG_airW7%n7-brW!9x!2vg@v3-*pGQ}E%|?K!{XIsA zf3)&>iF*rOVWyeX)(ht~y;dlxS)!DC^x5^x!W@oB+QLpT-ClhmqxU2~?CA(mIBwfF zKCALRC|iiIe^9t);=s)=hcm-ci;=WcctDwOnbQQ{K9y6MvE3FT3uIHnDybF+O|k-}xI&;A#C zHpNey0tAvYD0*1hukf=5nJSxcm>zser>D9p1fekEUg6*Q|qS+VSHZ~uqn`dfy$Ol4h}10GDIbkK{lxH>7xHYuqq$DCMN zK8k)dMaIQX)kmR)HU>PI?h*2rZb!8=1JH8!!G}&6Uu#sAD}J&O%nx%nZJes@1CQsn z2F|LE@=v9YDi&}#fe_WHMgd3fkvqfhvlw(!l`;*eyFJaHg}umS5}N9X@EyfC*USOd zZosc+wOD-lfNH>OG*6S?Km4s0v!mftK9`p3*^BEv<3Y~0A>V&dhJUh^umB0kaZ{we zZ+m`+V@%mVF{wRN_VLeZf;GoSX!sHI??3+ecDXa(ZM_0-toLN&1@Ok6UP+&bJ+mP+ z25U1Q+Ann_eW03Wx%*Yw%V?CM5)qlb6wwCeIWFg2ChUv+vPxZNLsC(@ST5y~kZ8~w4MWEb+ z&1`e6XUf3A7dpC08xE7!^B|Ic86xKfbChqA+ed!EvG@=Z8iAc8conx|Gk6q<_0$lZ z?~@bom&t$0C^dqQfZ3i4--vckRHop;^s|Y!?Jh8&Io1d%Lk&yYpIElAJp`_d`BY_i zz}K~B${?iN8qV&|oi_^w&I`6H!-CDKW|7y0O628^lK@j)&7x`emZmo!{rl^2MqwF7 zuHRQ_nd%bd`or8_UCF=Hy{fD1T8Xvv=(%6Zs1Ilxxea|2oUV}5xN z*Eb~z2K#Gj+u+O}xzQ}r#2}`SW;CkxCLv-H9=&bwf|@(Y&UH%yO)SYltLc0#bZ7p~ zy*E^#+%)pjzpG>i;lv&GksxJ$?;6ZVyP0FNt(QYiCH=ErN_0Q0uL>T?WNp?5E@F^y z?TLs^i%wKk`1q@Sh;f=5J`CfHlU`($noMX`fWyrpZ@g3Xi&lkc+ZLnbN;r6{^RB=L z!Z0yBJKAb&-@~y8r^NcTY(?l$d@`4o6sqUFmWY8<+PJB6l-zQPj=OK~bplS$vaqm? zPE+*eji`8G&07q5!Y)eYsW(Lq3eniRhBEaGpE4u7H8|26dT)x-UP&*A*Avdq*S?jJ zUdnd>nKY$UB2~9Cjb=fu!2-`eCf*Gy&gkZ%5uVsDGD!}0M7n^L{64cjJy0SFOSZ`` zW6<=Dekg!)5^@A(eGyha9b%-Uo{M3YAPT^0qMU)c`SWpy4n_4^pNFxJk*dS=qZyqZZhdD|n)7$xk%%+V#D2>Xq8`}@roVKoV*!Z;#k8caVVyzVD+cqi8E zpgU3HgOeJyd2s&co0oiXJTYMhAs` zh9&KvmIvL9n9C%Cv`Y2oLWzFZ9!Ywr$rnjmw2o889hpP5gg}BVzIqVE3UM*x3K7Qn z@1M+#c?W-zzbogxrvgb$fu*%e3{f<4iy20X01$3wR=#YEma}^|4IfQ;n_GCtm@^=T zDwj3sg|Ar~NYR5{mwRV4!}vPK`m44xkqs{@P!z{MWy#6XCjP5in$#^i%D__e)Y*<@ zenc!dml3tHTgo3DOq8IJLT0$h#n=AngFCAn^b6CuX|p&<%8`Q~-0IyX;}zbIJ2*;o zP$HXo$VB&c=Og-WpXZ6D-aPs5p*KYGg&Ys?W+pxl!2)v`BvrdreH?LEEj$mrYvP8stm#Vfj4Ci@C@EAy{bCl~t{0yB`LMbZI~hyyIU)fX3u|<*{@t@h^#KQ*&jv5==nf__Lo7 z#u=-RSp^ek)^hZn2Q2UWap7kmGWB@pnj6qZNTEFcNWO5QXj?9Lg8Tt`lo^YF{vz}r zlgy`mRO#&(i@G-34!%x2@E~iJedJ`!d}Z3qHgNT_zJ`GVeirc$8&q`q6F!8sczBhQ zH$7IfHp>Mp->JANtkc%ThX)^92Hbf*5Zb&JN0YnVly`}+t&5dc8o}_X(JmvR)lINM zt0LN~LV{r4{ag<|23|~zV7SSex_mE%12}isc4@frpcVJT&~xPd&oS=4Vi5i{cIJ9nL8Ul#TEp;f1o5**IkR+s0EDzTz$`=-{meQZ@6)<1XYPK)T#qQ`BM zAIQGG$=^1Lqf{K%G?eWncq$sI+j3*eg)>O_TWh<;c1 zK(6x7P5sNJUIDHyq5ca{s#QCxVH#B4TC!{AhdaNnKFVFnZK}L;)P4GM2df!Oiu5Sz zczR8rnZxD_)~A=WLr6i!jsBQW;`#imxM;}4z1NvA$1K=5 z$CzC_DTeet-<2Hq<2gQYq-k)s(QmffC}i&T_r88-d?^k25M`vLt9<-bQ2I}5!2d3bY@zwa-g%R`l;SJr z#=0Lk+Y&eD;(k*Se%*N1^L|PWdzZ;bOM3Wi}yA~i8~?B z79QJlSi+w)W%l>{@mz`b*on|>SHnXkRst(1e_Q~E3Fp~oCZ}RS%eZ!=Xw%Sk&9!C) zWg~g%SB0t9S-S-sSa$Mf-rJ@`PoZFcn2rRJr%rF?LHBunkW9w9?THV~MNbWb+&OV) zH)Jueqq867BK~NRt(+g`?y9jpQFz*vk@xQc>z%Q?QkWA-E?)XJBt>$0Pq<~_C)PDX3bO;e%D9JeK~^m zr&}#=&%a_``ksoN=?$OVyZ~s$&jjY&hYChWW9JozhB<$;m2;HdN+sQv@89vm3wHLO zU4_u#&P43MR2M+I?l9);Bs5%PuYsUzU$Czz@6tI{SK8?gCF&$WC-M~TC4}4yTbh6O zx4sq#wGcR~JQ_0#gCBf=%t^hLl@hj&{X=Obvj{!+gF1zi?*a-RAT>zWm#Hqt%R+}Rm z^XxI3NQN{Qc=gjuooc_EMrfQ;!fey7$c%l9dhPSB zvjx~OLf=7af|?;bQB3RiReHKEvw_pG05X zR}FtX01quCSv4Ys4Zc8pt{NwI$u2$v3HUJaND%}{w0k>W#d-ONMq4YV_X()8jEYjs zd=eFO0`+s8;{u3pT)6;rHoi2Sf5FV>*+I|KTduFovi=DXE+y2lXWPO*O;1c~bBX*I z*8Uc|!q;vTO31cYZ%n+RZSFd}WST_r#( z_R+2L;p6wWFMt&H)vM&g13{v`7r<4#of7`WA(U7`Uiq9h4b>e_8T$;x$M_fvwIJ_9epy^sv6I=5^<*C`y}wIE6vUNEQ6G# zI!6Ivkxgd{$CwoLo<#Lcd$i~UKwUz#Mxf%j4pj+SbRo<0{_m$V4SK1J+C%n4J@N6C2hGGK=(Qh@oEb|4 zl}Fw#yk>1 z;cRtM%!KbzUe$U2nR@)qrtUywaA7h9aXL@5b zAIEnufXc5=hHDS{LOQ&WGm^87AHwGmQ0m#c{5w`jY&#LXp-vqt=<_S#3di-IuoIgLQ!{Hb6?Hw!7n0;HoKs<k_}? z(!kA%4SP>yKfBt5t-U7|-tJ6XQ5$s#{Up9|yR`b>8|P)w<(vdk>x+}I+7M^5e-(y^ z@62tq?NGv~+^iF`@Hroq_fJKySw?P(Lw*xLFz!nBBtKXFo_wd7)AIWVMes_u^#zxG z)obHUtVu?pYe-B_p%UW=T?h1KiyG?FM%4JVK&NAgQ|j1YOD7`YxCSo}Sa2_7H; zA3WOIFH}VID;*Tx$nuoWlK}HH6J%pKwvpAmp;gDGo@<>#0*UEgLBYJsS^S_S0)3f)0LiDcQogqyf$sHKlL;1aTA*Qp1hX z8JWoBG07x1RQT;Xa!q!H%CV&Q5Qp#NBdi&<(Q5eF{60D~UQ z)mtH}pbu(gtOWP+QaO_h$c6062M>{OUzD}0M!iLvmqkylV%UF##<(a<&}};WH!tj* zhdPKR(2<)LWqkrV6p=qdeSwENb{~b2xJK!RwLiYc94fRR&J~FN&LaG_PY#nV0ChGS zTVhe-kFP`68x1&CT!(XB|5G_`=x+-YQ+OBHh+KJhxd8T=tq610g&&SI(q2!!t7=k8 zvLz;vVjs<@47w>8^6G$;Jb99gT7GaPJ=oDCy>3+({P6NmUfRu2qC#TfQn0h~?Q!?? zu^$w!rJk9;u3GT~l$=j-d(m!Ap)s5?@1m`LZpPk{vaPY|KRLhD$c}g+(_0yPDl>Qi zWZp%h&(j7D*4hX*HH(ww39ml&|D9W;r`%%+LeQ`!)@#jovC4Yi<12m3mFQK^~jLz@WWKYmAy*AZLFMCz{~vDNdY;LdL^U_0$0*IdH>`At3S z;vv4;>l)qJ#}eqJ#9CphbUL-r0?E|%q4(P2NS?x>|u@5r^*4Ji{>*yEHx{rZ;+ zE#?l!@^LPzOoBfy$$r94@^{6Ak4mUC-#=WJ8jIidJ69Ofi_mbTY~xtDG=egP39cJH z`cz|LGQLo1=^rMDp7#oegfFvS03P9o)@N`1I;wb!-r&~5i^7^hOfG=;_UAPhz=Zp* zm`mcafWJIV!)Ni}lU>#O3xTJlXBc^AY%aq80wDZ}q0lyJX)di4rVcn<{MyDW`mq7$ z*tMU38|r*3jJ&#SH)B54g#mBW z=G1Te8cztC9A)8epp&W{K8^xGrsL2vh99_timRy8;p30~{&}c;;)n>?j$#?(j+uY& zz%+5GBf{_0{~sw`IZRZveotMiYd#8G2W!W;Vdg)${v~zIa`SX<{&(ITam0ox`|b5^ z?&Ytuq?GXaFFWA#Py1qb!xygB63FUbp#M&I${rgidTgj=iX7oee%c=<4A^jz!PRa& zeCf|jh|A&c4}2^}^84jFdV@M^xi4@1{_^Q5{e9n7fLt6KBECfU+sDp|4~1yw+3BJQ z+2(8h?*5!h5`wWje zs9d|8wqoTa9uv1e2PRXqggn>G6QDg9P$qu%Ww_KS5X)zX@0;F4*{B1fH z<{(&mwrt#`4^M{gS0xvp%XK(QA;|`|*xl4gTC_5!a!7%l^ug z+wW8Y7Y&Nmy+n*M#&!O!+TE`?=8femv%kkhaLy^ZCFUWMJZVh{gU4@sa!LHs@1lO5 zE`Ob!uyw67o3yj}BHwr$r5raCt?1K-bhKL2)#yQ;s-%8V^lH|00+RG>xz`FFqtZjc*0~DT-?jA zB~o7^8Q$h5!i^g?;3MhRIRyUYaUZVfr}SB&%J>~sVv9Sb-TA3H|!$`sW1xc#~d zaWXJ(IwK2?e?@e9Qb-paF@V8WpX95)9OdKo_KN8Np_h{vqi1kB=)jJt0sIS;n5+$U zhTZ`bec)jTcT$lMR8~qqsju{Q#P!>;JaE(KWJV!+IYM^0nqmsc(DX_!zXPWV!g`g{t4H$CIaq6e=byJhy(`;}5x-&Q3XBjpcQ z-9;L>R{O*5n(CH)2-F!8^KWW<>6VYW_P!Dj>K8?+rwq%iHZn!t@%xrK9r?n zY2O}K+HWNJNcFPc2UGn7&5^Vr5_bvROd6qF^5)m+-DEQc>;2Eo%>g_`q zareZ|?gCi-SAlz{ZN907uVwE!vgr zpVefPiVdNyx7Z7DlqoE9?#|KuaYv=-DgQyaTwSBWQkG?yuZukq)}LgZD=8fY4!*lx zgWNNzexpTq`kSHYn*y=$pjF9vKRMvEf zoFe+gm)(i*5KcGY?7o)cC}_1vj_$(SZLmw<&$B&(e+oCbhDsTZgLz=c9p0HLd(|^b z^3+=FW-jH3$MMqX%iN)|u6y%*&o6}Z9Et)&(*%O?IFV6Jvk9bdY_~?q#MN)PQ=;CRZR(OLAuVwgrf+|;H_#&Ek zRh2*@`)@K~frEkE-~(rz_DyV->kP|>9*O32;@Wa|P{&;1r->Lb4xd*imetMWEhA=2 z!x_k#Q(@95QsO*K$z7~s;qN=s!HVCmUtFvVEN_oze5e1mEDw>|OaoIlSaO=3ULz`! z=&6Zj_@bik4})r_I;@w9OsZ8`8YgVyoQ2*XdjA^yR^xlH<@GDMa6XLk9!QW_+@l3H zLM5U1OTOHf3Y^H`N>p*)$KWeoljx2LE`JZgwJWg4r;f|jktT-o8zr`ZdzntAW^$aj z6QhS(9ClXDSls8qhzElDLp2rDzrSwny1)zSa{|?V`Q0+6SiK_t*FJHMQAIvP<49vS z=pJ@*JJzGOeY&RhW4M5^J|C7L1@yPOm6H+8M-gpr5~4u%<{xL?#AKb22aVuFkI8x6 zJCiYS6P^!(fX-`E9C(wq>)H4CD%T~*DsL%MOpb5oRv`4M>O3Os-oTyWrlWAYp;TwP zO!mu-8B-A2wpKn-2<4a3wQ={J;{CkHR0_o~x}!MaR40_~%*218pTp(eEYE1!+dWb7 ze4*b>@o^f1_?tE_-ssg?2r%1M&sB+^v4IyVaOc5BL~NO}|2&l4{@0TA#N6+yi5Wfp z7xA}~+5aJc_O6t_?{Ba_mD)hnh;P&^h)-55{GR3Bf!ucgJoTl!fH3%z7jN(};y5d% zQFbzav5OJ-`^Y3iq$;`^*MqE7{Ya63R!SQfx}ulsN67UnOX3WInGprw$zU$KOT6=N z)N0Ow{fK#ND=?^Is>vY7cQ++jNBIjB6y2v<Rh;@PuUe$a~1zX4_8(h{Q>;b{)58wp@}(nu%}2lX;k}0;^>}hSiY*v2 zJhldFQ!c&F0yopKdJycbKU|~gy8N*!66V!##m@WKB8K^x(MIKY5C?uXXDB&4U-sUU z{xUgAGy!&Lm~&<5y$_?ppNHaJCaDU`ksS=7t_w7mg#h^S#~AOoyl~RvwIh739NGgb zbji{X8=)0^GL#mJdjbQNvtBM_7shx;%gJrptC2bjQE#*VBN3{{TwKJPoTBUQb7acQ zsB&w)BcDr&oIvqwSa&QM>{YRox~&GzrT_12q9iDoq^1yf9!!n`dGQ###R=%^{>89- zav!=5xwu1-w%GL0v-;AUtV}YFRpBb9h*}rlLI3fZomKwNG=e2_SN`A%g1nYm8{A3v zZ;ytMZ^L(4o77C6gSyOL6<%_@Ad!QRJu?{??|&=Z;U8`%ha~Oqh3*iyH=p0+QCn~T zjtF{xh~>)r|D$~2h5EnboY|6L`?)?ga%Vvmqp*0@y-OEBE#_1-%q-bbz1r!YY7$$& zpsUor$~6*%WPj?-;4Po-(Qh=fzI0_?ignNbU#a8kjGj_sRhV^XW5iji?y98moFieX z;S@>+<`QGf_r^%_RDbnhbO_5Yk3?qbvknu9YX`&{3@Kw~Y?qV$ZFqU|Fg_f6{%o2v08jrW!Ez=H^-`OFo@^=a)JsjwIc4jdS;qxB_RloPg zkrUv<|A47a5k+RLXI@{#rk>X{>?w$LMXvR)OTdal+9jWEQ`_Mph2`a+;cMf1#cpZw>78 zZskSw6|ern8&>l%OZO-z%~( z^Of;7huOq2^x2K8n79*<&7l3UQ!_g>T6|tSg=ki}f?)DgpjYQzGzx_+#DAmNi=wj) z*e{u8POaxqvij;h{W`J^;9e<{pwu?fmXZEgyP|Twu3ThA(PD4E_NeLsHiMrJ;YCaC ztS*zr8kfGHoL)MI9ho(l%5`&}?C2fI39v9xos2-Ne14+zTo4C1HmN8!b`E|KxVA9mBYHWC;iQwl3QrH|bHfH9!2$A)(4&nP2lU zx<3^6xBt#MgAgUt#RLW^7XnLf|lw?H^DgenWG(c~(J23yd57Z>L!Vm3QcE)BzE zNJruCliMfN4OqO5APc?5w=%-D9Ep%HkY5r z%dF0URBp8q(O4F@EK5`SDO;NyT}yWQoi7TK{!}5jrB>ULm69_40)qvtmW9{Bb?PtL zYnUh{hh2S|tXFl<2f0}iXm=q{4OfeiBlE>2ejLcQ4dme(idHf zwi4s0Us<;C=W?^!tFI~iMbu!Aj2WN)60s9|-rX_o5JZAw9&wJ3Gr7 zOjole#1e=6FDg3+C6Uy)lFoxMq$u~E5akQt`uROl3;zW$5CgA!a{(+-l#pxkP2?bd z>j%1HZWlTnPFPeur?r$iN?BV7j}s^4Z|s|BzIYY+-v>?x4fTmbvyc8NK7Fg-K!~8| z#toPel6J=4d=3A;<+r-bGNW6~mXuuoBpFv6#D79>8ek=j2FnYLFDV%=>i*F7L#*G3 z5^Wd4nIH>MVXAoq`|Lq2?ie{LFW-U1mcgUwor(?;1&d8}oY^0%qJ%F_r7OISyQNVy z+M->@M(+6ccYb~R$&@7zinjGQcyTUxGhf6c&HH;m-N%Y>LMghpztu8sV;ltGVSRCQhkpI)RR<&z`hx-0pNe)#e{J^btBx z`qtS6PK*XM98`?i9|@|14<8M9NlD z1%Peg91%EuHb~uidAD4(AATr4seSmG3}!AD0JqIiv~}gT;quM>qy42M!$((T6Pz;I z6ekildS*_U;5*}oWqWB{%aSqsUCT`_>Ya}d<-WkOEmzeX^lu(Nj0(bGFtzS?AL3ip zXs>;TRdSE^Ro;*pQgXWL`H%uvc}5Vkx`NwUq1LtyhW0f%9KHH#Hbl`M+z7nf!S$z)`TTHp-PA2XtdzS~q-(H~+1OO`np%uE)(0lDf~g+c6s{nRv?zYtaenJJb59>r zHOxOWbXnNxA;R^}_gEE2$!@88_i2E|A4kU7ryg*)}`1;_6{`u%~9VkS{So{v5fXRl#-Q~m{!$u?2=eTOsm zK7QZ=I9b2Us!Ap*PN<1@3*m27pI!isV60JnJl}g&L^r~J~OsG33>Hdh~?`Ee#h(obi;nwl3a&cPv)++a;2- z#u56y)-85N8FM4+`zjo_Q9%CBI$~1mOIFue$sNycA^wX^G^~&Ad%RW%Ma&7ae08eQ z7m@Htl?0sbW%5|W6_ci*wU&{m!bg-#8osV2XX+!O{fDx#+nLwin)u#Ld?2L3>%9yS zDh&CJL1D=G-nR>YE#xs-@PlM<_Syb<=!+E@6k5;z zI9pfxcwHf3`rk>+Qopx%pg+Ivo!zFZ&Ves7p9`e^-0Rbo(Nb^at+^8ypj^NBeqDl2 z6;BE(uSEB3az(W0b@ZbgWVm(PzTzVYX~wC~By(=G~2n7(y?@2TrJUm=EpQ znzEO|kXxINWK@9?YDqXpeqV-PyjUeFO+Q^`)QC+dndv7=!2Ju^Z>)`&-reie9Rr4#TMMtpOOijOk{zxbjgr&}WU7!( zH!)>rXH$-6{}926SE-@4{??Bimpcw`FTWNIXEr1?kctbsIZAI`0OT*a%uINrinh9K zSZ*(wH$|R|&>1NiCx4J)DiS#*h1Fbn*^|pCTt-(ZME+cujn)yTEWBut_^Q)Hl!X}! z%n#7Gnsk^(T=MSv{Ggdi$X89n)Wq^_eWW(eD*rwjpv^n{e4iCKHH%t$nqj80jQkR9 z`KCG2OkNpSA?RIk8YT)+mRRwdM9KB4dM?YMMI0;GZio#JL#;n~+78q-Yj;@ZawTTG zl8M|@&dCr_OQY=UZ~p50{-t9)7(6%hG>-%efbMf!XyU@Tve z)qdEi{}*3NvGlasuyfUG(QCxpv`J0z- zT@=OT9^{O|Sibd)#w$ugs<(Fxd%j=M#=ydE@7`-wy>hS}OD0o8V!yo`%w!5t(ozmY zo^Z)z^`-gvld1*irbW^EHUoPWe@9~zz;o;6{-Z8aUB)0#bi@&Mp2G35SJ@y6l+@*{ zw^#6)g!xj@0DWd+TO6}PIc)sXs_jL&f~VlW7hZ~oE6SnZTa7=K8;4=$A?XVuo{IAMldcV@LSBdg*}YnX!_DCzZW;WM3m2~0=U!N4J0s6_l_+5Re5 z@P|x}tS^#SBSpq@MoE<0_#R8k8)Q{Y(v^p+-dm0D>1cb}bDR9JU^KX5#a0{-T{hd`Oz`(E*5gNq3l$%IVkxsf1HvIi@w@h73#|K7zx4L-Fx6@&Z_l(s{ zInQ-&x5~U;FZ!gM%WGu=*|)SGvqQbz7ymhz7+}XeJZt#BmGqTyQ9bY5DYjN2N@;eepe3AMeSKMgseJ|=7?;k#? z*KG<_vGg{z&ilA9OlpZT+aiYuWP5-9ym~3D=qnS|T^~gm?$(=Q9mf_a_aD~Mdcpqq zOjqG?Oed=-H)|MdyxCqr(MS=EtfpDk4JjJLo2p!lTXuN5R)`hnMp2jFj0!T*a?4T# z-|4%kETkwQ>^&iwYR}E-E;n%i^dFKAMgu%f`4GkZld5)3@BOu+hHyDzIQoiFn+OIIBqD9zAq%_5NIzL|w4} z?Xh4@eZI`^#w^B-R)}>LU)DI$nGD`G)8@0puc}pQpiv`g)B;?s9MUs;WpuvSKE0E8yK|m0Rx~5rXP}B|qW%Xmzd5y>=NF!+Dr%Qy0v@l_XIYzD zU{|I0FqdpU@nl*<M*S{$_mkBr%$1UsGo4U)gy-EcJcT5` z|BJ%QJ0Z7Jx*A>uc6Qq&mw3dFMwdzPFC`jYntVjmmMJd#x5n2ydu@fvB#N3{D&|h= zcS&lYPDTan$cAI1m=!(W^^{%1r}yu0W?ogY4P}v#_x=9dE3Fa%*`6?oFQ}C}U&^nD zcrXzShzN=K95{qzNeJ1y4hTvim(?_s<(1rPInm>x!81||O~VUL+eGQf88Lz5gzZlqG?d+L(u^P(c!z7Abf{H8YiDB}lalO6UDTjs?hrPEml9rCz-g8M^(2daYxd>UM ziyC`t*R({cAl3g@z<1P}wi(L&PYR4#%I1VDXz@Q-ad6-!`dnZ9jQ`Gfcu zB4TAEbSv*FNwBZE5bB0MrOGQTryJ}>##r?sA1 z9Y7;CriOjFL*VXwGyW3>UQo=r;iNL0hg$D$(IC^H>7avyuWHM*;RnTvHGy(_iwv>5 zCFY8*ZLT&u@2XT?ns~Uop@*WZ(eP@7x890!RlC9`5g~y;DwWE^vR_UmSe@xE^CC8K zLuRc%5vnMm%e^$aoNtao;6x=Ho#D-pkNa?KrMFbMe&y~rNpEn4f0Z2JfgK;I+N;`G z6DREBgDJKZFmo@nQ+U$#lXr`EA?&MFGm+D8ez_JTM%~#@b~Q~&&h`KD$4`>e)0#c| z*u1Fw!}d}wNoabCwrmHJj8r?PT5~crN0y*z-|Ho6wkj@PT6P}mU?-oD*$C6C%wEDM zmGNzpY}UBSP$~3o9s1#{d;T`YTstME;hRE%yzlNv($9!C(5{Bn?nvDiJZ<;{-1ftS zX36@)RE>Sf>dCLBEXn@KSOTB_BJK^d37wzVXz)7@Xq6<3b*9GGk$ear@TDJZN*h#o z!7l6Q@Fh{!sN@|tC`$I!T+b(=Yn+cMV{)+i?~=_w&^Z2X`62K#>D{RDKx_0b7ZG;e zlo30~ipr48kcfSFk z9v`$)WJCPHRqmW;A?oiBaYm?|t8m%1Vn_H%!y7?}Z{x3%6o6{`@WRmR`FD6JN zU2n=dt>xkI-^|s_bC&A*{wqSx`@~*+#x3f^WkhFQfCfWRkniPB$A#V<@nWc%d00;! znnR)iWt()F!m=J#Zqbpp8!1c|`o3^ALY04mfZj*bnj+1OS*D+c$}4cYzM_UNb~AwI z{a!suzGBsaeR|tn*7JOMU+Xc=nW6Z2!}zZ@4+jd~ORAf^P8Nfe!N#>Siv#-$-^MD2 z5GDefrkAM0XWqjO4CFm!6M)mQSB}y z$jnJ`e8=W@=gBz~wV;#22#(?W0e6DmV>W@*6nO_a+?&i*uGY!bzE|0_K_4~Ej z8-47P3$%zm>%vEHTP$4GaiJu6ZXWqlGRDK<@8l3U;YYWaGnW#f|P}mFmbP* zku@whycybVMCjMIL>=mjhxM17->*&+I|3bEY*lC17_xRzd~iSxE0e6(2G7uF?6z6Q z3~4q)SNe5wDFhUp>u$D+E#d`OlLk2Atj%(7t#d4X!WSwzlYpaKSZzKDBW~C&RFUD*i^2ozG^llQowHaZL36cia8TKjMGy- zaVy>o2`aAh6K&_3q;V3b=* z$bX>Pk^o0l5mbk~@5rg)C-H^_t#J+m*Ae+>Cj#nn*AMAlgwya?Lz{-=JA0-4HZ`r4 zSEojwd;dIDm;QO0oS&H^c>Tz}?Jo!?(8hF8`4TXLAwdkmmB;m5-^wR0fv$^PkP5IE zMQQ_$us=d+Ato8>iBtlr8&oi|pbaWH6C=68n;wzN9De~U>c-2vXgN^RUN$rZG%d7 zyHBz|lzloi#jc;j^~ENCNzsg*2J6m(K2F7rTgt}$(00N?$uBB&(x7rvK5bKvN#+va z|8)_l3cT8Mu%3aHN;XIWeV_5KtCiLMmr@$lUB&=5Fo$J=Y{~ecv3Jfy;8)XspqB(a z-_l60YjlMD*KVF6R<-rW8t|q=d*>x2B#P8EN^Txb`|3wuf_WNGlFVh1vf#S&vTTLk zyLTD*==(;3BnwC~7eonp-}|v7IFvrNPhK3xRv0y~4_?a;ZyTN~c?G@ojgR+A{JEQ3 zr$fA<)%GXJs2rAY5cj#kuCJjj;+@I;KH+%kFFvei0t z@cj|7^UvCL9!*9vhzy^U!oHt?ar&QEX<`->8{uJsq}*@c?I(x1ewcf_q+)t8UaIje z_rQmhqoU*hE@&hgp{yvkS1w6>$pqduP^;Q;P{*oUSygZ_`dy63fNNOyk3=+DnX5F! z=SwAH_|oy-gPMvvhH26Ss|}+@p9}*S)lIKYjRi_f?ABG!c$^go#I-*&ZF8b5Muo&j zeDu5IVxR~qV7ms#5neiet!yvLKL46%>Iiy7=WS*!$-iB zus3Yr&6ytRi<~_1%Sz9=ixpcP-_Ga4SB@d9j=#e5yJycdWDjktVQ1F1H-uO=pcvk^ z;-jIjK0z^D;o||e4bD-Wj@zOX&^7j!xB+I3)|$hX`|h2&PwtOCjkC>phvfIiB7bq( zeRSm(dhESyjB-|Nfd5hAK)()k-yWw#`_<|e9o%NNoN9JB6$`= zjgdg-Tq)veoMy4aoBGj9Z*u&~U$Ug|Sxg8Qe9K?=Db`{8rT5pv=ntt#-8tbHm6FF9 zI5wObKh)Dol7Qz3{Mpy~N}{D}<{|~Hb^_-w3j-R+!PwYAxJD*}7ZE~8W-rIMYqpu3 z{UydXy!Q&xuov4YTxAtF1*2AEC?BO}_8{Knv?v z!zd>N#glHTr9fN5&RFAe>+S?-xsLa4wZy&hW}ib&gYo9%d&V**6E z#ZQ2nY|8%&g}#=;f8fpW^O@-LIulPNIF|ny9hq)hieLvjaV$n}npGBIA*i90;y}$l zIGs`dt!XDkgKI$A*Uz2b6B#}i4PhJ&eA^R3t5i^@5ghlsX+i;rF)9u1W`dR|vw$i+ zOz4w-*m@tjq&#h~`sHgDuUJBwqf6`&JBVqkbmp5shp2BGIsro$J_x>d84@Ns6flQp zobljfFtlpJe98Xq^5ycv#H&Mv`+wsUyCfJtZ)A@mh#Zh0^$rwn?=s>3Y zXWuyEY1Yd+fT|Q_7XAZF3w9ntjR8zq8MF_ZtB_TQ4cCcd7KGxB>KktsF>BAIg52B| zWyW7N6{|XiHx@Socv1|8I#6fp(|78`@cZblf|V6lJVje$lZAU-X@okr;?!_}#z1gu zMvT69l-&F-_mxXlr6dns>PGAqDU;Sl6sjG#jQZ$yp0hjH-C;Z90*sqG0clEm)zInNt2=GB4fKcG74Pz*|%>w6n^gMMl%QJ5TX+BjkK-q zd5D+9BN1P%;i55E(KAH}aL+UU-R|s#{Bf{o9rV9t9>&I1z5m|73uFOm!o3So+xi+gJOa@4~eb z4G}{DL(r%}q>@Uh!_>8zHZgbI*m^jW*-HAu3|3*4Opz z3ggJm+XaJf;YSB^9^k=+tLvI5lQL-~!wtK5Ld4=TCiO z9QSR_0>?N1fsO#p0nyGGEbgs>`^GLhb6eMp*XJ4@Dm^{k%JTc~o~PiwXtpYnUtt!p zQsJ{NC2JSjLl7U);LI>EhBAD}zo&(_d25*kL9erEUud;FR!9H-n*!r(*|!9=~ks z5RyVuYTD?Jtf#;z9MPhv^uaZfI74?!MKavc;CcTe33uc#V_#6ve)?rCiLBK1DVDBr ztEX?A2A%VLjq+@MVE-K~{-F}LaaCa6My$-qtl^x>Z&LESUnoSj=BlDh-K)5Pf1s~? zN494=`g2m`o@Alks4q$MUHvK{(5jz`140r{`+toP2{lKA{r9&Zi^sI8CEi`W!779! zqaZ)1balBad<;u-#&84-Ix#6)r*6$6l%wH{{y1}_A zdP-#yC9#P((^+3E@6DG%i4NhYk!uW7ownfEW^y5NXx+vdH`ghRYIMD)0F}go@zsyf z<~QF+L@KZ|tH>@+q!fmv0_}MvjZ5%5wpB%~)_&NcW`BR$#sN*r3Xy-RjWJs?$@ePfm+hX;;T? zG>~DbgM1U;;AghWZ!mq+_^EucY3!ZC{WXrWmIQBHx~FH^5RI%;+zwnVnH2i`v*L`f zCEUl$hG5D1FF;sPZ|MOV>wZ9mQ)Ac6aZQ=JLuu-+seS$m?Qq@VIwP!42J8e}T)~Z8 z!v$OQDWP@zk)Bd1v_GNbTD>15cQPoy3*DE}2BC zzR7Vm!clMk50pLKzmB#o{|Dlz%Tb~a<;SIiH(^-k$>xejBuWFKuiNgn zOnuXgsHCx5n4m|pd>ePne-W|vyThycvP2hkT)56|YP92q{;|}S?On9em=znr4{}+q zSm@dtv$Q2y)=v%=yPxyJ+>SUFJb!lmrS2EtM z@B2|-Y6|sxz49ce6-$f3la3c-gU@_Jbluy&H59IxzJ(ZbaS_g@Ak=(l!Fi%3?!x&Jc^D*prjmUXwj@o8SWojKo~m>|#Z z>*z;$I}8%9LZ#734{VkT8c>fLH1q;Te=&_*KOh_Y@i%m|@IpZiPezLYsbQXImIrq9 zGh7EFBK?Hw8aky1Ew}aC1b@Ykf!0}w!@ekUdobokh4b!@hV^00fi6 z`RehRudCVhWbdte0(7Y`N*QmPM8XMqmQ>tqNVJ@XVU-N~;FE3!r#{?v7OV`h|Jr{NQIB4)3 z=xyZs1FUqp+pR^1uDqU&DWT@Qc!|f~J5kZUH99)px`ORJflGAHV_QIH-1=Qte<17U zh7F(D!zJpNn#kB?M+W}CRUh>hrX*Tr-uSQP+LarP-VkTs6sKzV2wj$)UZvx*o+wG% zhVr0bN2i5>^7>JDUE$_qef5S`iv@ARC(#a_hAnq!Ncf0ohrBmmfxqHD!QS*N#VUpm zv4OYd`)i!lKi5W<*z{GhiTneNrX+S2?<|no{Ic4!AGV${{!7jTZU!6$Vt-zF;1I`3 zJSy8ilY*gpO>r1GU12-Z^Nh5Bo6&3UX-_HC9Yvwr2e{g9Zmc*OhLK%FM{h|-^PmEv zO4=H=E-W_UHO&2#43|!-{{mPb!?e^*C596}!u}A~40Ew%56l-<+8cn8T+~2L9Ht7t zOUR9KOFncp`50*k@hSO85TRoC^Fe;{whP)0?(q-gigTR>LtzUceM*X-HW64sHjzV} zmTz*e$3MU}*_+@?vV?Tb62n8AlX@y2ozApRSP=xkI{X|yV99Z`8B~nk>lGjI+(`1+ zSsX7{ND|z?R)6uH+Xo^(T(xtTr&4W%Sh+Ur?QGQC0$SP0Xm6><8wM3!w7RlEzdRe) zL(L~DFug8tk)z)+4|sU{xE*q7?y@FxOvNZ6BwziJ2{xPbo!>P9D4P+0zC?c+x%se_ zeXA>#+%E zL&se`ML$5PA~%GQkz1&Mc(W@-=6|3;_(`05m?v++uLr3+nF+`bRQ=p34yhv>&4JEX zdfzLJvw&V3=l*c9Gxi+zm=bgpBu&e=Yjw)3 zZO%-_Uz89N(QEEmUF9MIPku01<2R>$iu=ij+G4!Dj6XUzz;()pjtwTGlC)91Hpf&!1HU(G9#>;Wh$Lo&B&yy{H zGU8`?*)K=W@M1bd)Ag~MA4U}$27H5J`y#|WTaB!!wMkFn#aJD$XKm>}U;HiD_GG_= zx$WqyU2x#ZJw1g&#nDi?q2EMvB8EGJf+hXWqQdm%uqmY>asB%5v!2B7j+2*_Dd z>v#Duj()SB;Mm>Qi-A{#j_qc@d?>2bxgG6y#p7?>2G-B4UIO2bqqP+!-7h1hXvj?f zJ!-DwCC&A-r|sP(Y59$;2_44(Cse`k6%?>7R$@*ZHJqZnv_)v`hVLKW{%e!%v6b)aX=pnf8ck!_-41dz#`t zNYyPFYobTDexXyWzs?IwW!Gfsb3MMVmH3fsAjpNDfUs%9E)QArxOR>lQ2;)(rqtLH zrrsou|It4el4J(uCW(EgW2&lIK?BBJxb1nOd4M5H90W)<^}^TqsOF#HE4Hm*?6Y@D z6lxo(z{*E!GNT%CHCLxiL0jzLnZZ`i)YH7xhH(Ub7||4fecCg`uK>*Qd)HVVylKW2 zY!P74Vt7M)@1Fi|UdXwh&X_(vv8u>12W!JNiV&@zzNai&ZLP;)r8a)r+znF#wnVxb z##M_WlKIel7qpNds4XcFSyvOPh|qU=g=$Q80*K_jR_r6&#U*Vh!U;c#@yz~E`UxO92`V^`4y~4- zTplTfE)SP8RtwdrbR!QmvG=d>VEohIn_$iJuDVBOdq=ya_-Q~xYYhI-O*`*V-ZCNV zH)?J&LtO2i2Vv_Q5O4}56gu(`wZ)U-ja}VY+H{* z44-%0JUv<63vu)eMg2ktTy>(TqhPMb&fBoqCiGiTDMh`LEBA*7j*_Cp12k7BnwL92#Hp^sbP%%RW`a00}lTVzONafAcT<%4ETP#n^z(&;VL(wX+aU~;~rED zhfs+@R=T{?qiwaZ7O0_W6gQreBl|}b7sVW zHb;D=1GsqL%~vp&pl{F0OJJTb_Zth0qu!cx>XknR;WD%?k(Z|tc=Pk>9U36Lk&$d` z#$aK%bX?~<*)?DX(S*wxTcs^i7)@zqInOIE?}9S+1mm8sArJPBb+_2$2RP1*#usbP zP2MF>9@V-NYALh7#fOT+b|ADDHS1`8l4F%({OH=_v!;AbG)FO3Yx>d(@{rQgI7{;H zV@>&*Aq+I+Y1>U~fHc4qhJ#yR$0?%6e%qcD=rn5bo~XTvqtP$k$f~fKyu>mUPMDx@ z$vY51*x?_~7}%M4!kS@use zA}xv?8yv?!x7XRw=7zK3boddo%FREuWUJQu;an~Ctx#10AIn)ndTXadz}`)Jqh})- z{sWz`wLWxgCU5#xXQ$E(l5+x*H=g)jVLvN=gv*M+9Z!}Q!2!^qATmQ=Uo%|T4Jq_&2F+81E!PP3T1Z`6vcAjD~ExWk2+ zBA^Ofp3YYkT*i}aZX(zN?=C+_H=mj7p=x%xn3bp0gfqWa-8+9y`@Elf(O#Id>lLCVVWf1F)v1*x(FH^*}5?UN9D-(8^}5VCl!mFQiS z`P?hiI{L8}$=3BTKv#EU>%nKZN^QR)1x9#Ceycusq&X0}-z^L^CdD}}6c2*KY%U4@y^dHmiCxO`+ zi4U%(*Q1xZXMj;<&t1m?Fh}kGb)uhzfJzb%08=gNSn*P1Vkw|NO z#nE`f9)J@|_dk_iW(nDgg32`0kzOl(#U+AwgIeL;?;R%8z|Y?Bl}2mHHAQF9C}#%cs3 zy(Hp*z`;H)U)_X+Z|(U94hj8-D*(GHT5a&evedWZ=XOcUa?C^tM{SYs%HS_m=`&nw`3Z z7NK)#ti=K^JQavH2!w=maLwUd0Cw|k{<4Px|Dzrt>r?Vhdxoy6u7CHxYDpc~ZG)Ts zx6JjLLwc1%oQTS8G*k#!N>TOmo#M{rp=M}x`>ih3d6MInv?2S<-XS1I!ev1NNto%o z4tiI|imUC}D1F6`E5UMxJ}7j#k7no-F+P6wafRtbl>Q!n@}{Agm}*{pPyf^J6ebmK z;VjN2Xc(UKf2Xc1v*~bwK$gMVvDU5Xb?U+Dr9YDcjLA9;j8ON?xY2eSCzW-d_?zWT z=VJusc__SO5s%=Z5Udzq9hbWF#L~20LD8dU z(cARv@d|32i;`d>*V{WU`P$lJ=8ifvAGbf(6mA3QX)zK>O5(U! zz-=ZtAkxg@7;FCJW$g#9m_FWvqt4b}j6SM`d1_az8t>&d~2{3!LwO%{Dm65s6@L8Yi$=A$>Pa z^71&(u-iCH#ytJ7MV#O^y3@<|6(!~oei0C3f5bvy0fkmpZkALP_gyU?AJQc|WG_FG z8A(=Yk9aHA2N3)yMFVC;E3d}~sL=ue11U@3AvwN*o&*jO$JSXXtA&ft;nNgyHD6ao zIFn4bv!nuJ|K8~h4LH#p=QuOyiB4(e(!Nh-qV0E6~b5Pq z)Ob~k@;r9i9#&ARoa^;K0%o zECI&=yClV}q*eQlDW}v-$h{8lwp)sNj`y`X_&`;>6@#seUfEro?LgNiMJ^VwYU?V zejE9_P*-;X=6l2pXK|6(pc=HTIWDbJl)bfV9r9Y?>B{m4W>cSb^wiPMh3Rg zkWbc=wQe=reOD8lP&0Aw^dX*vEAHCaMd3R;pdGseKg7=gaA;zW8{*;O!7Hw0NINvx_ZsK}te%tN`82Y7g9>(Fqmpo`=g^VK3q^gtkDvj0m4BpXQh12xTfDNyXidt8vA=)`@gZ&B4PukNT%MQBWF}ydP|}a(fBJtOZ|6J zWrJN-rd{*RR$cl=9q@l3!_Mql5swom(I->lD`Q7`Iy4X-oGXHl6-bmwddyj0nlil) z=~4V6Tk*|+SGS}2@w50;G9bdDpk~OKE*q<^kZ5GGaCaxzFm)fI&Iw>}kts#-f_LfG zpfgjx%HM%^{XZy=cyLU>ByTmgC#&jpumC%pvM%q7U=WgC&+@Uk{R5gvzv;HFQB?;0wU(Piv5_BGNv9z zg$e9WedJSw_IZ&=nbF+8C@FuCe{n~b-n+>pQn}dWqD-hrPEfbW&X_!j6K={#*H&5v zgcb@c5M;2omz4Gu^^(wKv`M;GEf5ubatFPMpi<-~tP#}~hl5`DooWOQ3UkqcGXB5Y zFz+38IwKJ9P*8L#o^Z@7gOV;x7;~5hRJw{=77jc)SIF6pEX2wG4~8X1psa+5FT}3!6q4GP5-T5Q8UwEVQQ` z7!J8C2~ICY=GCOsD4&Uq|4cnJ+L~9XgEZ31P;!XNQ4bo7Zp74IM`ePZ?ivj{*UB3X#i%7`~=h8A*4dUyi z*Cg$xTGTjdm`06NyvTKQi|-~74-S`%vbgjW^|xi1YnPIudCfqlnkog;rdlTETf_4MT#ta zMb?#J97)I;=6WNawzuQ#&fP3R>B5+bT)p1PxiaAcJ-CpZAsI9Li!3Z%PONNoO1tba1mwDK)a0@_DWQ|gX}@u;&KbEQbM zxVi{)Izs!2X@5H1QHnO%%mOW=3e!GBe@H+~P}94K*``_YS&GCvt}v~l`2|t;m$ql+ zNEWRHQyz?2>w-Pu$wjGhL!#hTvq?>dxF5rF16`@*O2Vb`*uF+f)9A@ylM14vi#)p zuxuvZLiSk8(SE7X+ob~tUt=t({NJjj2VyN$1|7P31O<<-D++- z*2J0kHaT=cQcsBti#L$v+EeUyLv5ct5c}9fN>lEE!KB#t!WW zpSI~oYzyZT(^fCuUkq0RdI?D9wd6~3xXlmPqBr3TVkqUPE%NkY^rgpB7_%d76SJ(r zOzFypxAy<-5n-4!>WvdOj3hfEhsz|WWXfB5PptA44h`hT-lvVdAE>o-OfE$qhvwGBhX)U`GS&h_Kc(<>V55PwhqZDeVOAI zG!&D7oMtbQxKF}a6lz(4+flS%{vW)TDR-T5gZq&}}d&jz!(Dn+q21sH#=Sca3 zaqUnoa(3@QQdi1LCPD1+r6fP-vh-urFW_)fBk`y*5@=z?D`C(8II;bOvD(y0)qM}3 zfsMNY`v7SCKx@d<&NOHgNOfuZ5@-BX@X6FPIgJP1@$AC`>FG9$j16PoK~5gj%H&+7 zSpCMbu8hoO#rYtcz=t9OZ@pDSjWV_5#w8^Fd&%C)lm}B;EV72{z&G^;4bM5tTqGAC zZxO&S-|z{n`c3}G(@sS6J2eUb67RforX9f>mQaKj1~J#)686Wlvm}3DN9amQs*dz8~p`mnKjIo>NkY zCUyrVm}(JU!5Fvmu9ALClaKx4Na&%oU83>a3-5fvZ}pN#Q#>s!iUPg{+>SL`EZEyA z-huOEAkBt1U2-1q;C&OhplP2*t#6qqP84b6B$v8Y)JH|C$j_)`k~r<;psW~T)UXoZ z47VE|-oE>JBBoxJ)ksU(K-1F9KKHU>;ji~ps*4+I;XT#%keHd!6BIG)Pe+GLIm2J1>kSDiyNrqi4buI$ zb8Gar(05c=T46F@T4Rw9S z9C!fLw=AHwzbLl9sN^prvbUN_D(`}*8&KS{2q9BwG~!!zHC(HRl3=DebA4fT=5w1gf5b8(=dz!;YuYw_hs-V7nMbS1mEg#{#|EHRw|19fcmkA zsvK9*^K3V?Yk%>47`eNB2;q4Ww2YiF{UATpx`Kt4kY<=YG@j->AE|h0MXY>%Xdb4N zX^YO;*BdM|7jJl#*Esjt;M^=EoSvaZp5BK+L$UIiTr%QEnIhD(v?#v+*|;`YuE{`+ zG+JFp?YYuRI(N=@I9KC2_$(#8kK%uROjzhWZo-D&r5?>pc#cvv74HrRlA}f%7+cMY zl9I{iul3}N?0%Oj0ts>)HEPUE^}ys%$`q!jD58C!*bzMKpStvg>hi&%!35<}82^$t z92N|YO?|Geg`9#Lq{nA}3#VJ(svvrPf9jaKS>|1-q6@(jW-;iDNyHQ- ~/stream-reset + + # Stream Raspberry Pi Camera ffmpeg -f video4linux2 -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -hls_time "${HLS_TIME}" "${what}.m3u8" > ~/ffmpeg.log 2>&1 + + # Stream FM Station from a SDR module (see contrib/pi-stream to install drivers) + # Frequency ends in M IE 99.9M + # rtl_fm -f 99.9M -M fm -s 170k -A std -l0 -E deemp -r 44.1k | ffmpeg -r 15 -loop 1 -i ../audio.jpg -f s16le -ac 1 -i pipe:0 -c:v libx264 -tune stillimage -preset ultrafast -hls_time "${HLS_TIME}" "${what}.m3u8" > ~/ffmpeg 2>&1 + sleep 0.5 done } From 6946f13e157624735f81c98966e81f9ae25233bb Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 15 Dec 2018 10:14:26 -0500 Subject: [PATCH 058/162] Better regex --- scripts/status | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/status b/scripts/status index 5622bfc6a..141ba3732 100755 --- a/scripts/status +++ b/scripts/status @@ -120,12 +120,12 @@ if [ "$(which cjdroute)" ]; then fi if [ "$(which yggdrasil)" ]; then - MYIP=$(ifconfig ygg0 | grep inet6 | grep 202 | awk '{print $2}') + YGGIP=$(ifconfig ygg0 | grep -E 'inet6 2[0-9a-fA-F]{2}:' | awk '{print $2}') echo -e '---------------------------------------' echo -e 'YGGDRASIL NODE' - echo -e $MYIP + echo -e $YGGIP echo -e '---------------------------------------' echo -e 'YGGDRASIL PEERS' - yggdrasilctl getPeers | grep -v "$MYIP" | awk '{print $1}' | grep -v "bytes_recvd" + yggdrasilctl getPeers | grep -v "$YGGIP" | awk '{print $1}' | grep -v "bytes_recvd" echo -e '---------------------------------------' fi From a8ec3c9a2953ee85262a7a861e6265ec798ae510 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 25 Dec 2018 21:11:28 -0500 Subject: [PATCH 059/162] [Contrib] Captive Portal like lock for internet bound connection on an offline node (#229) --- contrib/offline/redirect-port-80.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 contrib/offline/redirect-port-80.sh diff --git a/contrib/offline/redirect-port-80.sh b/contrib/offline/redirect-port-80.sh new file mode 100644 index 000000000..d74965fcb --- /dev/null +++ b/contrib/offline/redirect-port-80.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# Backup file +if ! [ -f "/etc/hostapd/nat.sh.bak" ]; then + sudo cp /etc/hostapd/nat.sh /etc/hostapd/nat.sh.bak +fi + +# Redirect all IPv4 80 traffic to the pi +echo iptables -t nat -I PREROUTING -i wlan-ap -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1:80 | sudo tee --append /etc/hostapd/nat.sh > /dev/null + +# Prevent masquerading out IPv4 +# This is to prevent IPTUNNEL and routing to the internet (Exit node) +sudo sed -i "/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE/d" /etc/hostapd/nat.sh + +# Set nginx to redirect any 404 errors to / +sed -i '$i error_page 404 =200 /index.html;' /etc/nginx/sites-enabled/main.conf +sudo systemctl restart hostapd From 81f3772a65c0c2c92447e2ba8de22cb467476363 Mon Sep 17 00:00:00 2001 From: makeworld <25111343+makeworld-the-better-one@users.noreply.github.com> Date: Tue, 25 Dec 2018 22:08:40 -0500 Subject: [PATCH 060/162] Make nginx install by default (#252) * Made changes according to issue's list * removed extra installs --- scripts/install2 | 3 +++ scripts/ipfs-pi-stream/install | 1 + scripts/ipfs/install | 4 +--- scripts/{shared => }/nginx/index.html | 0 scripts/{shared => }/nginx/install | 0 scripts/{shared => }/nginx/main.conf | 0 scripts/{shared => }/nginx/uninstall | 0 scripts/ssb-patchfoo/install | 6 +----- scripts/ssb-web-pi/install | 4 +--- scripts/uninstall | 2 +- 10 files changed, 8 insertions(+), 12 deletions(-) rename scripts/{shared => }/nginx/index.html (100%) rename scripts/{shared => }/nginx/install (100%) rename scripts/{shared => }/nginx/main.conf (100%) rename scripts/{shared => }/nginx/uninstall (100%) diff --git a/scripts/install2 b/scripts/install2 index d9abcda23..c8f3a70ab 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -331,6 +331,9 @@ sudo systemctl enable cjdns.service NEWHOSTNAME=$(sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g' | sed "s/.*:/$MESH_NAME-/g") export NEWHOSTNAME +# Install nginx +source nginx/install + # Install yggdrasil if [ "$(checkModule 'WITH_YGGDRASIL')" ]; then source yggdrasil/install diff --git a/scripts/ipfs-pi-stream/install b/scripts/ipfs-pi-stream/install index a6cf0a0b5..ed6315a37 100755 --- a/scripts/ipfs-pi-stream/install +++ b/scripts/ipfs-pi-stream/install @@ -8,6 +8,7 @@ BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" sudo "$BASE_DIR/enable-camera.sh" # Install ffmpeg and supporting tools + sudo apt-get install -y ffmpeg lsof inotify-tools nginx # Copy placeholder for audio-only streams diff --git a/scripts/ipfs/install b/scripts/ipfs/install index 36de1de93..2e01ad520 100755 --- a/scripts/ipfs/install +++ b/scripts/ipfs/install @@ -23,8 +23,6 @@ rm -rf "$BASE_DIR/tmp" ipfs init || true # Configure HTTP to IPFS gateway -# shellcheck source=../shared/nginx/install -source "$BASE_DIR/../shared/nginx/install" sudo cp "$BASE_DIR/ipfs-http-gateway.conf" /etc/nginx/site-path-enabled/ipfs-http-gateway.conf sudo systemctl restart nginx.service @@ -51,4 +49,4 @@ sudo systemctl start ipfs.service # Add entry into nginx home screen APP="" -sudo sed -i "s#<\!--APPLIST-->#$APP\n<\!--APPLIST-->#" "/var/www/html/index.html" \ No newline at end of file +sudo sed -i "s#<\!--APPLIST-->#$APP\n<\!--APPLIST-->#" "/var/www/html/index.html" diff --git a/scripts/shared/nginx/index.html b/scripts/nginx/index.html similarity index 100% rename from scripts/shared/nginx/index.html rename to scripts/nginx/index.html diff --git a/scripts/shared/nginx/install b/scripts/nginx/install similarity index 100% rename from scripts/shared/nginx/install rename to scripts/nginx/install diff --git a/scripts/shared/nginx/main.conf b/scripts/nginx/main.conf similarity index 100% rename from scripts/shared/nginx/main.conf rename to scripts/nginx/main.conf diff --git a/scripts/shared/nginx/uninstall b/scripts/nginx/uninstall similarity index 100% rename from scripts/shared/nginx/uninstall rename to scripts/nginx/uninstall diff --git a/scripts/ssb-patchfoo/install b/scripts/ssb-patchfoo/install index 1b5e2c0a0..5e0cec6ba 100755 --- a/scripts/ssb-patchfoo/install +++ b/scripts/ssb-patchfoo/install @@ -6,10 +6,6 @@ BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CURRENT_DIR="$(pwd)" -# Install nginx -# shellcheck source=../shared/nginx/install -source "$BASE_DIR/../shared/nginx/install" - sleep 5 # shellcheck disable=SC2164 cd ~/.ssb/node_modules @@ -43,4 +39,4 @@ APP="

Patch Foo

Plain SSB web UI.
0) { //not self + rx=node.bytes_recvd-lastrx[node.port]; + tx=node.bytes_sent-lasttx[node.port]; + lastrx[node.port]=node.bytes_recvd; + lasttx[node.port]=node.bytes_sent; + UpdateNode(addr,addr,node.port,rx + " bps /" + tx + " bps", "yggdrasil",NodeExist); + } + } + DeleteNodes("yggdrasil",NodeExist); + setTimeout("loadXMLDoc_y()",1000); +} + +// Update Map +// vis.js Initialization +var nodeIDs=[]; +var edgeIDs=[]; +var nodesArray=[]; +var edgesArray=[]; +var nodes=[]; +var edges=[]; +var network=[]; +//var nodeIds,edgesIDs, nodesArray, nodes, edgesArray, edges, network; + +function InitMap(name) { + nodeIDs[name]=[]; + edgeIDs[name]=[]; + nodesArray[name]=[{id: 0, label: 'Me'}]; + nodes[name] = new vis.DataSet(nodesArray[name]); + edgesArray[name] = []; + edges[name] = new vis.DataSet(edgesArray[name]); + var container = document.getElementById('network' + name); + var data = { + nodes: nodes[name], + edges: edges[name] + }; + var options = {}; + network[name]= new vis.Network(container, data, options); +} + +InitMap("cjdns"); +InitMap("yggdrasil"); + +function UpdateNode(nodeID,name,edgeID,edgeLabel,map,NodeExist) { + NodeExist[nodeID]=1; + if (!nodeIDs[map][nodeID]) { + name=name.substr(name.length-4,4); + nodeIDs[map][nodeID]=nodes[map].add({id:nodeID, label:name}); + } + if (!edgeIDs[map][edgeID]) { + edgeIDs[map][edgeID] = edges[map].add({id: edgeID, from: nodeID, to: 0}); + console.debug(edgeID + "-" + nodeID); + } + edges[map].update({id: edgeID, label:edgeLabel }); +} +function DeleteNodes(map,NodeExist) { + for (var key in nodeIDs[map]) { + if (NodeExist[key]!=1) { + nodes[map].remove(key); + nodeIDs[map][key]=undefined; + console.log("gatta delete " + key); + } + } +} diff --git a/scripts/nginx/peers-cjdns b/scripts/nginx/peers-cjdns new file mode 100644 index 000000000..51142e2a8 --- /dev/null +++ b/scripts/nginx/peers-cjdns @@ -0,0 +1,54 @@ +#!/usr/bin/env perl +use warnings; +use strict; +# +# Copyright (C) 2018 Hamish Coleman +# +# The simplest tool was the raw rpc tool +# + +# The default options - should be set from commandline or rc file eventually +my $option = { + addr => "127.0.0.1", + port => "11234", + password => "NONE", + trace => 1, +}; + +BEGIN { + use File::Spec; + # allow the libs to be in the bin dir + unshift @INC, File::Spec->catdir((File::Spec->splitpath($0))[1],'lib'); + print "Content-type: text/html\n\n"; +} + +use mini::Data; +use mini::Digest::SHA; +use Bencode_bork; +use Cjdns::RPC; + +sub main() { + my $rpc = Cjdns::RPC->new( + $option->{addr}, + $option->{port}, + $option->{password}, + ) or die "cannot start rpc"; +# $rpc->trace($option->{trace}); + +# print(mini::Data::Dumper($rpc->ping())); + mini::Data::Dumper($rpc->cookie()); + mini::Data::Dumper($rpc->ping_auth()); + + #print(mini::Data::Dumper($rpc->Admin_availableFunctions())); + + my $packet; +# $packet = $rpc->_build_query_auth('ETHInterface_listDevices'); +# print(mini::Data::Dumper($rpc->_sync_call($packet))); + + $packet = $rpc->_build_query_unauth('InterfaceController_peerStats'); + print(mini::Data::Dumper($rpc->_sync_call($packet))); +} +unless (caller) { + # only run main if we are called as a CLI tool + main(); +} diff --git a/scripts/nginx/peers-yggdrasil b/scripts/nginx/peers-yggdrasil new file mode 100644 index 000000000..b1c6660aa --- /dev/null +++ b/scripts/nginx/peers-yggdrasil @@ -0,0 +1,4 @@ +#!/bin/sh +echo "Content-type: text/html\n\n"; + +yggdrasilctl --json getPeers \ No newline at end of file diff --git a/scripts/nginx/sha512.js b/scripts/nginx/sha512.js new file mode 100644 index 000000000..b145ebb97 --- /dev/null +++ b/scripts/nginx/sha512.js @@ -0,0 +1,927 @@ +/* + * [js-sha512]{@link https://github.com/emn178/js-sha512} + * + * @version 0.8.0 + * @author Chen, Yi-Cyuan [emn178@gmail.com] + * @copyright Chen, Yi-Cyuan 2014-2018 + * @license MIT + */ +/*jslint bitwise: true */ +(function () { + 'use strict'; + + var INPUT_ERROR = 'input is invalid type'; + var FINALIZE_ERROR = 'finalize already called'; + var WINDOW = typeof window === 'object'; + var root = WINDOW ? window : {}; + if (root.JS_SHA512_NO_WINDOW) { + WINDOW = false; + } + var WEB_WORKER = !WINDOW && typeof self === 'object'; + var NODE_JS = !root.JS_SHA512_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node; + if (NODE_JS) { + root = global; + } else if (WEB_WORKER) { + root = self; + } + var COMMON_JS = !root.JS_SHA512_NO_COMMON_JS && typeof module === 'object' && module.exports; + var AMD = typeof define === 'function' && define.amd; + var ARRAY_BUFFER = !root.JS_SHA512_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined'; + var HEX_CHARS = '0123456789abcdef'.split(''); + var EXTRA = [-2147483648, 8388608, 32768, 128]; + var SHIFT = [24, 16, 8, 0]; + var K = [ + 0x428A2F98, 0xD728AE22, 0x71374491, 0x23EF65CD, + 0xB5C0FBCF, 0xEC4D3B2F, 0xE9B5DBA5, 0x8189DBBC, + 0x3956C25B, 0xF348B538, 0x59F111F1, 0xB605D019, + 0x923F82A4, 0xAF194F9B, 0xAB1C5ED5, 0xDA6D8118, + 0xD807AA98, 0xA3030242, 0x12835B01, 0x45706FBE, + 0x243185BE, 0x4EE4B28C, 0x550C7DC3, 0xD5FFB4E2, + 0x72BE5D74, 0xF27B896F, 0x80DEB1FE, 0x3B1696B1, + 0x9BDC06A7, 0x25C71235, 0xC19BF174, 0xCF692694, + 0xE49B69C1, 0x9EF14AD2, 0xEFBE4786, 0x384F25E3, + 0x0FC19DC6, 0x8B8CD5B5, 0x240CA1CC, 0x77AC9C65, + 0x2DE92C6F, 0x592B0275, 0x4A7484AA, 0x6EA6E483, + 0x5CB0A9DC, 0xBD41FBD4, 0x76F988DA, 0x831153B5, + 0x983E5152, 0xEE66DFAB, 0xA831C66D, 0x2DB43210, + 0xB00327C8, 0x98FB213F, 0xBF597FC7, 0xBEEF0EE4, + 0xC6E00BF3, 0x3DA88FC2, 0xD5A79147, 0x930AA725, + 0x06CA6351, 0xE003826F, 0x14292967, 0x0A0E6E70, + 0x27B70A85, 0x46D22FFC, 0x2E1B2138, 0x5C26C926, + 0x4D2C6DFC, 0x5AC42AED, 0x53380D13, 0x9D95B3DF, + 0x650A7354, 0x8BAF63DE, 0x766A0ABB, 0x3C77B2A8, + 0x81C2C92E, 0x47EDAEE6, 0x92722C85, 0x1482353B, + 0xA2BFE8A1, 0x4CF10364, 0xA81A664B, 0xBC423001, + 0xC24B8B70, 0xD0F89791, 0xC76C51A3, 0x0654BE30, + 0xD192E819, 0xD6EF5218, 0xD6990624, 0x5565A910, + 0xF40E3585, 0x5771202A, 0x106AA070, 0x32BBD1B8, + 0x19A4C116, 0xB8D2D0C8, 0x1E376C08, 0x5141AB53, + 0x2748774C, 0xDF8EEB99, 0x34B0BCB5, 0xE19B48A8, + 0x391C0CB3, 0xC5C95A63, 0x4ED8AA4A, 0xE3418ACB, + 0x5B9CCA4F, 0x7763E373, 0x682E6FF3, 0xD6B2B8A3, + 0x748F82EE, 0x5DEFB2FC, 0x78A5636F, 0x43172F60, + 0x84C87814, 0xA1F0AB72, 0x8CC70208, 0x1A6439EC, + 0x90BEFFFA, 0x23631E28, 0xA4506CEB, 0xDE82BDE9, + 0xBEF9A3F7, 0xB2C67915, 0xC67178F2, 0xE372532B, + 0xCA273ECE, 0xEA26619C, 0xD186B8C7, 0x21C0C207, + 0xEADA7DD6, 0xCDE0EB1E, 0xF57D4F7F, 0xEE6ED178, + 0x06F067AA, 0x72176FBA, 0x0A637DC5, 0xA2C898A6, + 0x113F9804, 0xBEF90DAE, 0x1B710B35, 0x131C471B, + 0x28DB77F5, 0x23047D84, 0x32CAAB7B, 0x40C72493, + 0x3C9EBE0A, 0x15C9BEBC, 0x431D67C4, 0x9C100D4C, + 0x4CC5D4BE, 0xCB3E42B6, 0x597F299C, 0xFC657E2A, + 0x5FCB6FAB, 0x3AD6FAEC, 0x6C44198C, 0x4A475817 + ]; + + var OUTPUT_TYPES = ['hex', 'array', 'digest', 'arrayBuffer']; + + var blocks = []; + + if (root.JS_SHA512_NO_NODE_JS || !Array.isArray) { + Array.isArray = function (obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; + }; + } + + if (ARRAY_BUFFER && (root.JS_SHA512_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) { + ArrayBuffer.isView = function (obj) { + return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer; + }; + } + + var createOutputMethod = function (outputType, bits) { + return function (message) { + return new Sha512(bits, true).update(message)[outputType](); + }; + }; + + var createMethod = function (bits) { + var method = createOutputMethod('hex', bits); + method.create = function () { + return new Sha512(bits); + }; + method.update = function (message) { + return method.create().update(message); + }; + for (var i = 0; i < OUTPUT_TYPES.length; ++i) { + var type = OUTPUT_TYPES[i]; + method[type] = createOutputMethod(type, bits); + } + return method; + }; + + var createHmacOutputMethod = function (outputType, bits) { + return function (key, message) { + return new HmacSha512(key, bits, true).update(message)[outputType](); + }; + }; + + var createHmacMethod = function (bits) { + var method = createHmacOutputMethod('hex', bits); + method.create = function (key) { + return new HmacSha512(key, bits); + }; + method.update = function (key, message) { + return method.create(key).update(message); + }; + for (var i = 0; i < OUTPUT_TYPES.length; ++i) { + var type = OUTPUT_TYPES[i]; + method[type] = createHmacOutputMethod(type, bits); + } + return method; + }; + + function Sha512(bits, sharedMemory) { + if (sharedMemory) { + blocks[0] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = + blocks[5] = blocks[6] = blocks[7] = blocks[8] = + blocks[9] = blocks[10] = blocks[11] = blocks[12] = + blocks[13] = blocks[14] = blocks[15] = blocks[16] = + blocks[17] = blocks[18] = blocks[19] = blocks[20] = + blocks[21] = blocks[22] = blocks[23] = blocks[24] = + blocks[25] = blocks[26] = blocks[27] = blocks[28] = + blocks[29] = blocks[30] = blocks[31] = blocks[32] = 0; + this.blocks = blocks; + } else { + this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + } + + if (bits == 384) { + this.h0h = 0xCBBB9D5D; + this.h0l = 0xC1059ED8; + this.h1h = 0x629A292A; + this.h1l = 0x367CD507; + this.h2h = 0x9159015A; + this.h2l = 0x3070DD17; + this.h3h = 0x152FECD8; + this.h3l = 0xF70E5939; + this.h4h = 0x67332667; + this.h4l = 0xFFC00B31; + this.h5h = 0x8EB44A87; + this.h5l = 0x68581511; + this.h6h = 0xDB0C2E0D; + this.h6l = 0x64F98FA7; + this.h7h = 0x47B5481D; + this.h7l = 0xBEFA4FA4; + } else if (bits == 256) { + this.h0h = 0x22312194; + this.h0l = 0xFC2BF72C; + this.h1h = 0x9F555FA3; + this.h1l = 0xC84C64C2; + this.h2h = 0x2393B86B; + this.h2l = 0x6F53B151; + this.h3h = 0x96387719; + this.h3l = 0x5940EABD; + this.h4h = 0x96283EE2; + this.h4l = 0xA88EFFE3; + this.h5h = 0xBE5E1E25; + this.h5l = 0x53863992; + this.h6h = 0x2B0199FC; + this.h6l = 0x2C85B8AA; + this.h7h = 0x0EB72DDC; + this.h7l = 0x81C52CA2; + } else if (bits == 224) { + this.h0h = 0x8C3D37C8; + this.h0l = 0x19544DA2; + this.h1h = 0x73E19966; + this.h1l = 0x89DCD4D6; + this.h2h = 0x1DFAB7AE; + this.h2l = 0x32FF9C82; + this.h3h = 0x679DD514; + this.h3l = 0x582F9FCF; + this.h4h = 0x0F6D2B69; + this.h4l = 0x7BD44DA8; + this.h5h = 0x77E36F73; + this.h5l = 0x04C48942; + this.h6h = 0x3F9D85A8; + this.h6l = 0x6A1D36C8; + this.h7h = 0x1112E6AD; + this.h7l = 0x91D692A1; + } else { // 512 + this.h0h = 0x6A09E667; + this.h0l = 0xF3BCC908; + this.h1h = 0xBB67AE85; + this.h1l = 0x84CAA73B; + this.h2h = 0x3C6EF372; + this.h2l = 0xFE94F82B; + this.h3h = 0xA54FF53A; + this.h3l = 0x5F1D36F1; + this.h4h = 0x510E527F; + this.h4l = 0xADE682D1; + this.h5h = 0x9B05688C; + this.h5l = 0x2B3E6C1F; + this.h6h = 0x1F83D9AB; + this.h6l = 0xFB41BD6B; + this.h7h = 0x5BE0CD19; + this.h7l = 0x137E2179; + } + this.bits = bits; + + this.block = this.start = this.bytes = this.hBytes = 0; + this.finalized = this.hashed = false; + } + + Sha512.prototype.update = function (message) { + if (this.finalized) { + throw new Error(FINALIZE_ERROR); + } + var notString, type = typeof message; + if (type !== 'string') { + if (type === 'object') { + if (message === null) { + throw new Error(INPUT_ERROR); + } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) { + message = new Uint8Array(message); + } else if (!Array.isArray(message)) { + if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) { + throw new Error(INPUT_ERROR); + } + } + } else { + throw new Error(INPUT_ERROR); + } + notString = true; + } + var code, index = 0, i, length = message.length, blocks = this.blocks; + + while (index < length) { + if (this.hashed) { + this.hashed = false; + blocks[0] = this.block; + blocks[1] = blocks[2] = blocks[3] = blocks[4] = + blocks[5] = blocks[6] = blocks[7] = blocks[8] = + blocks[9] = blocks[10] = blocks[11] = blocks[12] = + blocks[13] = blocks[14] = blocks[15] = blocks[16] = + blocks[17] = blocks[18] = blocks[19] = blocks[20] = + blocks[21] = blocks[22] = blocks[23] = blocks[24] = + blocks[25] = blocks[26] = blocks[27] = blocks[28] = + blocks[29] = blocks[30] = blocks[31] = blocks[32] = 0; + } + + if(notString) { + for (i = this.start; index < length && i < 128; ++index) { + blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; + } + } else { + for (i = this.start; index < length && i < 128; ++index) { + code = message.charCodeAt(index); + if (code < 0x80) { + blocks[i >> 2] |= code << SHIFT[i++ & 3]; + } else if (code < 0x800) { + blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } else if (code < 0xd800 || code >= 0xe000) { + blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } else { + code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); + blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } + } + } + + this.lastByteIndex = i; + this.bytes += i - this.start; + if (i >= 128) { + this.block = blocks[32]; + this.start = i - 128; + this.hash(); + this.hashed = true; + } else { + this.start = i; + } + } + if (this.bytes > 4294967295) { + this.hBytes += this.bytes / 4294967296 << 0; + this.bytes = this.bytes % 4294967296; + } + return this; + }; + + Sha512.prototype.finalize = function () { + if (this.finalized) { + return; + } + this.finalized = true; + var blocks = this.blocks, i = this.lastByteIndex; + blocks[32] = this.block; + blocks[i >> 2] |= EXTRA[i & 3]; + this.block = blocks[32]; + if (i >= 112) { + if (!this.hashed) { + this.hash(); + } + blocks[0] = this.block; + blocks[1] = blocks[2] = blocks[3] = blocks[4] = + blocks[5] = blocks[6] = blocks[7] = blocks[8] = + blocks[9] = blocks[10] = blocks[11] = blocks[12] = + blocks[13] = blocks[14] = blocks[15] = blocks[16] = + blocks[17] = blocks[18] = blocks[19] = blocks[20] = + blocks[21] = blocks[22] = blocks[23] = blocks[24] = + blocks[25] = blocks[26] = blocks[27] = blocks[28] = + blocks[29] = blocks[30] = blocks[31] = blocks[32] = 0; + } + blocks[30] = this.hBytes << 3 | this.bytes >>> 29; + blocks[31] = this.bytes << 3; + this.hash(); + }; + + Sha512.prototype.hash = function () { + var h0h = this.h0h, h0l = this.h0l, h1h = this.h1h, h1l = this.h1l, + h2h = this.h2h, h2l = this.h2l, h3h = this.h3h, h3l = this.h3l, + h4h = this.h4h, h4l = this.h4l, h5h = this.h5h, h5l = this.h5l, + h6h = this.h6h, h6l = this.h6l, h7h = this.h7h, h7l = this.h7l, + blocks = this.blocks, j, s0h, s0l, s1h, s1l, c1, c2, c3, c4, + abh, abl, dah, dal, cdh, cdl, bch, bcl, + majh, majl, t1h, t1l, t2h, t2l, chh, chl; + + for (j = 32; j < 160; j += 2) { + t1h = blocks[j - 30]; + t1l = blocks[j - 29]; + s0h = ((t1h >>> 1) | (t1l << 31)) ^ ((t1h >>> 8) | (t1l << 24)) ^ (t1h >>> 7); + s0l = ((t1l >>> 1) | (t1h << 31)) ^ ((t1l >>> 8) | (t1h << 24)) ^ ((t1l >>> 7) | t1h << 25); + + t1h = blocks[j - 4]; + t1l = blocks[j - 3]; + s1h = ((t1h >>> 19) | (t1l << 13)) ^ ((t1l >>> 29) | (t1h << 3)) ^ (t1h >>> 6); + s1l = ((t1l >>> 19) | (t1h << 13)) ^ ((t1h >>> 29) | (t1l << 3)) ^ ((t1l >>> 6) | t1h << 26); + + t1h = blocks[j - 32]; + t1l = blocks[j - 31]; + t2h = blocks[j - 14]; + t2l = blocks[j - 13]; + + c1 = (t2l & 0xFFFF) + (t1l & 0xFFFF) + (s0l & 0xFFFF) + (s1l & 0xFFFF); + c2 = (t2l >>> 16) + (t1l >>> 16) + (s0l >>> 16) + (s1l >>> 16) + (c1 >>> 16); + c3 = (t2h & 0xFFFF) + (t1h & 0xFFFF) + (s0h & 0xFFFF) + (s1h & 0xFFFF) + (c2 >>> 16); + c4 = (t2h >>> 16) + (t1h >>> 16) + (s0h >>> 16) + (s1h >>> 16) + (c3 >>> 16); + + blocks[j] = (c4 << 16) | (c3 & 0xFFFF); + blocks[j + 1] = (c2 << 16) | (c1 & 0xFFFF); + } + + var ah = h0h, al = h0l, bh = h1h, bl = h1l, ch = h2h, cl = h2l, dh = h3h, dl = h3l, eh = h4h, el = h4l, fh = h5h, fl = h5l, gh = h6h, gl = h6l, hh = h7h, hl = h7l; + bch = bh & ch; + bcl = bl & cl; + for (j = 0; j < 160; j += 8) { + s0h = ((ah >>> 28) | (al << 4)) ^ ((al >>> 2) | (ah << 30)) ^ ((al >>> 7) | (ah << 25)); + s0l = ((al >>> 28) | (ah << 4)) ^ ((ah >>> 2) | (al << 30)) ^ ((ah >>> 7) | (al << 25)); + + s1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((el >>> 9) | (eh << 23)); + s1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((eh >>> 9) | (el << 23)); + + abh = ah & bh; + abl = al & bl; + majh = abh ^ (ah & ch) ^ bch; + majl = abl ^ (al & cl) ^ bcl; + + chh = (eh & fh) ^ (~eh & gh); + chl = (el & fl) ^ (~el & gl); + + t1h = blocks[j]; + t1l = blocks[j + 1]; + t2h = K[j]; + t2l = K[j + 1]; + + c1 = (t2l & 0xFFFF) + (t1l & 0xFFFF) + (chl & 0xFFFF) + (s1l & 0xFFFF) + (hl & 0xFFFF); + c2 = (t2l >>> 16) + (t1l >>> 16) + (chl >>> 16) + (s1l >>> 16) + (hl >>> 16) + (c1 >>> 16); + c3 = (t2h & 0xFFFF) + (t1h & 0xFFFF) + (chh & 0xFFFF) + (s1h & 0xFFFF) + (hh & 0xFFFF) + (c2 >>> 16); + c4 = (t2h >>> 16) + (t1h >>> 16) + (chh >>> 16) + (s1h >>> 16) + (hh >>> 16) + (c3 >>> 16); + + t1h = (c4 << 16) | (c3 & 0xFFFF); + t1l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (majl & 0xFFFF) + (s0l & 0xFFFF); + c2 = (majl >>> 16) + (s0l >>> 16) + (c1 >>> 16); + c3 = (majh & 0xFFFF) + (s0h & 0xFFFF) + (c2 >>> 16); + c4 = (majh >>> 16) + (s0h >>> 16) + (c3 >>> 16); + + t2h = (c4 << 16) | (c3 & 0xFFFF); + t2l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (dl & 0xFFFF) + (t1l & 0xFFFF); + c2 = (dl >>> 16) + (t1l >>> 16) + (c1 >>> 16); + c3 = (dh & 0xFFFF) + (t1h & 0xFFFF) + (c2 >>> 16); + c4 = (dh >>> 16) + (t1h >>> 16) + (c3 >>> 16); + + hh = (c4 << 16) | (c3 & 0xFFFF); + hl = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (t2l & 0xFFFF) + (t1l & 0xFFFF); + c2 = (t2l >>> 16) + (t1l >>> 16) + (c1 >>> 16); + c3 = (t2h & 0xFFFF) + (t1h & 0xFFFF) + (c2 >>> 16); + c4 = (t2h >>> 16) + (t1h >>> 16) + (c3 >>> 16); + + dh = (c4 << 16) | (c3 & 0xFFFF); + dl = (c2 << 16) | (c1 & 0xFFFF); + + s0h = ((dh >>> 28) | (dl << 4)) ^ ((dl >>> 2) | (dh << 30)) ^ ((dl >>> 7) | (dh << 25)); + s0l = ((dl >>> 28) | (dh << 4)) ^ ((dh >>> 2) | (dl << 30)) ^ ((dh >>> 7) | (dl << 25)); + + s1h = ((hh >>> 14) | (hl << 18)) ^ ((hh >>> 18) | (hl << 14)) ^ ((hl >>> 9) | (hh << 23)); + s1l = ((hl >>> 14) | (hh << 18)) ^ ((hl >>> 18) | (hh << 14)) ^ ((hh >>> 9) | (hl << 23)); + + dah = dh & ah; + dal = dl & al; + majh = dah ^ (dh & bh) ^ abh; + majl = dal ^ (dl & bl) ^ abl; + + chh = (hh & eh) ^ (~hh & fh); + chl = (hl & el) ^ (~hl & fl); + + t1h = blocks[j + 2]; + t1l = blocks[j + 3]; + t2h = K[j + 2]; + t2l = K[j + 3]; + + c1 = (t2l & 0xFFFF) + (t1l & 0xFFFF) + (chl & 0xFFFF) + (s1l & 0xFFFF) + (gl & 0xFFFF); + c2 = (t2l >>> 16) + (t1l >>> 16) + (chl >>> 16) + (s1l >>> 16) + (gl >>> 16) + (c1 >>> 16); + c3 = (t2h & 0xFFFF) + (t1h & 0xFFFF) + (chh & 0xFFFF) + (s1h & 0xFFFF) + (gh & 0xFFFF) + (c2 >>> 16); + c4 = (t2h >>> 16) + (t1h >>> 16) + (chh >>> 16) + (s1h >>> 16) + (gh >>> 16) + (c3 >>> 16); + + t1h = (c4 << 16) | (c3 & 0xFFFF); + t1l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (majl & 0xFFFF) + (s0l & 0xFFFF); + c2 = (majl >>> 16) + (s0l >>> 16) + (c1 >>> 16); + c3 = (majh & 0xFFFF) + (s0h & 0xFFFF) + (c2 >>> 16); + c4 = (majh >>> 16) + (s0h >>> 16) + (c3 >>> 16); + + t2h = (c4 << 16) | (c3 & 0xFFFF); + t2l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (cl & 0xFFFF) + (t1l & 0xFFFF); + c2 = (cl >>> 16) + (t1l >>> 16) + (c1 >>> 16); + c3 = (ch & 0xFFFF) + (t1h & 0xFFFF) + (c2 >>> 16); + c4 = (ch >>> 16) + (t1h >>> 16) + (c3 >>> 16); + + gh = (c4 << 16) | (c3 & 0xFFFF); + gl = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (t2l & 0xFFFF) + (t1l & 0xFFFF); + c2 = (t2l >>> 16) + (t1l >>> 16) + (c1 >>> 16); + c3 = (t2h & 0xFFFF) + (t1h & 0xFFFF) + (c2 >>> 16); + c4 = (t2h >>> 16) + (t1h >>> 16) + (c3 >>> 16); + + ch = (c4 << 16) | (c3 & 0xFFFF); + cl = (c2 << 16) | (c1 & 0xFFFF); + + s0h = ((ch >>> 28) | (cl << 4)) ^ ((cl >>> 2) | (ch << 30)) ^ ((cl >>> 7) | (ch << 25)); + s0l = ((cl >>> 28) | (ch << 4)) ^ ((ch >>> 2) | (cl << 30)) ^ ((ch >>> 7) | (cl << 25)); + + s1h = ((gh >>> 14) | (gl << 18)) ^ ((gh >>> 18) | (gl << 14)) ^ ((gl >>> 9) | (gh << 23)); + s1l = ((gl >>> 14) | (gh << 18)) ^ ((gl >>> 18) | (gh << 14)) ^ ((gh >>> 9) | (gl << 23)); + + cdh = ch & dh; + cdl = cl & dl; + majh = cdh ^ (ch & ah) ^ dah; + majl = cdl ^ (cl & al) ^ dal; + + chh = (gh & hh) ^ (~gh & eh); + chl = (gl & hl) ^ (~gl & el); + + t1h = blocks[j + 4]; + t1l = blocks[j + 5]; + t2h = K[j + 4]; + t2l = K[j + 5]; + + c1 = (t2l & 0xFFFF) + (t1l & 0xFFFF) + (chl & 0xFFFF) + (s1l & 0xFFFF) + (fl & 0xFFFF); + c2 = (t2l >>> 16) + (t1l >>> 16) + (chl >>> 16) + (s1l >>> 16) + (fl >>> 16) + (c1 >>> 16); + c3 = (t2h & 0xFFFF) + (t1h & 0xFFFF) + (chh & 0xFFFF) + (s1h & 0xFFFF) + (fh & 0xFFFF) + (c2 >>> 16); + c4 = (t2h >>> 16) + (t1h >>> 16) + (chh >>> 16) + (s1h >>> 16) + (fh >>> 16) + (c3 >>> 16); + + t1h = (c4 << 16) | (c3 & 0xFFFF); + t1l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (majl & 0xFFFF) + (s0l & 0xFFFF); + c2 = (majl >>> 16) + (s0l >>> 16) + (c1 >>> 16); + c3 = (majh & 0xFFFF) + (s0h & 0xFFFF) + (c2 >>> 16); + c4 = (majh >>> 16) + (s0h >>> 16) + (c3 >>> 16); + + t2h = (c4 << 16) | (c3 & 0xFFFF); + t2l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (bl & 0xFFFF) + (t1l & 0xFFFF); + c2 = (bl >>> 16) + (t1l >>> 16) + (c1 >>> 16); + c3 = (bh & 0xFFFF) + (t1h & 0xFFFF) + (c2 >>> 16); + c4 = (bh >>> 16) + (t1h >>> 16) + (c3 >>> 16); + + fh = (c4 << 16) | (c3 & 0xFFFF); + fl = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (t2l & 0xFFFF) + (t1l & 0xFFFF); + c2 = (t2l >>> 16) + (t1l >>> 16) + (c1 >>> 16); + c3 = (t2h & 0xFFFF) + (t1h & 0xFFFF) + (c2 >>> 16); + c4 = (t2h >>> 16) + (t1h >>> 16) + (c3 >>> 16); + + bh = (c4 << 16) | (c3 & 0xFFFF); + bl = (c2 << 16) | (c1 & 0xFFFF); + + s0h = ((bh >>> 28) | (bl << 4)) ^ ((bl >>> 2) | (bh << 30)) ^ ((bl >>> 7) | (bh << 25)); + s0l = ((bl >>> 28) | (bh << 4)) ^ ((bh >>> 2) | (bl << 30)) ^ ((bh >>> 7) | (bl << 25)); + + s1h = ((fh >>> 14) | (fl << 18)) ^ ((fh >>> 18) | (fl << 14)) ^ ((fl >>> 9) | (fh << 23)); + s1l = ((fl >>> 14) | (fh << 18)) ^ ((fl >>> 18) | (fh << 14)) ^ ((fh >>> 9) | (fl << 23)); + + bch = bh & ch; + bcl = bl & cl; + majh = bch ^ (bh & dh) ^ cdh; + majl = bcl ^ (bl & dl) ^ cdl; + + chh = (fh & gh) ^ (~fh & hh); + chl = (fl & gl) ^ (~fl & hl); + + t1h = blocks[j + 6]; + t1l = blocks[j + 7]; + t2h = K[j + 6]; + t2l = K[j + 7]; + + c1 = (t2l & 0xFFFF) + (t1l & 0xFFFF) + (chl & 0xFFFF) + (s1l & 0xFFFF) + (el & 0xFFFF); + c2 = (t2l >>> 16) + (t1l >>> 16) + (chl >>> 16) + (s1l >>> 16) + (el >>> 16) + (c1 >>> 16); + c3 = (t2h & 0xFFFF) + (t1h & 0xFFFF) + (chh & 0xFFFF) + (s1h & 0xFFFF) + (eh & 0xFFFF) + (c2 >>> 16); + c4 = (t2h >>> 16) + (t1h >>> 16) + (chh >>> 16) + (s1h >>> 16) + (eh >>> 16) + (c3 >>> 16); + + t1h = (c4 << 16) | (c3 & 0xFFFF); + t1l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (majl & 0xFFFF) + (s0l & 0xFFFF); + c2 = (majl >>> 16) + (s0l >>> 16) + (c1 >>> 16); + c3 = (majh & 0xFFFF) + (s0h & 0xFFFF) + (c2 >>> 16); + c4 = (majh >>> 16) + (s0h >>> 16) + (c3 >>> 16); + + t2h = (c4 << 16) | (c3 & 0xFFFF); + t2l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (al & 0xFFFF) + (t1l & 0xFFFF); + c2 = (al >>> 16) + (t1l >>> 16) + (c1 >>> 16); + c3 = (ah & 0xFFFF) + (t1h & 0xFFFF) + (c2 >>> 16); + c4 = (ah >>> 16) + (t1h >>> 16) + (c3 >>> 16); + + eh = (c4 << 16) | (c3 & 0xFFFF); + el = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (t2l & 0xFFFF) + (t1l & 0xFFFF); + c2 = (t2l >>> 16) + (t1l >>> 16) + (c1 >>> 16); + c3 = (t2h & 0xFFFF) + (t1h & 0xFFFF) + (c2 >>> 16); + c4 = (t2h >>> 16) + (t1h >>> 16) + (c3 >>> 16); + + ah = (c4 << 16) | (c3 & 0xFFFF); + al = (c2 << 16) | (c1 & 0xFFFF); + } + + c1 = (h0l & 0xFFFF) + (al & 0xFFFF); + c2 = (h0l >>> 16) + (al >>> 16) + (c1 >>> 16); + c3 = (h0h & 0xFFFF) + (ah & 0xFFFF) + (c2 >>> 16); + c4 = (h0h >>> 16) + (ah >>> 16) + (c3 >>> 16); + + this.h0h = (c4 << 16) | (c3 & 0xFFFF); + this.h0l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (h1l & 0xFFFF) + (bl & 0xFFFF); + c2 = (h1l >>> 16) + (bl >>> 16) + (c1 >>> 16); + c3 = (h1h & 0xFFFF) + (bh & 0xFFFF) + (c2 >>> 16); + c4 = (h1h >>> 16) + (bh >>> 16) + (c3 >>> 16); + + this.h1h = (c4 << 16) | (c3 & 0xFFFF); + this.h1l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (h2l & 0xFFFF) + (cl & 0xFFFF); + c2 = (h2l >>> 16) + (cl >>> 16) + (c1 >>> 16); + c3 = (h2h & 0xFFFF) + (ch & 0xFFFF) + (c2 >>> 16); + c4 = (h2h >>> 16) + (ch >>> 16) + (c3 >>> 16); + + this.h2h = (c4 << 16) | (c3 & 0xFFFF); + this.h2l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (h3l & 0xFFFF) + (dl & 0xFFFF); + c2 = (h3l >>> 16) + (dl >>> 16) + (c1 >>> 16); + c3 = (h3h & 0xFFFF) + (dh & 0xFFFF) + (c2 >>> 16); + c4 = (h3h >>> 16) + (dh >>> 16) + (c3 >>> 16); + + this.h3h = (c4 << 16) | (c3 & 0xFFFF); + this.h3l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (h4l & 0xFFFF) + (el & 0xFFFF); + c2 = (h4l >>> 16) + (el >>> 16) + (c1 >>> 16); + c3 = (h4h & 0xFFFF) + (eh & 0xFFFF) + (c2 >>> 16); + c4 = (h4h >>> 16) + (eh >>> 16) + (c3 >>> 16); + + this.h4h = (c4 << 16) | (c3 & 0xFFFF); + this.h4l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (h5l & 0xFFFF) + (fl & 0xFFFF); + c2 = (h5l >>> 16) + (fl >>> 16) + (c1 >>> 16); + c3 = (h5h & 0xFFFF) + (fh & 0xFFFF) + (c2 >>> 16); + c4 = (h5h >>> 16) + (fh >>> 16) + (c3 >>> 16); + + this.h5h = (c4 << 16) | (c3 & 0xFFFF); + this.h5l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (h6l & 0xFFFF) + (gl & 0xFFFF); + c2 = (h6l >>> 16) + (gl >>> 16) + (c1 >>> 16); + c3 = (h6h & 0xFFFF) + (gh & 0xFFFF) + (c2 >>> 16); + c4 = (h6h >>> 16) + (gh >>> 16) + (c3 >>> 16); + + this.h6h = (c4 << 16) | (c3 & 0xFFFF); + this.h6l = (c2 << 16) | (c1 & 0xFFFF); + + c1 = (h7l & 0xFFFF) + (hl & 0xFFFF); + c2 = (h7l >>> 16) + (hl >>> 16) + (c1 >>> 16); + c3 = (h7h & 0xFFFF) + (hh & 0xFFFF) + (c2 >>> 16); + c4 = (h7h >>> 16) + (hh >>> 16) + (c3 >>> 16); + + this.h7h = (c4 << 16) | (c3 & 0xFFFF); + this.h7l = (c2 << 16) | (c1 & 0xFFFF); + }; + + Sha512.prototype.hex = function () { + this.finalize(); + + var h0h = this.h0h, h0l = this.h0l, h1h = this.h1h, h1l = this.h1l, + h2h = this.h2h, h2l = this.h2l, h3h = this.h3h, h3l = this.h3l, + h4h = this.h4h, h4l = this.h4l, h5h = this.h5h, h5l = this.h5l, + h6h = this.h6h, h6l = this.h6l, h7h = this.h7h, h7l = this.h7l, + bits = this.bits; + + var hex = HEX_CHARS[(h0h >> 28) & 0x0F] + HEX_CHARS[(h0h >> 24) & 0x0F] + + HEX_CHARS[(h0h >> 20) & 0x0F] + HEX_CHARS[(h0h >> 16) & 0x0F] + + HEX_CHARS[(h0h >> 12) & 0x0F] + HEX_CHARS[(h0h >> 8) & 0x0F] + + HEX_CHARS[(h0h >> 4) & 0x0F] + HEX_CHARS[h0h & 0x0F] + + HEX_CHARS[(h0l >> 28) & 0x0F] + HEX_CHARS[(h0l >> 24) & 0x0F] + + HEX_CHARS[(h0l >> 20) & 0x0F] + HEX_CHARS[(h0l >> 16) & 0x0F] + + HEX_CHARS[(h0l >> 12) & 0x0F] + HEX_CHARS[(h0l >> 8) & 0x0F] + + HEX_CHARS[(h0l >> 4) & 0x0F] + HEX_CHARS[h0l & 0x0F] + + HEX_CHARS[(h1h >> 28) & 0x0F] + HEX_CHARS[(h1h >> 24) & 0x0F] + + HEX_CHARS[(h1h >> 20) & 0x0F] + HEX_CHARS[(h1h >> 16) & 0x0F] + + HEX_CHARS[(h1h >> 12) & 0x0F] + HEX_CHARS[(h1h >> 8) & 0x0F] + + HEX_CHARS[(h1h >> 4) & 0x0F] + HEX_CHARS[h1h & 0x0F] + + HEX_CHARS[(h1l >> 28) & 0x0F] + HEX_CHARS[(h1l >> 24) & 0x0F] + + HEX_CHARS[(h1l >> 20) & 0x0F] + HEX_CHARS[(h1l >> 16) & 0x0F] + + HEX_CHARS[(h1l >> 12) & 0x0F] + HEX_CHARS[(h1l >> 8) & 0x0F] + + HEX_CHARS[(h1l >> 4) & 0x0F] + HEX_CHARS[h1l & 0x0F] + + HEX_CHARS[(h2h >> 28) & 0x0F] + HEX_CHARS[(h2h >> 24) & 0x0F] + + HEX_CHARS[(h2h >> 20) & 0x0F] + HEX_CHARS[(h2h >> 16) & 0x0F] + + HEX_CHARS[(h2h >> 12) & 0x0F] + HEX_CHARS[(h2h >> 8) & 0x0F] + + HEX_CHARS[(h2h >> 4) & 0x0F] + HEX_CHARS[h2h & 0x0F] + + HEX_CHARS[(h2l >> 28) & 0x0F] + HEX_CHARS[(h2l >> 24) & 0x0F] + + HEX_CHARS[(h2l >> 20) & 0x0F] + HEX_CHARS[(h2l >> 16) & 0x0F] + + HEX_CHARS[(h2l >> 12) & 0x0F] + HEX_CHARS[(h2l >> 8) & 0x0F] + + HEX_CHARS[(h2l >> 4) & 0x0F] + HEX_CHARS[h2l & 0x0F] + + HEX_CHARS[(h3h >> 28) & 0x0F] + HEX_CHARS[(h3h >> 24) & 0x0F] + + HEX_CHARS[(h3h >> 20) & 0x0F] + HEX_CHARS[(h3h >> 16) & 0x0F] + + HEX_CHARS[(h3h >> 12) & 0x0F] + HEX_CHARS[(h3h >> 8) & 0x0F] + + HEX_CHARS[(h3h >> 4) & 0x0F] + HEX_CHARS[h3h & 0x0F]; + if (bits >= 256) { + hex += HEX_CHARS[(h3l >> 28) & 0x0F] + HEX_CHARS[(h3l >> 24) & 0x0F] + + HEX_CHARS[(h3l >> 20) & 0x0F] + HEX_CHARS[(h3l >> 16) & 0x0F] + + HEX_CHARS[(h3l >> 12) & 0x0F] + HEX_CHARS[(h3l >> 8) & 0x0F] + + HEX_CHARS[(h3l >> 4) & 0x0F] + HEX_CHARS[h3l & 0x0F]; + } + if (bits >= 384) { + hex += HEX_CHARS[(h4h >> 28) & 0x0F] + HEX_CHARS[(h4h >> 24) & 0x0F] + + HEX_CHARS[(h4h >> 20) & 0x0F] + HEX_CHARS[(h4h >> 16) & 0x0F] + + HEX_CHARS[(h4h >> 12) & 0x0F] + HEX_CHARS[(h4h >> 8) & 0x0F] + + HEX_CHARS[(h4h >> 4) & 0x0F] + HEX_CHARS[h4h & 0x0F] + + HEX_CHARS[(h4l >> 28) & 0x0F] + HEX_CHARS[(h4l >> 24) & 0x0F] + + HEX_CHARS[(h4l >> 20) & 0x0F] + HEX_CHARS[(h4l >> 16) & 0x0F] + + HEX_CHARS[(h4l >> 12) & 0x0F] + HEX_CHARS[(h4l >> 8) & 0x0F] + + HEX_CHARS[(h4l >> 4) & 0x0F] + HEX_CHARS[h4l & 0x0F] + + HEX_CHARS[(h5h >> 28) & 0x0F] + HEX_CHARS[(h5h >> 24) & 0x0F] + + HEX_CHARS[(h5h >> 20) & 0x0F] + HEX_CHARS[(h5h >> 16) & 0x0F] + + HEX_CHARS[(h5h >> 12) & 0x0F] + HEX_CHARS[(h5h >> 8) & 0x0F] + + HEX_CHARS[(h5h >> 4) & 0x0F] + HEX_CHARS[h5h & 0x0F] + + HEX_CHARS[(h5l >> 28) & 0x0F] + HEX_CHARS[(h5l >> 24) & 0x0F] + + HEX_CHARS[(h5l >> 20) & 0x0F] + HEX_CHARS[(h5l >> 16) & 0x0F] + + HEX_CHARS[(h5l >> 12) & 0x0F] + HEX_CHARS[(h5l >> 8) & 0x0F] + + HEX_CHARS[(h5l >> 4) & 0x0F] + HEX_CHARS[h5l & 0x0F]; + } + if (bits == 512) { + hex += HEX_CHARS[(h6h >> 28) & 0x0F] + HEX_CHARS[(h6h >> 24) & 0x0F] + + HEX_CHARS[(h6h >> 20) & 0x0F] + HEX_CHARS[(h6h >> 16) & 0x0F] + + HEX_CHARS[(h6h >> 12) & 0x0F] + HEX_CHARS[(h6h >> 8) & 0x0F] + + HEX_CHARS[(h6h >> 4) & 0x0F] + HEX_CHARS[h6h & 0x0F] + + HEX_CHARS[(h6l >> 28) & 0x0F] + HEX_CHARS[(h6l >> 24) & 0x0F] + + HEX_CHARS[(h6l >> 20) & 0x0F] + HEX_CHARS[(h6l >> 16) & 0x0F] + + HEX_CHARS[(h6l >> 12) & 0x0F] + HEX_CHARS[(h6l >> 8) & 0x0F] + + HEX_CHARS[(h6l >> 4) & 0x0F] + HEX_CHARS[h6l & 0x0F] + + HEX_CHARS[(h7h >> 28) & 0x0F] + HEX_CHARS[(h7h >> 24) & 0x0F] + + HEX_CHARS[(h7h >> 20) & 0x0F] + HEX_CHARS[(h7h >> 16) & 0x0F] + + HEX_CHARS[(h7h >> 12) & 0x0F] + HEX_CHARS[(h7h >> 8) & 0x0F] + + HEX_CHARS[(h7h >> 4) & 0x0F] + HEX_CHARS[h7h & 0x0F] + + HEX_CHARS[(h7l >> 28) & 0x0F] + HEX_CHARS[(h7l >> 24) & 0x0F] + + HEX_CHARS[(h7l >> 20) & 0x0F] + HEX_CHARS[(h7l >> 16) & 0x0F] + + HEX_CHARS[(h7l >> 12) & 0x0F] + HEX_CHARS[(h7l >> 8) & 0x0F] + + HEX_CHARS[(h7l >> 4) & 0x0F] + HEX_CHARS[h7l & 0x0F]; + } + return hex; + }; + + Sha512.prototype.toString = Sha512.prototype.hex; + + Sha512.prototype.digest = function () { + this.finalize(); + + var h0h = this.h0h, h0l = this.h0l, h1h = this.h1h, h1l = this.h1l, + h2h = this.h2h, h2l = this.h2l, h3h = this.h3h, h3l = this.h3l, + h4h = this.h4h, h4l = this.h4l, h5h = this.h5h, h5l = this.h5l, + h6h = this.h6h, h6l = this.h6l, h7h = this.h7h, h7l = this.h7l, + bits = this.bits; + + var arr = [ + (h0h >> 24) & 0xFF, (h0h >> 16) & 0xFF, (h0h >> 8) & 0xFF, h0h & 0xFF, + (h0l >> 24) & 0xFF, (h0l >> 16) & 0xFF, (h0l >> 8) & 0xFF, h0l & 0xFF, + (h1h >> 24) & 0xFF, (h1h >> 16) & 0xFF, (h1h >> 8) & 0xFF, h1h & 0xFF, + (h1l >> 24) & 0xFF, (h1l >> 16) & 0xFF, (h1l >> 8) & 0xFF, h1l & 0xFF, + (h2h >> 24) & 0xFF, (h2h >> 16) & 0xFF, (h2h >> 8) & 0xFF, h2h & 0xFF, + (h2l >> 24) & 0xFF, (h2l >> 16) & 0xFF, (h2l >> 8) & 0xFF, h2l & 0xFF, + (h3h >> 24) & 0xFF, (h3h >> 16) & 0xFF, (h3h >> 8) & 0xFF, h3h & 0xFF + ]; + + if (bits >= 256) { + arr.push((h3l >> 24) & 0xFF, (h3l >> 16) & 0xFF, (h3l >> 8) & 0xFF, h3l & 0xFF); + } + if (bits >= 384) { + arr.push( + (h4h >> 24) & 0xFF, (h4h >> 16) & 0xFF, (h4h >> 8) & 0xFF, h4h & 0xFF, + (h4l >> 24) & 0xFF, (h4l >> 16) & 0xFF, (h4l >> 8) & 0xFF, h4l & 0xFF, + (h5h >> 24) & 0xFF, (h5h >> 16) & 0xFF, (h5h >> 8) & 0xFF, h5h & 0xFF, + (h5l >> 24) & 0xFF, (h5l >> 16) & 0xFF, (h5l >> 8) & 0xFF, h5l & 0xFF + ); + } + if (bits == 512) { + arr.push( + (h6h >> 24) & 0xFF, (h6h >> 16) & 0xFF, (h6h >> 8) & 0xFF, h6h & 0xFF, + (h6l >> 24) & 0xFF, (h6l >> 16) & 0xFF, (h6l >> 8) & 0xFF, h6l & 0xFF, + (h7h >> 24) & 0xFF, (h7h >> 16) & 0xFF, (h7h >> 8) & 0xFF, h7h & 0xFF, + (h7l >> 24) & 0xFF, (h7l >> 16) & 0xFF, (h7l >> 8) & 0xFF, h7l & 0xFF + ); + } + return arr; + }; + + Sha512.prototype.array = Sha512.prototype.digest; + + Sha512.prototype.arrayBuffer = function () { + this.finalize(); + + var bits = this.bits; + var buffer = new ArrayBuffer(bits / 8); + var dataView = new DataView(buffer); + dataView.setUint32(0, this.h0h); + dataView.setUint32(4, this.h0l); + dataView.setUint32(8, this.h1h); + dataView.setUint32(12, this.h1l); + dataView.setUint32(16, this.h2h); + dataView.setUint32(20, this.h2l); + dataView.setUint32(24, this.h3h); + + if (bits >= 256) { + dataView.setUint32(28, this.h3l); + } + if (bits >= 384) { + dataView.setUint32(32, this.h4h); + dataView.setUint32(36, this.h4l); + dataView.setUint32(40, this.h5h); + dataView.setUint32(44, this.h5l); + } + if (bits == 512) { + dataView.setUint32(48, this.h6h); + dataView.setUint32(52, this.h6l); + dataView.setUint32(56, this.h7h); + dataView.setUint32(60, this.h7l); + } + return buffer; + }; + + Sha512.prototype.clone = function () { + var hash = new Sha512(this.bits, false); + this.copyTo(hash); + return hash; + }; + + Sha512.prototype.copyTo = function (hash) { + var i = 0, attrs = [ + 'h0h', 'h0l', 'h1h', 'h1l', 'h2h', 'h2l', 'h3h', 'h3l', 'h4h', 'h4l', 'h5h', 'h5l', 'h6h', 'h6l', 'h7h', 'h7l', + 'start', 'bytes', 'hBytes', 'finalized', 'hashed', 'lastByteIndex' + ]; + for (i = 0; i < attrs.length; ++i) { + hash[attrs[i]] = this[attrs[i]]; + } + for (i = 0; i < this.blocks.length; ++i) { + hash.blocks[i] = this.blocks[i]; + } + }; + + function HmacSha512(key, bits, sharedMemory) { + var notString, type = typeof key; + if (type !== 'string') { + if (type === 'object') { + if (key === null) { + throw new Error(INPUT_ERROR); + } else if (ARRAY_BUFFER && key.constructor === ArrayBuffer) { + key = new Uint8Array(key); + } else if (!Array.isArray(key)) { + if (!ARRAY_BUFFER || !ArrayBuffer.isView(key)) { + throw new Error(INPUT_ERROR); + } + } + } else { + throw new Error(INPUT_ERROR); + } + notString = true; + } + var length = key.length; + if (!notString) { + var bytes = [], length = key.length, index = 0, code; + for (var i = 0; i < length; ++i) { + code = key.charCodeAt(i); + if (code < 0x80) { + bytes[index++] = code; + } else if (code < 0x800) { + bytes[index++] = (0xc0 | (code >> 6)); + bytes[index++] = (0x80 | (code & 0x3f)); + } else if (code < 0xd800 || code >= 0xe000) { + bytes[index++] = (0xe0 | (code >> 12)); + bytes[index++] = (0x80 | ((code >> 6) & 0x3f)); + bytes[index++] = (0x80 | (code & 0x3f)); + } else { + code = 0x10000 + (((code & 0x3ff) << 10) | (key.charCodeAt(++i) & 0x3ff)); + bytes[index++] = (0xf0 | (code >> 18)); + bytes[index++] = (0x80 | ((code >> 12) & 0x3f)); + bytes[index++] = (0x80 | ((code >> 6) & 0x3f)); + bytes[index++] = (0x80 | (code & 0x3f)); + } + } + key = bytes; + } + + if (key.length > 128) { + key = (new Sha512(bits, true)).update(key).array(); + } + + var oKeyPad = [], iKeyPad = []; + for (var i = 0; i < 128; ++i) { + var b = key[i] || 0; + oKeyPad[i] = 0x5c ^ b; + iKeyPad[i] = 0x36 ^ b; + } + + Sha512.call(this, bits, sharedMemory); + + this.update(iKeyPad); + this.oKeyPad = oKeyPad; + this.inner = true; + this.sharedMemory = sharedMemory; + } + HmacSha512.prototype = new Sha512(); + + HmacSha512.prototype.finalize = function () { + Sha512.prototype.finalize.call(this); + if (this.inner) { + this.inner = false; + var innerHash = this.array(); + Sha512.call(this, this.bits, this.sharedMemory); + this.update(this.oKeyPad); + this.update(innerHash); + Sha512.prototype.finalize.call(this); + } + }; + + HmacSha512.prototype.clone = function () { + var hash = new HmacSha512([], this.bits, false); + this.copyTo(hash); + hash.inner = this.inner; + for (var i = 0; i < this.oKeyPad.length; ++i) { + hash.oKeyPad[i] = this.oKeyPad[i]; + } + return hash; + }; + + var exports = createMethod(512); + exports.sha512 = exports; + exports.sha384 = createMethod(384); + exports.sha512_256 = createMethod(256); + exports.sha512_224 = createMethod(224); + exports.sha512.hmac = createHmacMethod(512); + exports.sha384.hmac = createHmacMethod(384); + exports.sha512_256.hmac = createHmacMethod(256); + exports.sha512_224.hmac = createHmacMethod(224); + + if (COMMON_JS) { + module.exports = exports; + } else { + root.sha512 = exports.sha512; + root.sha384 = exports.sha384; + root.sha512_256 = exports.sha512_256; + root.sha512_224 = exports.sha512_224; + if (AMD) { + define(function () { + return exports; + }); + } + } +})(); diff --git a/scripts/nginx/uninstall b/scripts/nginx/uninstall index 89208895f..36a2abdea 100644 --- a/scripts/nginx/uninstall +++ b/scripts/nginx/uninstall @@ -5,4 +5,4 @@ sudo rm -rf /etc/nginx/sites-enabled/main.conf || true sudo rm /etc/nginx/sites-enabled/default || true sudo rm -rf /etc/nginx/site-path-enabled || true sudo apt-get remove nginx -y -sudo rm -rf /var/www/html/index.html \ No newline at end of file +sudo rm -rf /var/www/html \ No newline at end of file diff --git a/scripts/nginx/vis-network.min.css b/scripts/nginx/vis-network.min.css new file mode 100644 index 000000000..ea487a481 --- /dev/null +++ b/scripts/nginx/vis-network.min.css @@ -0,0 +1 @@ +.vis .overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-active{box-shadow:0 0 10px #86d5f8}.vis [class*=span]{min-height:0;width:auto}div.vis-configuration{position:relative;display:block;float:left;font-size:12px}div.vis-configuration-wrapper{display:block;width:700px}div.vis-configuration-wrapper::after{clear:both;content:"";display:block}div.vis-configuration.vis-config-option-container{display:block;width:495px;background-color:#fff;border:2px solid #f7f8fa;border-radius:4px;margin-top:20px;left:10px;padding-left:5px}div.vis-configuration.vis-config-button{display:block;width:495px;height:25px;vertical-align:middle;line-height:25px;background-color:#f7f8fa;border:2px solid #ceced0;border-radius:4px;margin-top:20px;left:10px;padding-left:5px;cursor:pointer;margin-bottom:30px}div.vis-configuration.vis-config-button.hover{background-color:#4588e6;border:2px solid #214373;color:#fff}div.vis-configuration.vis-config-item{display:block;float:left;width:495px;height:25px;vertical-align:middle;line-height:25px}div.vis-configuration.vis-config-item.vis-config-s2{left:10px;background-color:#f7f8fa;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s3{left:20px;background-color:#e4e9f0;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s4{left:30px;background-color:#cfd8e6;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-header{font-size:18px;font-weight:700}div.vis-configuration.vis-config-label{width:120px;height:25px;line-height:25px}div.vis-configuration.vis-config-label.vis-config-s3{width:110px}div.vis-configuration.vis-config-label.vis-config-s4{width:100px}div.vis-configuration.vis-config-colorBlock{top:1px;width:30px;height:19px;border:1px solid #444;border-radius:2px;padding:0;margin:0;cursor:pointer}input.vis-configuration.vis-config-checkbox{left:-5px}input.vis-configuration.vis-config-rangeinput{position:relative;top:-5px;width:60px;padding:1px;margin:0;pointer-events:none}input.vis-configuration.vis-config-range{-webkit-appearance:none;border:0 solid #fff;background-color:rgba(0,0,0,0);width:300px;height:20px}input.vis-configuration.vis-config-range::-webkit-slider-runnable-track{width:300px;height:5px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-webkit-slider-thumb{-webkit-appearance:none;border:1px solid #14334b;height:17px;width:17px;border-radius:50%;background:#3876c2;background:-moz-linear-gradient(top,#3876c2 0,#385380 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3876c2),color-stop(100%,#385380));background:-webkit-linear-gradient(top,#3876c2 0,#385380 100%);background:-o-linear-gradient(top,#3876c2 0,#385380 100%);background:-ms-linear-gradient(top,#3876c2 0,#385380 100%);background:linear-gradient(to bottom,#3876c2 0,#385380 100%);box-shadow:#111927 0 0 1px 0;margin-top:-7px}input.vis-configuration.vis-config-range:focus{outline:0}input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track{background:#9d9d9d;background:-moz-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#9d9d9d),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-o-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:linear-gradient(to bottom,#9d9d9d 0,#c8c8c8 99%)}input.vis-configuration.vis-config-range::-moz-range-track{width:300px;height:10px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-moz-range-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:-moz-focusring{outline:1px solid #fff;outline-offset:-1px}input.vis-configuration.vis-config-range::-ms-track{width:300px;height:5px;background:0 0;border-color:transparent;border-width:6px 0;color:transparent}input.vis-configuration.vis-config-range::-ms-fill-lower{background:#777;border-radius:10px}input.vis-configuration.vis-config-range::-ms-fill-upper{background:#ddd;border-radius:10px}input.vis-configuration.vis-config-range::-ms-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:focus::-ms-fill-lower{background:#888}input.vis-configuration.vis-config-range:focus::-ms-fill-upper{background:#ccc}.vis-configuration-popup{position:absolute;background:rgba(57,76,89,.85);border:2px solid #f2faff;line-height:30px;height:30px;width:150px;text-align:center;color:#fff;font-size:14px;border-radius:4px;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out}.vis-configuration-popup:after,.vis-configuration-popup:before{left:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.vis-configuration-popup:after{border-color:rgba(136,183,213,0);border-left-color:rgba(57,76,89,.85);border-width:8px;margin-top:-8px}.vis-configuration-popup:before{border-color:rgba(194,225,245,0);border-left-color:#f2faff;border-width:12px;margin-top:-12px}div.vis-tooltip{position:absolute;visibility:hidden;padding:5px;white-space:nowrap;font-family:verdana;font-size:14px;color:#000;background-color:#f5f4ed;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;border:1px solid #808074;box-shadow:3px 3px 10px rgba(0,0,0,.2);pointer-events:none;z-index:5}div.vis-color-picker{position:absolute;top:0;left:30px;margin-top:-140px;margin-left:30px;width:310px;height:444px;z-index:1;padding:10px;border-radius:15px;background-color:#fff;display:none;box-shadow:rgba(0,0,0,.5) 0 0 10px 0}div.vis-color-picker div.vis-arrow{position:absolute;top:147px;left:5px}div.vis-color-picker div.vis-arrow::after,div.vis-color-picker div.vis-arrow::before{right:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.vis-color-picker div.vis-arrow:after{border-color:rgba(255,255,255,0);border-right-color:#fff;border-width:30px;margin-top:-30px}div.vis-color-picker div.vis-color{position:absolute;width:289px;height:289px;cursor:pointer}div.vis-color-picker div.vis-brightness{position:absolute;top:313px}div.vis-color-picker div.vis-opacity{position:absolute;top:350px}div.vis-color-picker div.vis-selector{position:absolute;top:137px;left:137px;width:15px;height:15px;border-radius:15px;border:1px solid #fff;background:#4c4c4c;background:-moz-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4c4c4c),color-stop(12%,#595959),color-stop(25%,#666),color-stop(39%,#474747),color-stop(50%,#2c2c2c),color-stop(51%,#000),color-stop(60%,#111),color-stop(76%,#2b2b2b),color-stop(91%,#1c1c1c),color-stop(100%,#131313));background:-webkit-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-o-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-ms-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:linear-gradient(to bottom,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%)}div.vis-color-picker div.vis-new-color{position:absolute;width:140px;height:20px;border:1px solid rgba(0,0,0,.1);border-radius:5px;top:380px;left:159px;text-align:right;padding-right:2px;font-size:10px;color:rgba(0,0,0,.4);vertical-align:middle;line-height:20px}div.vis-color-picker div.vis-initial-color{position:absolute;width:140px;height:20px;border:1px solid rgba(0,0,0,.1);border-radius:5px;top:380px;left:10px;text-align:left;padding-left:2px;font-size:10px;color:rgba(0,0,0,.4);vertical-align:middle;line-height:20px}div.vis-color-picker div.vis-label{position:absolute;width:300px;left:10px}div.vis-color-picker div.vis-label.vis-brightness{top:300px}div.vis-color-picker div.vis-label.vis-opacity{top:338px}div.vis-color-picker div.vis-button{position:absolute;width:68px;height:25px;border-radius:10px;vertical-align:middle;text-align:center;line-height:25px;top:410px;border:2px solid #d9d9d9;background-color:#f7f7f7;cursor:pointer}div.vis-color-picker div.vis-button.vis-cancel{left:5px}div.vis-color-picker div.vis-button.vis-load{left:82px}div.vis-color-picker div.vis-button.vis-apply{left:159px}div.vis-color-picker div.vis-button.vis-save{left:236px}div.vis-color-picker input.vis-range{width:290px;height:20px}div.vis-network div.vis-manipulation{box-sizing:content-box;border-width:0;border-bottom:1px;border-style:solid;border-color:#d6d9d8;background:#fff;background:-moz-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(48%,#fcfcfc),color-stop(50%,#fafafa),color-stop(100%,#fcfcfc));background:-webkit-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-o-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-ms-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:linear-gradient(to bottom,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);padding-top:4px;position:absolute;left:0;top:0;width:100%;height:28px}div.vis-network div.vis-edit-mode{position:absolute;left:0;top:5px;height:30px}div.vis-network div.vis-close{position:absolute;right:0;top:0;width:30px;height:30px;background-position:20px 3px;background-repeat:no-repeat;background-image:url(img/network/cross.png);cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-close:hover{opacity:.6}div.vis-network div.vis-edit-mode div.vis-button,div.vis-network div.vis-manipulation div.vis-button{float:left;font-family:verdana;font-size:12px;-moz-border-radius:15px;border-radius:15px;display:inline-block;background-position:0 0;background-repeat:no-repeat;height:24px;margin-left:10px;cursor:pointer;padding:0 8px 0 8px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-manipulation div.vis-button:hover{box-shadow:1px 1px 8px rgba(0,0,0,.2)}div.vis-network div.vis-manipulation div.vis-button:active{box-shadow:1px 1px 8px rgba(0,0,0,.5)}div.vis-network div.vis-manipulation div.vis-button.vis-back{background-image:url(img/network/backIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-none:hover{box-shadow:1px 1px 8px transparent;cursor:default}div.vis-network div.vis-manipulation div.vis-button.vis-none:active{box-shadow:1px 1px 8px transparent}div.vis-network div.vis-manipulation div.vis-button.vis-none{padding:0}div.vis-network div.vis-manipulation div.notification{margin:2px;font-weight:700}div.vis-network div.vis-manipulation div.vis-button.vis-add{background-image:url(img/network/addNodeIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit,div.vis-network div.vis-manipulation div.vis-button.vis-edit{background-image:url(img/network/editIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit.vis-edit-mode{background-color:#fcfcfc;border:1px solid #ccc}div.vis-network div.vis-manipulation div.vis-button.vis-connect{background-image:url(img/network/connectIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-delete{background-image:url(img/network/deleteIcon.png)}div.vis-network div.vis-edit-mode div.vis-label,div.vis-network div.vis-manipulation div.vis-label{margin:0 0 0 23px;line-height:25px}div.vis-network div.vis-manipulation div.vis-separator-line{float:left;display:inline-block;width:1px;height:21px;background-color:#bdbdbd;margin:0 7px 0 15px}div.vis-network div.vis-navigation div.vis-button{width:34px;height:34px;-moz-border-radius:17px;border-radius:17px;position:absolute;display:inline-block;background-position:2px 2px;background-repeat:no-repeat;cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-navigation div.vis-button:hover{box-shadow:0 0 3px 3px rgba(56,207,21,.3)}div.vis-network div.vis-navigation div.vis-button:active{box-shadow:0 0 1px 3px rgba(56,207,21,.95)}div.vis-network div.vis-navigation div.vis-button.vis-up{background-image:url(img/network/upArrow.png);bottom:50px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-down{background-image:url(img/network/downArrow.png);bottom:10px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-left{background-image:url(img/network/leftArrow.png);bottom:10px;left:15px}div.vis-network div.vis-navigation div.vis-button.vis-right{background-image:url(img/network/rightArrow.png);bottom:10px;left:95px}div.vis-network div.vis-navigation div.vis-button.vis-zoomIn{background-image:url(img/network/plus.png);bottom:10px;right:15px}div.vis-network div.vis-navigation div.vis-button.vis-zoomOut{background-image:url(img/network/minus.png);bottom:10px;right:55px}div.vis-network div.vis-navigation div.vis-button.vis-zoomExtends{background-image:url(img/network/zoomExtends.png);bottom:50px;right:15px} \ No newline at end of file diff --git a/scripts/nginx/vis.min.js b/scripts/nginx/vis.min.js new file mode 100644 index 000000000..1136c8a15 --- /dev/null +++ b/scripts/nginx/vis.min.js @@ -0,0 +1,47 @@ +/** + * vis.js + * https://github.com/almende/vis + * + * A dynamic, browser-based visualization library. + * + * @version 4.21.0 + * @date 2017-10-12 + * + * @license + * Copyright (C) 2011-2017 Almende B.V, http://almende.com + * + * Vis.js is dual licensed under both + * + * * The Apache 2.0 License + * http://www.apache.org/licenses/LICENSE-2.0 + * + * and + * + * * The MIT License + * http://opensource.org/licenses/MIT + * + * Vis.js may be distributed under either license. + */ +"use strict";!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.vis=e():t.vis=e()}(this,function(){return function(t){function e(o){if(i[o])return i[o].exports;var n=i[o]={i:o,l:!1,exports:{}};return t[o].call(n.exports,n,n.exports,e),n.l=!0,n.exports}var i={};return e.m=t,e.c=i,e.d=function(t,i,o){e.o(t,i)||Object.defineProperty(t,i,{configurable:!1,enumerable:!0,get:o})},e.n=function(t){var i=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(i,"a",i),i},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=123)}([function(t,e,i){e.__esModule=!0,e.default=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}},function(t,e,i){e.__esModule=!0;var o=i(169),n=function(t){return t&&t.__esModule?t:{default:t}}(o);e.default=function(){function t(t,e){for(var i=0;i2&&void 0!==arguments[2]&&arguments[2];for(var s in t)void 0!==i[s]&&(null===i[s]||"object"!==(0,c.default)(i[s])?n(t,i,s,o):"object"===(0,c.default)(t[s])&&e.fillIfDefined(t[s],i[s],o))},e.extend=function(t,e){for(var i=1;i3&&void 0!==arguments[3]&&arguments[3];if(Array.isArray(o))throw new TypeError("Arrays are not supported by deepExtend");for(var r=0;r3&&void 0!==arguments[3]&&arguments[3];if(Array.isArray(o))throw new TypeError("Arrays are not supported by deepExtend");for(var r in o)if(o.hasOwnProperty(r)&&-1===t.indexOf(r))if(o[r]&&o[r].constructor===Object)void 0===i[r]&&(i[r]={}),i[r].constructor===Object?e.deepExtend(i[r],o[r]):n(i,o,r,s);else if(Array.isArray(o[r])){i[r]=[];for(var a=0;a2&&void 0!==arguments[2]&&arguments[2],s=arguments.length>3&&void 0!==arguments[3]&&arguments[3];for(var r in i)if(i.hasOwnProperty(r)||!0===o)if(i[r]&&i[r].constructor===Object)void 0===t[r]&&(t[r]={}),t[r].constructor===Object?e.deepExtend(t[r],i[r],o):n(t,i,r,s);else if(Array.isArray(i[r])){t[r]=[];for(var a=0;a=0&&(e="DOMMouseScroll"),t.addEventListener(e,i,o)):t.attachEvent("on"+e,i)},e.removeEventListener=function(t,e,i,o){t.removeEventListener?(void 0===o&&(o=!1),"mousewheel"===e&&navigator.userAgent.indexOf("Firefox")>=0&&(e="DOMMouseScroll"),t.removeEventListener(e,i,o)):t.detachEvent("on"+e,i)},e.preventDefault=function(t){t||(t=window.event),t.preventDefault?t.preventDefault():t.returnValue=!1},e.getTarget=function(t){t||(t=window.event);var e;return t.target?e=t.target:t.srcElement&&(e=t.srcElement),void 0!=e.nodeType&&3==e.nodeType&&(e=e.parentNode),e},e.hasParent=function(t,e){for(var i=t;i;){if(i===e)return!0;i=i.parentNode}return!1},e.option={},e.option.asBoolean=function(t,e){return"function"==typeof t&&(t=t()),null!=t?0!=t:e||null},e.option.asNumber=function(t,e){return"function"==typeof t&&(t=t()),null!=t?Number(t)||e||null:e||null},e.option.asString=function(t,e){return"function"==typeof t&&(t=t()),null!=t?String(t):e||null},e.option.asSize=function(t,i){return"function"==typeof t&&(t=t()),e.isString(t)?t:e.isNumber(t)?t+"px":i||null},e.option.asElement=function(t,e){return"function"==typeof t&&(t=t()),t||e||null},e.hexToRGB=function(t){var e=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(e,function(t,e,i,o){return e+e+i+i+o+o});var i=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return i?{r:parseInt(i[1],16),g:parseInt(i[2],16),b:parseInt(i[3],16)}:null},e.overrideOpacity=function(t,i){var o;return-1!=t.indexOf("rgba")?t:-1!=t.indexOf("rgb")?(o=t.substr(t.indexOf("(")+1).replace(")","").split(","),"rgba("+o[0]+","+o[1]+","+o[2]+","+i+")"):(o=e.hexToRGB(t),null==o?t:"rgba("+o.r+","+o.g+","+o.b+","+i+")")},e.RGBToHex=function(t,e,i){return"#"+((1<<24)+(t<<16)+(e<<8)+i).toString(16).slice(1)},e.parseColor=function(t){var i;if(!0===e.isString(t)){if(!0===e.isValidRGB(t)){var o=t.substr(4).substr(0,t.length-5).split(",").map(function(t){return parseInt(t)});t=e.RGBToHex(o[0],o[1],o[2])}if(!0===e.isValidHex(t)){var n=e.hexToHSV(t),s={h:n.h,s:.8*n.s,v:Math.min(1,1.02*n.v)},r={h:n.h,s:Math.min(1,1.25*n.s),v:.8*n.v},a=e.HSVToHex(r.h,r.s,r.v),h=e.HSVToHex(s.h,s.s,s.v);i={background:t,border:a,highlight:{background:h,border:a},hover:{background:h,border:a}}}else i={background:t,border:t,highlight:{background:t,border:t},hover:{background:t,border:t}}}else i={},i.background=t.background||void 0,i.border=t.border||void 0,e.isString(t.highlight)?i.highlight={border:t.highlight,background:t.highlight}:(i.highlight={},i.highlight.background=t.highlight&&t.highlight.background||void 0,i.highlight.border=t.highlight&&t.highlight.border||void 0),e.isString(t.hover)?i.hover={border:t.hover,background:t.hover}:(i.hover={},i.hover.background=t.hover&&t.hover.background||void 0,i.hover.border=t.hover&&t.hover.border||void 0);return i},e.RGBToHSV=function(t,e,i){t/=255,e/=255,i/=255;var o=Math.min(t,Math.min(e,i)),n=Math.max(t,Math.max(e,i));if(o==n)return{h:0,s:0,v:o};var s=t==o?e-i:i==o?t-e:i-t;return{h:60*((t==o?3:i==o?1:5)-s/(n-o))/360,s:(n-o)/n,v:n}};var v={split:function(t){var e={};return t.split(";").forEach(function(t){if(""!=t.trim()){var i=t.split(":"),o=i[0].trim(),n=i[1].trim();e[o]=n}}),e},join:function(t){return(0,l.default)(t).map(function(e){return e+": "+t[e]}).join("; ")}};e.addCssText=function(t,i){var o=v.split(t.style.cssText),n=v.split(i),s=e.extend(o,n);t.style.cssText=v.join(s)},e.removeCssText=function(t,e){var i=v.split(t.style.cssText),o=v.split(e);for(var n in o)o.hasOwnProperty(n)&&delete i[n];t.style.cssText=v.join(i)},e.HSVToRGB=function(t,e,i){var o,n,s,r=Math.floor(6*t),a=6*t-r,h=i*(1-e),d=i*(1-a*e),l=i*(1-(1-a)*e);switch(r%6){case 0:o=i,n=l,s=h;break;case 1:o=d,n=i,s=h;break;case 2:o=h,n=i,s=l;break;case 3:o=h,n=d,s=i;break;case 4:o=l,n=h,s=i;break;case 5:o=i,n=h,s=d}return{r:Math.floor(255*o),g:Math.floor(255*n),b:Math.floor(255*s)}},e.HSVToHex=function(t,i,o){var n=e.HSVToRGB(t,i,o);return e.RGBToHex(n.r,n.g,n.b)},e.hexToHSV=function(t){var i=e.hexToRGB(t);return e.RGBToHSV(i.r,i.g,i.b)},e.isValidHex=function(t){return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(t)},e.isValidRGB=function(t){return t=t.replace(" ",""),/rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(t)},e.isValidRGBA=function(t){return t=t.replace(" ",""),/rgba\((\d{1,3}),(\d{1,3}),(\d{1,3}),(.{1,3})\)/i.test(t)},e.selectiveBridgeObject=function(t,i){if(null!==i&&"object"===(void 0===i?"undefined":(0,c.default)(i))){for(var o=(0,h.default)(i),n=0;n0&&e(o,t[n-1])<0;n--)t[n]=t[n-1];t[n]=o}return t},e.mergeOptions=function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},n=function(t){return null!==t&&void 0!==t},s=function(t){return null!==t&&"object"===(void 0===t?"undefined":(0,c.default)(t))};if(!s(t))throw new Error("Parameter mergeTarget must be an object");if(!s(e))throw new Error("Parameter options must be an object");if(!n(i))throw new Error("Parameter option must have a value");if(!s(o))throw new Error("Parameter globalOptions must be an object");var r=e[i],a=s(o)&&!function(t){for(var e in t)if(t.hasOwnProperty(e))return!1;return!0}(o),d=a?o[i]:void 0,l=d?d.enabled:void 0;if(void 0!==r){if("boolean"==typeof r)return s(t[i])||(t[i]={}),void(t[i].enabled=r);if(null===r&&!s(t[i])){if(!n(d))return;t[i]=(0,h.default)(d)}if(s(r)){var u=!0;void 0!==r.enabled?u=r.enabled:void 0!==l&&(u=d.enabled),function(t,e,i){s(t[i])||(t[i]={});var o=e[i],n=t[i];for(var r in o)o.hasOwnProperty(r)&&(n[r]=o[r])}(t,e,i),t[i].enabled=u}}},e.binarySearchCustom=function(t,e,i,o){for(var n=0,s=0,r=t.length-1;s<=r&&n<1e4;){var a=Math.floor((s+r)/2),h=t[a],d=void 0===o?h[i]:h[i][o],l=e(d);if(0==l)return a;-1==l?s=a+1:r=a-1,n++}return-1},e.binarySearchValue=function(t,e,i,o,n){var s,r,a,h,d=0,l=0,u=t.length-1;for(n=void 0!=n?n:function(t,e){return t==e?0:t0)return"before"==o?Math.max(0,h-1):h;if(n(r,e)<0&&n(a,e)>0)return"before"==o?h:Math.min(t.length-1,h+1);n(r,e)<0?l=h+1:u=h-1,d++}return-1},e.easingFunctions={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return t*(2-t)},easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return--t*t*t+1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return 1- --t*t*t*t},easeInOutQuart:function(t){return t<.5?8*t*t*t*t:1-8*--t*t*t*t},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return 1+--t*t*t*t*t},easeInOutQuint:function(t){return t<.5?16*t*t*t*t*t:1+16*--t*t*t*t*t}},e.getScrollBarWidth=function(){var t=document.createElement("p");t.style.width="100%",t.style.height="200px";var e=document.createElement("div");e.style.position="absolute",e.style.top="0px",e.style.left="0px",e.style.visibility="hidden",e.style.width="200px",e.style.height="150px",e.style.overflow="hidden",e.appendChild(t),document.body.appendChild(e);var i=t.offsetWidth;e.style.overflow="scroll";var o=t.offsetWidth;return i==o&&(o=e.clientWidth),document.body.removeChild(e),i-o},e.topMost=function(t,e){var i=void 0;Array.isArray(e)||(e=[e]);var o=!0,n=!1,s=void 0;try{for(var a,h=(0,r.default)(t);!(o=(a=h.next()).done);o=!0){var d=a.value;if(d){i=d[e[0]];for(var l=1;ln?1:or)&&(s=h,r=d)}return s},n.prototype.min=function(t){var e,i,o=this._data,n=(0,l.default)(o),s=null,r=null;for(e=0,i=n.length;e0?(o=e[t].redundant[0],e[t].redundant.shift()):(o=document.createElementNS("http://www.w3.org/2000/svg",t),i.appendChild(o)):(o=document.createElementNS("http://www.w3.org/2000/svg",t),e[t]={used:[],redundant:[]},i.appendChild(o)),e[t].used.push(o),o},e.getDOMElement=function(t,e,i,o){var n;return e.hasOwnProperty(t)?e[t].redundant.length>0?(n=e[t].redundant[0],e[t].redundant.shift()):(n=document.createElement(t),void 0!==o?i.insertBefore(n,o):i.appendChild(n)):(n=document.createElement(t),e[t]={used:[],redundant:[]},void 0!==o?i.insertBefore(n,o):i.appendChild(n)),e[t].used.push(n),n},e.drawPoint=function(t,i,o,n,s,r){var a;if("circle"==o.style?(a=e.getSVGElement("circle",n,s),a.setAttributeNS(null,"cx",t),a.setAttributeNS(null,"cy",i),a.setAttributeNS(null,"r",.5*o.size)):(a=e.getSVGElement("rect",n,s),a.setAttributeNS(null,"x",t-.5*o.size),a.setAttributeNS(null,"y",i-.5*o.size),a.setAttributeNS(null,"width",o.size),a.setAttributeNS(null,"height",o.size)),void 0!==o.styles&&a.setAttributeNS(null,"style",o.styles),a.setAttributeNS(null,"class",o.className+" vis-point"),r){var h=e.getSVGElement("text",n,s);r.xOffset&&(t+=r.xOffset),r.yOffset&&(i+=r.yOffset),r.content&&(h.textContent=r.content),r.className&&h.setAttributeNS(null,"class",r.className+" vis-label"),h.setAttributeNS(null,"x",t),h.setAttributeNS(null,"y",i)}return a},e.drawBar=function(t,i,o,n,s,r,a,h){if(0!=n){n<0&&(n*=-1,i-=n);var d=e.getSVGElement("rect",r,a);d.setAttributeNS(null,"x",t-.5*o),d.setAttributeNS(null,"y",i),d.setAttributeNS(null,"width",o),d.setAttributeNS(null,"height",n),d.setAttributeNS(null,"class",s),h&&d.setAttributeNS(null,"style",h)}}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0}),e.printStyle=void 0;var n=i(19),s=o(n),r=i(6),a=o(r),h=i(8),d=o(h),l=i(0),u=o(l),c=i(1),p=o(c),f=i(2),m=!1,v=void 0,g="background: #FFeeee; color: #dd0000",y=function(){function t(){(0,u.default)(this,t)}return(0,p.default)(t,null,[{key:"validate",value:function(e,i,o){m=!1,v=i;var n=i;return void 0!==o&&(n=i[o]),t.parse(e,n,[]),m}},{key:"parse",value:function(e,i,o){for(var n in e)e.hasOwnProperty(n)&&t.check(n,e,i,o)}},{key:"check",value:function(e,i,o,n){if(void 0===o[e]&&void 0===o.__any__)return void t.getSuggestion(e,o,n);var s=e,r=!0;void 0===o[e]&&void 0!==o.__any__&&(s="__any__",r="object"===t.getType(i[e]));var a=o[s];r&&void 0!==a.__type__&&(a=a.__type__),t.checkFields(e,i,o,s,a,n)}},{key:"checkFields",value:function(e,i,o,n,s,r){var a=function(i){console.log("%c"+i+t.printLocation(r,e),g)},h=t.getType(i[e]),l=s[h];void 0!==l?"array"===t.getType(l)&&-1===l.indexOf(i[e])?(a('Invalid option detected in "'+e+'". Allowed values are:'+t.print(l)+' not "'+i[e]+'". '),m=!0):"object"===h&&"__any__"!==n&&(r=f.copyAndExtendArray(r,e),t.parse(i[e],o[n],r)):void 0===s.any&&(a('Invalid type received for "'+e+'". Expected: '+t.print((0,d.default)(s))+". Received ["+h+'] "'+i[e]+'"'),m=!0)}},{key:"getType",value:function(t){var e=void 0===t?"undefined":(0,a.default)(t);return"object"===e?null===t?"null":t instanceof Boolean?"boolean":t instanceof Number?"number":t instanceof String?"string":Array.isArray(t)?"array":t instanceof Date?"date":void 0!==t.nodeType?"dom":!0===t._isAMomentObject?"moment":"object":"number"===e?"number":"boolean"===e?"boolean":"string"===e?"string":void 0===e?"undefined":e}},{key:"getSuggestion",value:function(e,i,o){var n=t.findInOptions(e,i,o,!1),s=t.findInOptions(e,v,[],!0),r=void 0 +;r=void 0!==n.indexMatch?" in "+t.printLocation(n.path,e,"")+'Perhaps it was incomplete? Did you mean: "'+n.indexMatch+'"?\n\n':s.distance<=4&&n.distance>s.distance?" in "+t.printLocation(n.path,e,"")+"Perhaps it was misplaced? Matching option found at: "+t.printLocation(s.path,s.closestMatch,""):n.distance<=8?'. Did you mean "'+n.closestMatch+'"?'+t.printLocation(n.path,e):". Did you mean one of these: "+t.print((0,d.default)(i))+t.printLocation(o,e),console.log('%cUnknown option detected: "'+e+'"'+r,g),m=!0}},{key:"findInOptions",value:function(e,i,o){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3],s=1e9,r="",a=[],h=e.toLowerCase(),d=void 0;for(var l in i){var u=void 0;if(void 0!==i[l].__type__&&!0===n){var c=t.findInOptions(e,i[l],f.copyAndExtendArray(o,l));s>c.distance&&(r=c.closestMatch,a=c.path,s=c.distance,d=c.indexMatch)}else-1!==l.toLowerCase().indexOf(h)&&(d=l),u=t.levenshteinDistance(e,l),s>u&&(r=l,a=f.copyArray(o),s=u)}return{closestMatch:r,path:a,distance:s,indexMatch:d}}},{key:"printLocation",value:function(t,e){for(var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Problem value found at: \n",o="\n\n"+i+"options = {\n",n=0;n0&&(this.enableBorderDashes(t,e),t.stroke(),this.disableBorderDashes(t,e)),t.restore()}},{key:"performFill",value:function(t,e){this.enableShadow(t,e),t.fill(),this.disableShadow(t,e),this.performStroke(t,e)}},{key:"_addBoundingBoxMargin",value:function(t){this.boundingBox.left-=t,this.boundingBox.top-=t,this.boundingBox.bottom+=t,this.boundingBox.right+=t}},{key:"_updateBoundingBox",value:function(t,e,i,o,n){void 0!==i&&this.resize(i,o,n),this.left=t-this.width/2,this.top=e-this.height/2,this.boundingBox.left=this.left,this.boundingBox.top=this.top,this.boundingBox.bottom=this.top+this.height,this.boundingBox.right=this.left+this.width}},{key:"updateBoundingBox",value:function(t,e,i,o,n){this._updateBoundingBox(t,e,i,o,n)}},{key:"getDimensionsFromLabel",value:function(t,e,i){this.textSize=this.labelModule.getTextSize(t,e,i);var o=this.textSize.width,n=this.textSize.height;return 0===o&&(o=14,n=14),{width:o,height:n}}}]),t}();e.default=l},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(23),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{size:this.options.size};if(this.needsRefresh(e,i)){this.labelModule.getTextSize(t,e,i);var n=2*o.size;this.width=n,this.height=n,this.radius=.5*this.width}}},{key:"_drawShape",value:function(t,e,i,o,n,s,r,a){if(this.resize(t,s,r,a),this.left=o-this.width/2,this.top=n-this.height/2,this.initContextForDraw(t,a),t[e](o,n,a.size),this.performFill(t,a),void 0!==this.options.label){this.labelModule.calculateLabelSize(t,s,r,o,n,"hanging");var h=n+.5*this.height+.5*this.labelModule.size.height;this.labelModule.draw(t,o,h,s,r,"hanging")}this.updateBoundingBox(o,n)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size,void 0!==this.options.label&&this.labelModule.size.width>0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height))}}]),e}(m.default);e.default=v},function(t,e,i){var o=i(78),n=i(51);t.exports=function(t){return o(n(t))}},function(t,e,i){var o=i(20),n=i(39);t.exports=i(21)?function(t,e,i){return o.f(t,e,n(1,i))}:function(t,e,i){return t[e]=i,t}},function(t,e,i){var o=i(32);t.exports=function(t){if(!o(t))throw TypeError(t+" is not an object!");return t}},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e,i){t.exports={default:i(138),__esModule:!0}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}e.__esModule=!0;var n=i(188),s=o(n),r=i(77),a=o(r);e.default=function(){function t(t,e){var i=[],o=!0,n=!1,s=void 0;try{for(var r,h=(0,a.default)(t);!(o=(r=h.next()).done)&&(i.push(r.value),!e||i.length!==e);o=!0);}catch(t){n=!0,s=t}finally{try{!o&&h.return&&h.return()}finally{if(n)throw s}}return i}return function(e,i){if(Array.isArray(e))return e;if((0,s.default)(Object(e)))return t(e,i);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}()},function(t,e){t.exports={}},function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,e,i){var o=i(84),n=i(58);t.exports=Object.keys||function(t){return o(t,n)}},function(t,e,i){function o(t,e,i){this.x=void 0!==t?t:0,this.y=void 0!==e?e:0,this.z=void 0!==i?i:0}o.subtract=function(t,e){var i=new o;return i.x=t.x-e.x,i.y=t.y-e.y,i.z=t.z-e.z,i},o.add=function(t,e){var i=new o;return i.x=t.x+e.x,i.y=t.y+e.y,i.z=t.z+e.z,i},o.avg=function(t,e){return new o((t.x+e.x)/2,(t.y+e.y)/2,(t.z+e.z)/2)},o.crossProduct=function(t,e){var i=new o;return i.x=t.y*e.z-t.z*e.y,i.y=t.z*e.x-t.x*e.z,i.z=t.x*e.y-t.y*e.x,i},o.prototype.length=function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},t.exports=o},function(t,e,i){var o,n,s;!function(i,r){n=[],o=r,void 0!==(s="function"==typeof o?o.apply(e,n):o)&&(t.exports=s)}(0,function(){function t(t){var e,i=t&&t.preventDefault||!1,o=t&&t.container||window,n={},s={keydown:{},keyup:{}},r={};for(e=97;e<=122;e++)r[String.fromCharCode(e)]={code:e-97+65,shift:!1};for(e=65;e<=90;e++)r[String.fromCharCode(e)]={code:e,shift:!0};for(e=0;e<=9;e++)r[""+e]={code:48+e,shift:!1};for(e=1;e<=12;e++)r["F"+e]={code:111+e,shift:!1};for(e=0;e<=9;e++)r["num"+e]={code:96+e,shift:!1};r["num*"]={code:106,shift:!1},r["num+"]={code:107,shift:!1},r["num-"]={code:109,shift:!1},r["num/"]={code:111,shift:!1},r["num."]={code:110,shift:!1},r.left={code:37,shift:!1},r.up={code:38,shift:!1},r.right={code:39,shift:!1},r.down={code:40,shift:!1},r.space={code:32,shift:!1},r.enter={code:13,shift:!1},r.shift={code:16,shift:void 0},r.esc={code:27,shift:!1},r.backspace={code:8,shift:!1},r.tab={code:9,shift:!1},r.ctrl={code:17,shift:!1},r.alt={code:18,shift:!1},r.delete={code:46,shift:!1},r.pageup={code:33,shift:!1},r.pagedown={code:34,shift:!1},r["="]={code:187,shift:!1},r["-"]={code:189,shift:!1},r["]"]={code:221,shift:!1},r["["]={code:219,shift:!1};var a=function(t){d(t,"keydown")},h=function(t){d(t,"keyup")},d=function(t,e){if(void 0!==s[e][t.keyCode]){for(var o=s[e][t.keyCode],n=0;n=4*a){var c=0,p=s.clone();switch(o[h].repeat){case"daily":d.day()!=l.day()&&(c=1),d.dayOfYear(n.dayOfYear()),d.year(n.year()),d.subtract(7,"days"),l.dayOfYear(n.dayOfYear()),l.year(n.year()),l.subtract(7-c,"days"),p.add(1,"weeks");break;case"weekly":var f=l.diff(d,"days"),m=d.day();d.date(n.date()),d.month(n.month()),d.year(n.year()),l=d.clone(),d.day(m),l.day(m),l.add(f,"days"),d.subtract(1,"weeks"),l.subtract(1,"weeks"),p.add(1,"weeks");break;case"monthly":d.month()!=l.month()&&(c=1),d.month(n.month()),d.year(n.year()),d.subtract(1,"months"),l.month(n.month()),l.year(n.year()),l.subtract(1,"months"),l.add(c,"months"),p.add(1,"months");break;case"yearly":d.year()!=l.year()&&(c=1),d.year(n.year()),d.subtract(1,"years"),l.year(n.year()),l.subtract(1,"years"),l.add(c,"years"),p.add(1,"years");break;default:return void console.log("Wrong repeat format, allowed are: daily, weekly, monthly, yearly. Given:",o[h].repeat)}for(;d=e[o].start&&e[n].end<=e[o].end?e[n].remove=!0:e[n].start>=e[o].start&&e[n].start<=e[o].end?(e[o].end=e[n].end,e[n].remove=!0):e[n].end>=e[o].start&&e[n].end<=e[o].end&&(e[o].start=e[n].start,e[n].remove=!0));for(o=0;o=r&&nt.range.end){var h={start:t.range.start,end:i};return i=e.correctTimeForHidden(t.options.moment,t.body.hiddenDates,h,i),n=t.range.conversion(o,r),(i.valueOf()-n.offset)*n.scale}return i=e.correctTimeForHidden(t.options.moment,t.body.hiddenDates,t.range,i),n=t.range.conversion(o,r),(i.valueOf()-n.offset)*n.scale},e.toTime=function(t,i,o){if(0==t.body.hiddenDates.length){var n=t.range.conversion(o);return new Date(i/n.scale+n.offset)}var s=e.getHiddenDurationBetween(t.body.hiddenDates,t.range.start,t.range.end),r=t.range.end-t.range.start-s,a=r*i/o,h=e.getAccumulatedHiddenDuration(t.body.hiddenDates,t.range,a);return new Date(h+a+t.range.start)},e.getHiddenDurationBetween=function(t,e,i){for(var o=0,n=0;n=e&&r=e&&r<=i&&(o+=r-s)}return o},e.correctTimeForHidden=function(t,i,o,n){return n=t(n).toDate().valueOf(),n-=e.getHiddenDurationBefore(t,i,o,n)},e.getHiddenDurationBefore=function(t,e,i,o){var n=0;o=t(o).toDate().valueOf();for(var s=0;s=i.start&&a=a&&(n+=a-r)}return n},e.getAccumulatedHiddenDuration=function(t,e,i){for(var o=0,n=0,s=e.start,r=0;r=e.start&&h=i)break;o+=h-a}}return o},e.snapAwayFromHidden=function(t,i,o,n){var s=e.isHidden(i,t);return 1==s.hidden?o<0?1==n?s.startDate-(s.endDate-i)-1:s.startDate-1:1==n?s.endDate+(i-s.startDate)+1:s.endDate+1:i},e.isHidden=function(t,e){for(var i=0;i=o&&t0){var e=[];if(Array.isArray(this.options.dataAttributes))e=this.options.dataAttributes;else{if("all"!=this.options.dataAttributes)return;e=(0,h.default)(this.data)}for(var i=0;ithis.max&&this.flush(),clearTimeout(this._timeout),this.queue.length>0&&"number"==typeof this.delay){var t=this;this._timeout=setTimeout(function(){t.flush()},this.delay)}},o.prototype.flush=function(){for(;this._queue.length>0;){var t=this._queue.shift();t.fn.apply(t.context||t.fn,t.args||[])}},t.exports=o},function(t,e){function i(t){if(t)return o(t)}function o(t){for(var e in i.prototype)t[e]=i.prototype[e];return t}t.exports=i,i.prototype.on=i.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks[t]=this._callbacks[t]||[]).push(e),this},i.prototype.once=function(t,e){function i(){o.off(t,i),e.apply(this,arguments)}var o=this;return this._callbacks=this._callbacks||{},i.fn=e,this.on(t,i),this},i.prototype.off=i.prototype.removeListener=i.prototype.removeAllListeners=i.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var i=this._callbacks[t];if(!i)return this;if(1==arguments.length)return delete this._callbacks[t],this;for(var o,n=0;n=.4*v}if(this.options.showMinorLabels&&m){var k=this._repaintMinorText(c,y,t,b);k.style.width=_+"px"}f&&this.options.showMajorLabels?(c>0&&(void 0==w&&(w=c),k=this._repaintMajorText(c,s.getLabelMajor(),t,b)),g=this._repaintMajorLine(c,_,t,b)):m?g=this._repaintMinorLine(c,_,t,b):g&&(g.style.width=parseInt(g.style.width)+_+"px")}if(1e3!==x||u||(console.warn("Something is wrong with the Timeline scale. Limited drawing of grid lines to 1000 lines."),u=!0),this.options.showMajorLabels){var S=this.body.util.toTime(0),D=s.getLabelMajor(S),M=D.length*(this.props.majorCharWidth||10)+10;(void 0==w||Mt.left&&this.shape.topt.top}},{key:"isBoundingBoxOverlappingWith",value:function(t){return this.shape.boundingBox.leftt.left&&this.shape.boundingBox.topt.top}}],[{key:"updateGroupOptions",value:function(t,e,i){if(void 0!==i){var o=t.group;if(void 0!==e&&void 0!==e.group&&o!==e.group)throw new Error("updateGroupOptions: group values in options don't match.");if("number"==typeof o||"string"==typeof o&&""!=o){var n=i.get(o);h.selectiveNotDeepExtend(["font"],t,n),t.color=h.parseColor(t.color)}}}},{key:"parseOptions",value:function(e,i){var o=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},s=arguments[4],r=["color","fixed","shadow"];if(h.selectiveNotDeepExtend(r,e,i,o),t.checkMass(i),h.mergeOptions(e,i,"shadow",n),void 0!==i.color&&null!==i.color){var a=h.parseColor(i.color);h.fillIfDefined(e.color,a)}else!0===o&&null===i.color&&(e.color=h.bridgeObject(n.color));void 0!==i.fixed&&null!==i.fixed&&("boolean"==typeof i.fixed?(e.fixed.x=i.fixed,e.fixed.y=i.fixed):(void 0!==i.fixed.x&&"boolean"==typeof i.fixed.x&&(e.fixed.x=i.fixed.x),void 0!==i.fixed.y&&"boolean"==typeof i.fixed.y&&(e.fixed.y=i.fixed.y))),!0===o&&null===i.font&&(e.font=h.bridgeObject(n.font)),t.updateGroupOptions(e,i,s),void 0!==i.scaling&&h.mergeOptions(e.scaling,i.scaling,"label",n.scaling)}},{key:"checkMass",value:function(t,e){if(void 0!==t.mass&&t.mass<=0){var i="";void 0!==e&&(i=" in node id: "+e),console.log("%cNegative or zero mass disallowed"+i+", setting mass to 1.",C),t.mass=1}}}]),t}();e.default=O},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(6),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(2),u=function(){function t(){(0,a.default)(this,t)}return(0,d.default)(t,null,[{key:"choosify",value:function(t,e){var i=["node","edge","label"],o=!0,n=l.topMost(e,"chosen");if("boolean"==typeof n)o=n;else if("object"===(void 0===n?"undefined":(0,s.default)(n))){if(-1===i.indexOf(t))throw new Error("choosify: subOption '"+t+"' should be one of '"+i.join("', '")+"'");var r=l.topMost(e,["chosen",t]);"boolean"!=typeof r&&"function"!=typeof r||(o=r)}return o}},{key:"pointInRect",value:function(t,e,i){if(t.width<=0||t.height<=0)return!1;if(void 0!==i){var o={x:e.x-i.x,y:e.y-i.y};if(0!==i.angle){var n=-i.angle;e={x:Math.cos(n)*o.x-Math.sin(n)*o.y,y:Math.sin(n)*o.x+Math.cos(n)*o.y}}else e=o}var s=t.x+t.width,r=t.y+t.width;return t.lefte.x&&t.tope.y}},{key:"isValidLabel",value:function(t){return"string"==typeof t&&""!==t}}]),t}();e.default=u},function(t,e,i){i(125);for(var o=i(18),n=i(26),s=i(31),r=i(13)("toStringTag"),a="CSSRuleList,CSSStyleDeclaration,CSSValueList,ClientRectList,DOMRectList,DOMStringList,DOMTokenList,DataTransferItemList,FileList,HTMLAllCollection,HTMLCollection,HTMLFormElement,HTMLSelectElement,MediaList,MimeTypeArray,NamedNodeMap,NodeList,PaintRequestList,Plugin,PluginArray,SVGLengthList,SVGNumberList,SVGPathSegList,SVGPointList,SVGStringList,SVGTransformList,SourceBufferList,StyleSheetList,TextTrackCueList,TextTrackList,TouchList".split(","),h=0;hdocument.F=Object<\/script>"),t.close(),h=t.F;o--;)delete h.prototype[s[o]];return h()};t.exports=Object.create||function(t,e){var i;return null!==t?(a.prototype=o(t),i=new a,a.prototype=null,i[r]=t):i=h(),void 0===e?i:n(i,e)}},function(t,e){var i=Math.ceil,o=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?o:i)(t)}},function(t,e,i){var o=i(57)("keys"),n=i(40);t.exports=function(t){return o[t]||(o[t]=n(t))}},function(t,e,i){var o=i(18),n=o["__core-js_shared__"]||(o["__core-js_shared__"]={});t.exports=function(t){return n[t]||(n[t]={})}},function(t,e){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,e,i){var o=i(20).f,n=i(22),s=i(13)("toStringTag");t.exports=function(t,e,i){t&&!n(t=i?t:t.prototype,s)&&o(t,s,{configurable:!0,value:e})}},function(t,e,i){var o=i(135)(!0);i(79)(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,e=this._t,i=this._i;return i>=e.length?{value:void 0,done:!0}:(t=o(e,i),this._i+=t.length,{value:t,done:!1})})},function(t,e,i){e.f=i(13)},function(t,e,i){var o=i(18),n=i(7),s=i(52),r=i(61),a=i(20).f;t.exports=function(t){var e=n.Symbol||(n.Symbol=s?{}:o.Symbol||{});"_"==t.charAt(0)||t in e||a(e,t,{value:r.f(t)})}},function(t,e){e.f=Object.getOwnPropertySymbols},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(t,e){var i=p().hours(0).minutes(0).seconds(0).milliseconds(0),o=i.clone().add(-3,"days").valueOf(),n=i.clone().add(3,"days").valueOf();this.millisecondsPerPixelCache=void 0,void 0===e?(this.start=o,this.end=n):(this.start=e.start||o,this.end=e.end||n),this.rolling=!1,this.body=t,this.deltaDifference=0,this.scaleOffset=0,this.startToFront=!1,this.endToFront=!0,this.defaultOptions={rtl:!1,start:null,end:null,moment:p,direction:"horizontal",moveable:!0,zoomable:!0,min:null,max:null,zoomMin:10,zoomMax:31536e10,rollingMode:{follow:!1,offset:.5}},this.options=c.extend({},this.defaultOptions),this.props={touch:{}},this.animationTimer=null,this.body.emitter.on("panstart",this._onDragStart.bind(this)),this.body.emitter.on("panmove",this._onDrag.bind(this)),this.body.emitter.on("panend",this._onDragEnd.bind(this)),this.body.emitter.on("mousewheel",this._onMouseWheel.bind(this)),this.body.emitter.on("touch",this._onTouch.bind(this)),this.body.emitter.on("pinch",this._onPinch.bind(this)),this.body.dom.rollingModeBtn.addEventListener("click",this.startRolling.bind(this)),this.setOptions(e)}function s(t){if("horizontal"!=t&&"vertical"!=t)throw new TypeError('Unknown direction "'+t+'". Choose "horizontal" or "vertical".')}var r=i(8),a=o(r),h=i(19),d=o(h),l=i(6),u=o(l),c=i(2),p=i(9),f=i(16),m=i(36);n.prototype=new f,n.prototype.setOptions=function(t){if(t){var e=["animation","direction","min","max","zoomMin","zoomMax","moveable","zoomable","moment","activate","hiddenDates","zoomKey","rtl","showCurrentTime","rollingMode","horizontalScroll"];c.selectiveExtend(e,this.options,t),t.rollingMode&&t.rollingMode.follow&&this.startRolling(),("start"in t||"end"in t)&&this.setRange(t.start,t.end)}},n.prototype.startRolling=function(){function t(){e.stopRolling(),e.rolling=!0;var i=e.end-e.start,o=c.convert(new Date,"Date").valueOf(),n=o-i*e.options.rollingMode.offset,s=o+i*(1-e.options.rollingMode.offset),r={animation:!1};e.setRange(n,s,r),i=1/e.conversion(e.body.domProps.center.width).scale/10,i<30&&(i=30),i>1e3&&(i=1e3),e.body.dom.rollingModeBtn.style.visibility="hidden",e.currentTimeTimer=setTimeout(t,i)}var e=this;t()},n.prototype.stopRolling=function(){void 0!==this.currentTimeTimer&&(clearTimeout(this.currentTimeTimer),this.rolling=!1,this.body.dom.rollingModeBtn.style.visibility="visible")},n.prototype.setRange=function(t,e,i,o,n){i||(i={}),!0!==i.byUser&&(i.byUser=!1);var s=this,r=void 0!=t?c.convert(t,"Date").valueOf():null,h=void 0!=e?c.convert(e,"Date").valueOf():null;if(this._cancelAnimation(),this.millisecondsPerPixelCache=void 0,i.animation){var l=this.start,p=this.end,f="object"===(0,u.default)(i.animation)&&"duration"in i.animation?i.animation.duration:500,v="object"===(0,u.default)(i.animation)&&"easingFunction"in i.animation?i.animation.easingFunction:"easeInOutQuad",g=c.easingFunctions[v];if(!g)throw new Error("Unknown easing function "+(0,d.default)(v)+". Choose from: "+(0,a.default)(c.easingFunctions).join(", "));var y=(new Date).valueOf(),b=!1;return function t(){if(!s.props.touch.dragging){var e=(new Date).valueOf(),a=e-y,d=g(a/f),u=a>f,c=u||null===r?r:l+(r-l)*d,v=u||null===h?h:p+(h-p)*d;_=s._applyRange(c,v),m.updateHiddenDates(s.options.moment,s.body,s.options.hiddenDates),b=b||_;var w={start:new Date(s.start),end:new Date(s.end),byUser:i.byUser,event:i.event};if(n&&n(d,_,u),_&&s.body.emitter.emit("rangechange",w),u){if(b&&(s.body.emitter.emit("rangechanged",w),o))return o()}else s.animationTimer=setTimeout(t,20)}}()}var _=this._applyRange(r,h);if(m.updateHiddenDates(this.options.moment,this.body,this.options.hiddenDates),_){var w={start:new Date(this.start),end:new Date(this.end),byUser:i.byUser,event:i.event};if(this.body.emitter.emit("rangechange",w),clearTimeout(s.timeoutID),s.timeoutID=setTimeout(function(){s.body.emitter.emit("rangechanged",w)},200),o)return o()}},n.prototype.getMillisecondsPerPixel=function(){return void 0===this.millisecondsPerPixelCache&&(this.millisecondsPerPixelCache=(this.end-this.start)/this.body.dom.center.clientWidth),this.millisecondsPerPixelCache},n.prototype._cancelAnimation=function(){this.animationTimer&&(clearTimeout(this.animationTimer),this.animationTimer=null)},n.prototype._applyRange=function(t,e){var i,o=null!=t?c.convert(t,"Date").valueOf():this.start,n=null!=e?c.convert(e,"Date").valueOf():this.end,s=null!=this.options.max?c.convert(this.options.max,"Date").valueOf():null,r=null!=this.options.min?c.convert(this.options.min,"Date").valueOf():null;if(isNaN(o)||null===o)throw new Error('Invalid start "'+t+'"');if(isNaN(n)||null===n)throw new Error('Invalid end "'+e+'"');if(ns&&(n=s)),null!==s&&n>s&&(i=n-s,o-=i,n-=i,null!=r&&o=this.start-.5&&n<=this.end?(o=this.start,n=this.end):(i=a-(n-o),o-=i/2,n+=i/2)}}if(null!==this.options.zoomMax){var h=parseFloat(this.options.zoomMax);h<0&&(h=0),n-o>h&&(this.end-this.start===h&&othis.end?(o=this.start,n=this.end):(i=n-o-h,o+=i/2,n-=i/2))}var d=this.start!=o||this.end!=n;return o>=this.start&&o<=this.end||n>=this.start&&n<=this.end||this.start>=o&&this.start<=n||this.end>=o&&this.end<=n||this.body.emitter.emit("checkRangedItems"),this.start=o,this.end=n,d},n.prototype.getRange=function(){return{start:this.start,end:this.end}},n.prototype.conversion=function(t,e){return n.conversion(this.start,this.end,t,e)},n.conversion=function(t,e,i,o){return void 0===o&&(o=0),0!=i&&e-t!=0?{offset:t,scale:i/(e-t-o)}:{offset:0,scale:1}},n.prototype._onDragStart=function(t){this.deltaDifference=0,this.previousDelta=0,this.options.moveable&&this._isInsideRange(t)&&this.props.touch.allowDragging&&(this.stopRolling(),this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.dragging=!0,this.body.dom.root&&(this.body.dom.root.style.cursor="move"))},n.prototype._onDrag=function(t){if(t&&this.props.touch.dragging&&this.options.moveable&&this.props.touch.allowDragging){var e=this.options.direction;s(e);var i="horizontal"==e?t.deltaX:t.deltaY;i-=this.deltaDifference;var o=this.props.touch.end-this.props.touch.start;o-=m.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end);var n,r="horizontal"==e?this.body.domProps.center.width:this.body.domProps.center.height;n=this.options.rtl?i/r*o:-i/r*o;var a=this.props.touch.start+n,h=this.props.touch.end+n,d=m.snapAwayFromHidden(this.body.hiddenDates,a,this.previousDelta-i,!0),l=m.snapAwayFromHidden(this.body.hiddenDates,h,this.previousDelta-i,!0);if(d!=a||l!=h)return this.deltaDifference+=i,this.props.touch.start=d,this.props.touch.end=l,void this._onDrag(t);this.previousDelta=i,this._applyRange(a,h);var u=new Date(this.start),c=new Date(this.end);this.body.emitter.emit("rangechange",{start:u,end:c,byUser:!0,event:t}),this.body.emitter.emit("panmove")}},n.prototype._onDragEnd=function(t){this.props.touch.dragging&&this.options.moveable&&this.props.touch.allowDragging&&(this.props.touch.dragging=!1,this.body.dom.root&&(this.body.dom.root.style.cursor="auto"),this.body.emitter.emit("rangechanged",{start:new Date(this.start),end:new Date(this.end),byUser:!0,event:t}))},n.prototype._onMouseWheel=function(t){var e=0;if(t.wheelDelta?e=t.wheelDelta/120:t.detail&&(e=-t.detail/3),!(this.options.zoomKey&&!t[this.options.zoomKey]&&this.options.zoomable||!this.options.zoomable&&this.options.moveable)&&this.options.zoomable&&this.options.moveable&&this._isInsideRange(t)&&e){var i;i=e<0?1-e/5:1/(1+e/5);var o;if(this.rolling)o=this.start+(this.end-this.start)*this.options.rollingMode.offset;else{var n=this.getPointer({x:t.clientX,y:t.clientY},this.body.dom.center);o=this._pointerToDate(n)}this.zoom(i,o,e,t),t.preventDefault()}},n.prototype._onTouch=function(t){this.props.touch.start=this.start,this.props.touch.end=this.end,this.props.touch.allowDragging=!0,this.props.touch.center=null,this.scaleOffset=0,this.deltaDifference=0,c.preventDefault(t)},n.prototype._onPinch=function(t){if(this.options.zoomable&&this.options.moveable){c.preventDefault(t),this.props.touch.allowDragging=!1,this.props.touch.center||(this.props.touch.center=this.getPointer(t.center,this.body.dom.center)),this.stopRolling();var e=1/(t.scale+this.scaleOffset),i=this._pointerToDate(this.props.touch.center),o=m.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end),n=m.getHiddenDurationBefore(this.options.moment,this.body.hiddenDates,this,i),s=o-n,r=i-n+(this.props.touch.start-(i-n))*e,a=i+s+(this.props.touch.end-(i+s))*e;this.startToFront=1-e<=0,this.endToFront=e-1<=0;var h=m.snapAwayFromHidden(this.body.hiddenDates,r,1-e,!0),d=m.snapAwayFromHidden(this.body.hiddenDates,a,e-1,!0);h==r&&d==a||(this.props.touch.start=h,this.props.touch.end=d,this.scaleOffset=1-t.scale,r=h,a=d);var l={animation:!1,byUser:!0,event:t};this.setRange(r,a,l),this.startToFront=!1,this.endToFront=!0}},n.prototype._isInsideRange=function(t){var e,i=t.center?t.center.x:t.clientX;e=this.options.rtl?i-c.getAbsoluteLeft(this.body.dom.centerContainer):c.getAbsoluteRight(this.body.dom.centerContainer)-i;var o=this.body.util.toTime(e);return o>=this.start&&o<=this.end},n.prototype._pointerToDate=function(t){var e,i=this.options.direction;if(s(i),"horizontal"==i)return this.body.util.toTime(t.x).valueOf();var o=this.body.domProps.center.height;return e=this.conversion(o),t.y/e.scale+e.offset},n.prototype.getPointer=function(t,e){return this.options.rtl?{x:c.getAbsoluteRight(e)-t.x,y:t.y-c.getAbsoluteTop(e)}:{x:t.x-c.getAbsoluteLeft(e),y:t.y-c.getAbsoluteTop(e)}},n.prototype.zoom=function(t,e,i,o){null==e&&(e=(this.start+this.end)/2);var n=m.getHiddenDurationBetween(this.body.hiddenDates,this.start,this.end),s=m.getHiddenDurationBefore(this.options.moment,this.body.hiddenDates,this,e),r=n-s,a=e-s+(this.start-(e-s))*t,h=e+r+(this.end-(e+r))*t;this.startToFront=!(i>0),this.endToFront=!(-i>0) +;var d=m.snapAwayFromHidden(this.body.hiddenDates,a,i,!0),l=m.snapAwayFromHidden(this.body.hiddenDates,h,-i,!0);d==a&&l==h||(a=d,h=l);var u={animation:!1,byUser:!0,event:o};this.setRange(a,h,u),this.startToFront=!1,this.endToFront=!0},n.prototype.move=function(t){var e=this.end-this.start,i=this.start+e*t,o=this.end+e*t;this.start=i,this.end=o},n.prototype.moveTo=function(t){var e=(this.start+this.end)/2,i=e-t,o=this.start-i,n=this.end-i,s={animation:!1,byUser:!0,event:null};this.setRange(o,n,s)},t.exports=n},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(){}var s=i(19),r=o(s),a=i(6),h=o(a),d=i(44),l=i(10),u=i(37),c=i(2),p=i(45),f=i(97),m=i(36),v=i(46);d(n.prototype),n.prototype._create=function(t){function e(t){this.isActive()&&this.emit("mousewheel",t);var e=0,i=0;if("detail"in t&&(i=-1*t.detail),"wheelDelta"in t&&(i=t.wheelDelta),"wheelDeltaY"in t&&(i=t.wheelDeltaY),"wheelDeltaX"in t&&(e=-1*t.wheelDeltaX),"axis"in t&&t.axis===t.HORIZONTAL_AXIS&&(e=-1*i,i=0),"deltaY"in t&&(i=-1*t.deltaY),"deltaX"in t&&(e=t.deltaX),this.options.zoomKey&&!t[this.options.zoomKey])if(t.preventDefault(),this.options.verticalScroll&&Math.abs(i)>=Math.abs(e)){var o=this.props.scrollTop,n=o+i;this.isActive()&&(this._setScrollTop(n),this._redraw(),this.emit("scroll",t))}else if(this.options.horizontalScroll){var s=Math.abs(e)>=Math.abs(i)?e:i,r=s/120*(this.range.end-this.range.start)/20,a=this.range.start+r,h=this.range.end+r,d={animation:!1,byUser:!0,event:t};this.range.setRange(a,h,d)}}function i(t){if(s.options.verticalScroll&&(t.preventDefault(),s.isActive())){var e=-t.target.scrollTop;s._setScrollTop(e),s._redraw(),s.emit("scrollSide",t)}}function o(t){if(t.preventDefault&&t.preventDefault(),!(!t.target.className.indexOf("vis")>-1||a))return t.dataTransfer.dropEffect="move",a=!0,!1}function n(t){t.preventDefault&&t.preventDefault(),t.stopPropagation&&t.stopPropagation();try{var e=JSON.parse(t.dataTransfer.getData("text"));if(!e||!e.content)return}catch(t){return!1}return a=!1,t.center={x:t.clientX,y:t.clientY},"item"!==e.target?s.itemSet._onAddItem(t):s.itemSet._onDropObjectOnItem(t),s.emit("drop",s.getEventProperties(t)),!1}this.dom={},this.dom.container=t,this.dom.root=document.createElement("div"),this.dom.background=document.createElement("div"),this.dom.backgroundVertical=document.createElement("div"),this.dom.backgroundHorizontal=document.createElement("div"),this.dom.centerContainer=document.createElement("div"),this.dom.leftContainer=document.createElement("div"),this.dom.rightContainer=document.createElement("div"),this.dom.center=document.createElement("div"),this.dom.left=document.createElement("div"),this.dom.right=document.createElement("div"),this.dom.top=document.createElement("div"),this.dom.bottom=document.createElement("div"),this.dom.shadowTop=document.createElement("div"),this.dom.shadowBottom=document.createElement("div"),this.dom.shadowTopLeft=document.createElement("div"),this.dom.shadowBottomLeft=document.createElement("div"),this.dom.shadowTopRight=document.createElement("div"),this.dom.shadowBottomRight=document.createElement("div"),this.dom.rollingModeBtn=document.createElement("div"),this.dom.root.className="vis-timeline",this.dom.background.className="vis-panel vis-background",this.dom.backgroundVertical.className="vis-panel vis-background vis-vertical",this.dom.backgroundHorizontal.className="vis-panel vis-background vis-horizontal",this.dom.centerContainer.className="vis-panel vis-center",this.dom.leftContainer.className="vis-panel vis-left",this.dom.rightContainer.className="vis-panel vis-right",this.dom.top.className="vis-panel vis-top",this.dom.bottom.className="vis-panel vis-bottom",this.dom.left.className="vis-content",this.dom.center.className="vis-content",this.dom.right.className="vis-content",this.dom.shadowTop.className="vis-shadow vis-top",this.dom.shadowBottom.className="vis-shadow vis-bottom",this.dom.shadowTopLeft.className="vis-shadow vis-top",this.dom.shadowBottomLeft.className="vis-shadow vis-bottom",this.dom.shadowTopRight.className="vis-shadow vis-top",this.dom.shadowBottomRight.className="vis-shadow vis-bottom",this.dom.rollingModeBtn.className="vis-rolling-mode-btn",this.dom.root.appendChild(this.dom.background),this.dom.root.appendChild(this.dom.backgroundVertical),this.dom.root.appendChild(this.dom.backgroundHorizontal),this.dom.root.appendChild(this.dom.centerContainer),this.dom.root.appendChild(this.dom.leftContainer),this.dom.root.appendChild(this.dom.rightContainer),this.dom.root.appendChild(this.dom.top),this.dom.root.appendChild(this.dom.bottom),this.dom.root.appendChild(this.dom.bottom),this.dom.root.appendChild(this.dom.rollingModeBtn),this.dom.centerContainer.appendChild(this.dom.center),this.dom.leftContainer.appendChild(this.dom.left),this.dom.rightContainer.appendChild(this.dom.right),this.dom.centerContainer.appendChild(this.dom.shadowTop),this.dom.centerContainer.appendChild(this.dom.shadowBottom),this.dom.leftContainer.appendChild(this.dom.shadowTopLeft),this.dom.leftContainer.appendChild(this.dom.shadowBottomLeft),this.dom.rightContainer.appendChild(this.dom.shadowTopRight),this.dom.rightContainer.appendChild(this.dom.shadowBottomRight),this.props={root:{},background:{},centerContainer:{},leftContainer:{},rightContainer:{},center:{},left:{},right:{},top:{},bottom:{},border:{},scrollTop:0,scrollTopMin:0},this.on("rangechange",function(){!0===this.initialDrawDone&&this._redraw()}.bind(this)),this.on("rangechanged",function(){this.initialRangeChangeDone||(this.initialRangeChangeDone=!0)}.bind(this)),this.on("touch",this._onTouch.bind(this)),this.on("panmove",this._onDrag.bind(this));var s=this;this._origRedraw=this._redraw.bind(this),this._redraw=c.throttle(this._origRedraw),this.on("_change",function(t){s.itemSet&&s.itemSet.initialItemSetDrawn&&t&&1==t.queue?s._redraw():s._origRedraw()}),this.hammer=new l(this.dom.root);var r=this.hammer.get("pinch").set({enable:!0});u.disablePreventDefaultVertically(r),this.hammer.get("pan").set({threshold:5,direction:l.DIRECTION_HORIZONTAL}),this.listeners={},["tap","doubletap","press","pinch","pan","panstart","panmove","panend"].forEach(function(t){var e=function(e){s.isActive()&&s.emit(t,e)};s.hammer.on(t,e),s.listeners[t]=e}),u.onTouch(this.hammer,function(t){s.emit("touch",t)}.bind(this)),u.onRelease(this.hammer,function(t){s.emit("release",t)}.bind(this)),this.dom.centerContainer.addEventListener?(this.dom.centerContainer.addEventListener("mousewheel",e.bind(this),!1),this.dom.centerContainer.addEventListener("DOMMouseScroll",e.bind(this),!1)):this.dom.centerContainer.attachEvent("onmousewheel",e.bind(this)),this.dom.left.parentNode.addEventListener("scroll",i.bind(this)),this.dom.right.parentNode.addEventListener("scroll",i.bind(this));var a=!1;if(this.dom.center.addEventListener("dragover",o.bind(this),!1),this.dom.center.addEventListener("drop",n.bind(this),!1),this.customTimes=[],this.touch={},this.redrawCount=0,this.initialDrawDone=!1,this.initialRangeChangeDone=!1,!t)throw new Error("No container provided");t.appendChild(this.dom.root)},n.prototype.setOptions=function(t){if(t){var e=["width","height","minHeight","maxHeight","autoResize","start","end","clickToUse","dataAttributes","hiddenDates","locale","locales","moment","rtl","zoomKey","horizontalScroll","verticalScroll"];if(c.selectiveExtend(e,this.options,t),this.dom.rollingModeBtn.style.visibility="hidden",this.options.rtl&&(this.dom.container.style.direction="rtl",this.dom.backgroundVertical.className="vis-panel vis-background vis-vertical-rtl"),this.options.verticalScroll&&(this.options.rtl?this.dom.rightContainer.className="vis-panel vis-right vis-vertical-scroll":this.dom.leftContainer.className="vis-panel vis-left vis-vertical-scroll"),"object"!==(0,h.default)(this.options.orientation)&&(this.options.orientation={item:void 0,axis:void 0}),"orientation"in t&&("string"==typeof t.orientation?this.options.orientation={item:t.orientation,axis:t.orientation}:"object"===(0,h.default)(t.orientation)&&("item"in t.orientation&&(this.options.orientation.item=t.orientation.item),"axis"in t.orientation&&(this.options.orientation.axis=t.orientation.axis))),"both"===this.options.orientation.axis){if(!this.timeAxis2){var i=this.timeAxis2=new p(this.body);i.setOptions=function(t){var e=t?c.extend({},t):{};e.orientation="top",p.prototype.setOptions.call(i,e)},this.components.push(i)}}else if(this.timeAxis2){var o=this.components.indexOf(this.timeAxis2);-1!==o&&this.components.splice(o,1),this.timeAxis2.destroy(),this.timeAxis2=null}if("function"==typeof t.drawPoints&&(t.drawPoints={onRender:t.drawPoints}),"hiddenDates"in this.options&&m.convertHiddenOptions(this.options.moment,this.body,this.options.hiddenDates),"clickToUse"in t&&(t.clickToUse?this.activator||(this.activator=new f(this.dom.root)):this.activator&&(this.activator.destroy(),delete this.activator)),"showCustomTime"in t)throw new Error("Option `showCustomTime` is deprecated. Create a custom time bar via timeline.addCustomTime(time [, id])");this._initAutoResize()}if(this.components.forEach(function(e){return e.setOptions(t)}),"configure"in t){this.configurator||(this.configurator=this._createConfigurator()),this.configurator.setOptions(t.configure);var n=c.deepExtend({},this.options);this.components.forEach(function(t){c.deepExtend(n,t.options)}),this.configurator.setModuleOptions({global:n})}this._redraw()},n.prototype.isActive=function(){return!this.activator||this.activator.active},n.prototype.destroy=function(){this.setItems(null),this.setGroups(null),this.off(),this._stopAutoResize(),this.dom.root.parentNode&&this.dom.root.parentNode.removeChild(this.dom.root),this.dom=null,this.activator&&(this.activator.destroy(),delete this.activator);for(var t in this.listeners)this.listeners.hasOwnProperty(t)&&delete this.listeners[t];this.listeners=null,this.hammer=null,this.components.forEach(function(t){return t.destroy()}),this.body=null},n.prototype.setCustomTime=function(t,e){var i=this.customTimes.filter(function(t){return e===t.options.id});if(0===i.length)throw new Error("No custom time bar found with id "+(0,r.default)(e));i.length>0&&i[0].setCustomTime(t)},n.prototype.getCustomTime=function(t){var e=this.customTimes.filter(function(e){return e.options.id===t});if(0===e.length)throw new Error("No custom time bar found with id "+(0,r.default)(t));return e[0].getCustomTime()},n.prototype.setCustomTimeTitle=function(t,e){var i=this.customTimes.filter(function(t){return t.options.id===e});if(0===i.length)throw new Error("No custom time bar found with id "+(0,r.default)(e));if(i.length>0)return i[0].setCustomTitle(t)},n.prototype.getEventProperties=function(t){return{event:t}},n.prototype.addCustomTime=function(t,e){var i=void 0!==t?c.convert(t,"Date").valueOf():new Date;if(this.customTimes.some(function(t){return t.options.id===e}))throw new Error("A custom time with id "+(0,r.default)(e)+" already exists");var o=new v(this.body,c.extend({},this.options,{time:i,id:e}));return this.customTimes.push(o),this.components.push(o),this._redraw(),e},n.prototype.removeCustomTime=function(t){var e=this.customTimes.filter(function(e){return e.options.id===t});if(0===e.length)throw new Error("No custom time bar found with id "+(0,r.default)(t));e.forEach(function(t){this.customTimes.splice(this.customTimes.indexOf(t),1),this.components.splice(this.components.indexOf(t),1),t.destroy()}.bind(this))},n.prototype.getVisibleItems=function(){return this.itemSet&&this.itemSet.getVisibleItems()||[]},n.prototype.fit=function(t,e){var i=this.getDataRange();if(null!==i.min||null!==i.max){var o=i.max-i.min,n=new Date(i.min.valueOf()-.01*o),s=new Date(i.max.valueOf()+.01*o),r=!t||void 0===t.animation||t.animation;this.range.setRange(n,s,{animation:r},e)}},n.prototype.getDataRange=function(){throw new Error("Cannot invoke abstract method getDataRange")},n.prototype.setWindow=function(t,e,i,o){"function"==typeof arguments[2]&&(o=arguments[2],i={});var n,s;1==arguments.length?(s=arguments[0],n=void 0===s.animation||s.animation,this.range.setRange(s.start,s.end,{animation:n})):2==arguments.length&&"function"==typeof arguments[1]?(s=arguments[0],o=arguments[1],n=void 0===s.animation||s.animation,this.range.setRange(s.start,s.end,{animation:n},o)):(n=!i||void 0===i.animation||i.animation,this.range.setRange(t,e,{animation:n},o))},n.prototype.moveTo=function(t,e,i){"function"==typeof arguments[1]&&(i=arguments[1],e={});var o=this.range.end-this.range.start,n=c.convert(t,"Date").valueOf(),s=n-o/2,r=n+o/2,a=!e||void 0===e.animation||e.animation;this.range.setRange(s,r,{animation:a},i)},n.prototype.getWindow=function(){var t=this.range.getRange();return{start:new Date(t.start),end:new Date(t.end)}},n.prototype.zoomIn=function(t,e,i){if(!(!t||t<0||t>1)){"function"==typeof arguments[1]&&(i=arguments[1],e={});var o=this.getWindow(),n=o.start.valueOf(),s=o.end.valueOf(),r=s-n,a=r/(1+t),h=(r-a)/2,d=n+h,l=s-h;this.setWindow(d,l,e,i)}},n.prototype.zoomOut=function(t,e,i){if(!(!t||t<0||t>1)){"function"==typeof arguments[1]&&(i=arguments[1],e={});var o=this.getWindow(),n=o.start.valueOf(),s=o.end.valueOf(),r=s-n,a=n-r*t/2,h=s+r*t/2;this.setWindow(a,h,e,i)}},n.prototype.redraw=function(){this._redraw()},n.prototype._redraw=function(){this.redrawCount++;var t=!1,e=this.options,i=this.props,o=this.dom;if(o&&o.container&&0!=o.root.offsetWidth){m.updateHiddenDates(this.options.moment,this.body,this.options.hiddenDates),"top"==e.orientation?(c.addClassName(o.root,"vis-top"),c.removeClassName(o.root,"vis-bottom")):(c.removeClassName(o.root,"vis-top"),c.addClassName(o.root,"vis-bottom")),o.root.style.maxHeight=c.option.asSize(e.maxHeight,""),o.root.style.minHeight=c.option.asSize(e.minHeight,""),o.root.style.width=c.option.asSize(e.width,""),i.border.left=(o.centerContainer.offsetWidth-o.centerContainer.clientWidth)/2,i.border.right=i.border.left,i.border.top=(o.centerContainer.offsetHeight-o.centerContainer.clientHeight)/2,i.border.bottom=i.border.top,i.borderRootHeight=o.root.offsetHeight-o.root.clientHeight,i.borderRootWidth=o.root.offsetWidth-o.root.clientWidth,0===o.centerContainer.clientHeight&&(i.border.left=i.border.top,i.border.right=i.border.left),0===o.root.clientHeight&&(i.borderRootWidth=i.borderRootHeight),i.center.height=o.center.offsetHeight,i.left.height=o.left.offsetHeight,i.right.height=o.right.offsetHeight,i.top.height=o.top.clientHeight||-i.border.top,i.bottom.height=o.bottom.clientHeight||-i.border.bottom;var n=Math.max(i.left.height,i.center.height,i.right.height),s=i.top.height+n+i.bottom.height+i.borderRootHeight+i.border.top+i.border.bottom;o.root.style.height=c.option.asSize(e.height,s+"px"),i.root.height=o.root.offsetHeight,i.background.height=i.root.height-i.borderRootHeight;var r=i.root.height-i.top.height-i.bottom.height-i.borderRootHeight;i.centerContainer.height=r,i.leftContainer.height=r,i.rightContainer.height=i.leftContainer.height,i.root.width=o.root.offsetWidth,i.background.width=i.root.width-i.borderRootWidth,this.initialDrawDone||(i.scrollbarWidth=c.getScrollBarWidth()),e.verticalScroll?e.rtl?(i.left.width=o.leftContainer.clientWidth||-i.border.left,i.right.width=o.rightContainer.clientWidth+i.scrollbarWidth||-i.border.right):(i.left.width=o.leftContainer.clientWidth+i.scrollbarWidth||-i.border.left,i.right.width=o.rightContainer.clientWidth||-i.border.right):(i.left.width=o.leftContainer.clientWidth||-i.border.left,i.right.width=o.rightContainer.clientWidth||-i.border.right),this._setDOM();var a=this._updateScrollTop();"top"!=e.orientation.item&&(a+=Math.max(i.centerContainer.height-i.center.height-i.border.top-i.border.bottom,0)),o.center.style.top=a+"px";var h=0==i.scrollTop?"hidden":"",d=i.scrollTop==i.scrollTopMin?"hidden":"";o.shadowTop.style.visibility=h,o.shadowBottom.style.visibility=d,o.shadowTopLeft.style.visibility=h,o.shadowBottomLeft.style.visibility=d,o.shadowTopRight.style.visibility=h,o.shadowBottomRight.style.visibility=d,e.verticalScroll&&(o.rightContainer.className="vis-panel vis-right vis-vertical-scroll",o.leftContainer.className="vis-panel vis-left vis-vertical-scroll",o.shadowTopRight.style.visibility="hidden",o.shadowBottomRight.style.visibility="hidden",o.shadowTopLeft.style.visibility="hidden",o.shadowBottomLeft.style.visibility="hidden",o.left.style.top="0px",o.right.style.top="0px"),(!e.verticalScroll||i.center.heighti.centerContainer.height;this.hammer.get("pan").set({direction:u?l.DIRECTION_ALL:l.DIRECTION_HORIZONTAL}),this.components.forEach(function(e){t=e.redraw()||t});if(t){if(this.redrawCount<5)return void this.body.emitter.emit("_change");console.log("WARNING: infinite loop in redraw?")}else this.redrawCount=0;this.body.emitter.emit("changed")}},n.prototype._setDOM=function(){var t=this.props,e=this.dom;t.leftContainer.width=t.left.width,t.rightContainer.width=t.right.width;var i=t.root.width-t.left.width-t.right.width-t.borderRootWidth;t.center.width=i,t.centerContainer.width=i,t.top.width=i,t.bottom.width=i,e.background.style.height=t.background.height+"px",e.backgroundVertical.style.height=t.background.height+"px",e.backgroundHorizontal.style.height=t.centerContainer.height+"px",e.centerContainer.style.height=t.centerContainer.height+"px",e.leftContainer.style.height=t.leftContainer.height+"px",e.rightContainer.style.height=t.rightContainer.height+"px",e.background.style.width=t.background.width+"px",e.backgroundVertical.style.width=t.centerContainer.width+"px",e.backgroundHorizontal.style.width=t.background.width+"px",e.centerContainer.style.width=t.center.width+"px",e.top.style.width=t.top.width+"px",e.bottom.style.width=t.bottom.width+"px",e.background.style.left="0",e.background.style.top="0",e.backgroundVertical.style.left=t.left.width+t.border.left+"px",e.backgroundVertical.style.top="0",e.backgroundHorizontal.style.left="0",e.backgroundHorizontal.style.top=t.top.height+"px",e.centerContainer.style.left=t.left.width+"px",e.centerContainer.style.top=t.top.height+"px",e.leftContainer.style.left="0",e.leftContainer.style.top=t.top.height+"px",e.rightContainer.style.left=t.left.width+t.center.width+"px",e.rightContainer.style.top=t.top.height+"px",e.top.style.left=t.left.width+"px",e.top.style.top="0",e.bottom.style.left=t.left.width+"px",e.bottom.style.top=t.top.height+t.centerContainer.height+"px",e.center.style.left="0",e.left.style.left="0",e.right.style.left="0"},n.prototype.repaint=function(){throw new Error("Function repaint is deprecated. Use redraw instead.")},n.prototype.setCurrentTime=function(t){if(!this.currentTime)throw new Error("Option showCurrentTime must be true");this.currentTime.setCurrentTime(t)},n.prototype.getCurrentTime=function(){if(!this.currentTime)throw new Error("Option showCurrentTime must be true");return this.currentTime.getCurrentTime()},n.prototype._toTime=function(t){return m.toTime(this,t,this.props.center.width)},n.prototype._toGlobalTime=function(t){return m.toTime(this,t,this.props.root.width)},n.prototype._toScreen=function(t){return m.toScreen(this,t,this.props.center.width)},n.prototype._toGlobalScreen=function(t){return m.toScreen(this,t,this.props.root.width)},n.prototype._initAutoResize=function(){1==this.options.autoResize?this._startAutoResize():this._stopAutoResize()},n.prototype._startAutoResize=function(){var t=this;this._stopAutoResize(),this._onResize=function(){if(1!=t.options.autoResize)return void t._stopAutoResize();t.dom.root&&(t.dom.root.offsetWidth==t.props.lastWidth&&t.dom.root.offsetHeight==t.props.lastHeight||(t.props.lastWidth=t.dom.root.offsetWidth,t.props.lastHeight=t.dom.root.offsetHeight,t.props.scrollbarWidth=c.getScrollBarWidth(),t.body.emitter.emit("_change")))},c.addEventListener(window,"resize",this._onResize),t.dom.root&&(t.props.lastWidth=t.dom.root.offsetWidth,t.props.lastHeight=t.dom.root.offsetHeight),this.watchTimer=setInterval(this._onResize,1e3)},n.prototype._stopAutoResize=function(){this.watchTimer&&(clearInterval(this.watchTimer),this.watchTimer=void 0),this._onResize&&(c.removeEventListener(window,"resize",this._onResize),this._onResize=null)},n.prototype._onTouch=function(t){this.touch.allowDragging=!0,this.touch.initialScrollTop=this.props.scrollTop},n.prototype._onPinch=function(t){this.touch.allowDragging=!1},n.prototype._onDrag=function(t){if(t&&this.touch.allowDragging){var e=t.deltaY,i=this._getScrollTop(),o=this._setScrollTop(this.touch.initialScrollTop+e);this.options.verticalScroll&&(this.dom.left.parentNode.scrollTop=-this.props.scrollTop,this.dom.right.parentNode.scrollTop=-this.props.scrollTop),o!=i&&this.emit("verticalDrag")}},n.prototype._setScrollTop=function(t){return this.props.scrollTop=t,this._updateScrollTop(),this.props.scrollTop},n.prototype._updateScrollTop=function(){var t=Math.min(this.props.centerContainer.height-this.props.center.height,0);return t!=this.props.scrollTopMin&&("top"!=this.options.orientation.item&&(this.props.scrollTop+=t-this.props.scrollTopMin),this.props.scrollTopMin=t),this.props.scrollTop>0&&(this.props.scrollTop=0),this.props.scrollTop0&&this.current.milliseconds()0&&this.current.seconds()0&&this.current.minutes()0&&this.current.hours()0?t.step:1,this.autoScale=!1)},o.prototype.setAutoScale=function(t){this.autoScale=t},o.prototype.setMinimumStep=function(t){if(void 0!=t){31104e9>t&&(this.scale="year",this.step=1e3),15552e9>t&&(this.scale="year",this.step=500),31104e8>t&&(this.scale="year",this.step=100),15552e8>t&&(this.scale="year",this.step=50),31104e7>t&&(this.scale="year",this.step=10),15552e7>t&&(this.scale="year",this.step=5),31104e6>t&&(this.scale="year",this.step=1),7776e6>t&&(this.scale="month",this.step=3),2592e6>t&&(this.scale="month",this.step=1),432e6>t&&(this.scale="day",this.step=5),1728e5>t&&(this.scale="day",this.step=2),864e5>t&&(this.scale="day",this.step=1),432e5>t&&(this.scale="weekday",this.step=1),144e5>t&&(this.scale="hour",this.step=4),36e5>t&&(this.scale="hour",this.step=1),9e5>t&&(this.scale="minute",this.step=15),6e5>t&&(this.scale="minute",this.step=10),3e5>t&&(this.scale="minute",this.step=5),6e4>t&&(this.scale="minute",this.step=1),15e3>t&&(this.scale="second",this.step=15),1e4>t&&(this.scale="second",this.step=10),5e3>t&&(this.scale="second",this.step=5),1e3>t&&(this.scale="second",this.step=1),200>t&&(this.scale="millisecond",this.step=200),100>t&&(this.scale="millisecond",this.step=100),50>t&&(this.scale="millisecond",this.step=50),10>t&&(this.scale="millisecond",this.step=10),5>t&&(this.scale="millisecond",this.step=5),1>t&&(this.scale="millisecond",this.step=1)}},o.snap=function(t,e,i){var o=n(t);if("year"==e){var s=o.year()+Math.round(o.month()/12);o.year(Math.round(s/i)*i),o.month(0),o.date(0),o.hours(0),o.minutes(0),o.seconds(0),o.milliseconds(0)}else if("month"==e)o.date()>15?(o.date(1),o.add(1,"month")):o.date(1),o.hours(0),o.minutes(0),o.seconds(0),o.milliseconds(0);else if("week"==e)o.weekday()>2?(o.weekday(0),o.add(1,"week")):o.weekday(0),o.hours(0),o.minutes(0),o.seconds(0),o.milliseconds(0);else if("day"==e){switch(i){case 5:case 2:o.hours(24*Math.round(o.hours()/24));break;default:o.hours(12*Math.round(o.hours()/12))}o.minutes(0),o.seconds(0),o.milliseconds(0)}else if("weekday"==e){switch(i){case 5:case 2:o.hours(12*Math.round(o.hours()/12));break;default:o.hours(6*Math.round(o.hours()/6))}o.minutes(0),o.seconds(0),o.milliseconds(0)}else if("hour"==e){switch(i){case 4:o.minutes(60*Math.round(o.minutes()/60));break;default:o.minutes(30*Math.round(o.minutes()/30))}o.seconds(0),o.milliseconds(0)}else if("minute"==e){switch(i){case 15:case 10:o.minutes(5*Math.round(o.minutes()/5)),o.seconds(0);break;case 5:o.seconds(60*Math.round(o.seconds()/60));break;default:o.seconds(30*Math.round(o.seconds()/30))}o.milliseconds(0)}else if("second"==e)switch(i){case 15:case 10:o.seconds(5*Math.round(o.seconds()/5)),o.milliseconds(0);break;case 5:o.milliseconds(1e3*Math.round(o.milliseconds()/1e3));break;default:o.milliseconds(500*Math.round(o.milliseconds()/500))}else if("millisecond"==e){var r=i>5?i/2:1;o.milliseconds(Math.round(o.milliseconds()/r)*r)}return o},o.prototype.isMajor=function(){if(1==this.switchedYear)switch(this.scale){case"year":case"month":case"week":case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedMonth)switch(this.scale){case"week":case"weekday":case"day":case"hour":case"minute":case"second":case"millisecond":return!0;default:return!1}else if(1==this.switchedDay)switch(this.scale){case"millisecond":case"second":case"minute":case"hour":return!0;default:return!1}var t=this.moment(this.current);switch(this.scale){case"millisecond":return 0==t.milliseconds();case"second":return 0==t.seconds();case"minute":return 0==t.hours()&&0==t.minutes();case"hour":return 0==t.hours();case"weekday":case"day":case"week":return 1==t.date();case"month":return 0==t.month();case"year":default:return!1}},o.prototype.getLabelMinor=function(t){if(void 0==t&&(t=this.current),t instanceof Date&&(t=this.moment(t)),"function"==typeof this.format.minorLabels)return this.format.minorLabels(t,this.scale,this.step);var e=this.format.minorLabels[this.scale];switch(this.scale){case"week":if(this.isMajor()&&0!==t.weekday())return"";default:return e&&e.length>0?this.moment(t).format(e):""}},o.prototype.getLabelMajor=function(t){if(void 0==t&&(t=this.current),t instanceof Date&&(t=this.moment(t)),"function"==typeof this.format.majorLabels)return this.format.majorLabels(t,this.scale,this.step);var e=this.format.majorLabels[this.scale];return e&&e.length>0?this.moment(t).format(e):""},o.prototype.getClassName=function(){function t(t){return t/a%2==0?" vis-even":" vis-odd"}function e(t){return t.isSame(new Date,"day")?" vis-today":t.isSame(n().add(1,"day"),"day")?" vis-tomorrow":t.isSame(n().add(-1,"day"),"day")?" vis-yesterday":""}function i(t){return t.isSame(new Date,"week")?" vis-current-week":""}function o(t){return t.isSame(new Date,"month")?" vis-current-month":""}var n=this.moment,s=this.moment(this.current),r=s.locale?s.locale("en"):s.lang("en"),a=this.step,h=[];switch(this.scale){case"millisecond":h.push(e(r)),h.push(t(r.milliseconds()));break;case"second":h.push(e(r)),h.push(t(r.seconds()));break;case"minute":h.push(e(r)),h.push(t(r.minutes()));break;case"hour":h.push("vis-h"+r.hours()+(4==this.step?"-h"+(r.hours()+4):"")),h.push(e(r)),h.push(t(r.hours()));break;case"weekday":h.push("vis-"+r.format("dddd").toLowerCase()),h.push(e(r)),h.push(i(r)),h.push(t(r.date()));break;case"day":h.push("vis-day"+r.date()),h.push("vis-"+r.format("MMMM").toLowerCase()),h.push(e(r)),h.push(o(r)),h.push(this.step<=2?e(r):""),h.push(this.step<=2?"vis-"+r.format("dddd").toLowerCase():""), +h.push(t(r.date()-1));break;case"week":h.push("vis-week"+r.format("w")),h.push(i(r)),h.push(t(r.week()));break;case"month":h.push("vis-"+r.format("MMMM").toLowerCase()),h.push(o(r)),h.push(t(r.month()));break;case"year":h.push("vis-year"+r.year()),h.push(function(t){return t.isSame(new Date,"year")?" vis-current-year":""}(r)),h.push(t(r.year()))}return h.filter(String).join(" ")},t.exports=o},function(t,e,i){function o(t,e){this.body=t,this.defaultOptions={rtl:!1,showCurrentTime:!0,moment:r,locales:a,locale:"en"},this.options=n.extend({},this.defaultOptions),this.offset=0,this._create(),this.setOptions(e)}var n=i(2),s=i(16),r=i(9),a=i(98);o.prototype=new s,o.prototype._create=function(){var t=document.createElement("div");t.className="vis-current-time",t.style.position="absolute",t.style.top="0px",t.style.height="100%",this.bar=t},o.prototype.destroy=function(){this.options.showCurrentTime=!1,this.redraw(),this.body=null},o.prototype.setOptions=function(t){t&&n.selectiveExtend(["rtl","showCurrentTime","moment","locale","locales"],this.options,t)},o.prototype.redraw=function(){if(this.options.showCurrentTime){var t=this.body.dom.backgroundVertical;this.bar.parentNode!=t&&(this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),t.appendChild(this.bar),this.start());var e=this.options.moment((new Date).valueOf()+this.offset),i=this.body.util.toScreen(e),o=this.options.locales[this.options.locale];o||(this.warned||(console.log("WARNING: options.locales['"+this.options.locale+"'] not found. See http://visjs.org/docs/timeline/#Localization"),this.warned=!0),o=this.options.locales.en);var n=o.current+" "+o.time+": "+e.format("dddd, MMMM Do YYYY, H:mm:ss");n=n.charAt(0).toUpperCase()+n.substring(1),this.options.rtl?this.bar.style.right=i+"px":this.bar.style.left=i+"px",this.bar.title=n}else this.bar.parentNode&&this.bar.parentNode.removeChild(this.bar),this.stop();return!1},o.prototype.start=function(){function t(){e.stop();var i=e.body.range.conversion(e.body.domProps.center.width).scale,o=1/i/10;o<30&&(o=30),o>1e3&&(o=1e3),e.redraw(),e.body.emitter.emit("currentTimeTick"),e.currentTimeTimer=setTimeout(t,o)}var e=this;t()},o.prototype.stop=function(){void 0!==this.currentTimeTimer&&(clearTimeout(this.currentTimeTimer),delete this.currentTimeTimer)},o.prototype.setCurrentTime=function(t){var e=n.convert(t,"Date").valueOf(),i=(new Date).valueOf();this.offset=e-i,this.redraw()},o.prototype.getCurrentTime=function(){return new Date((new Date).valueOf()+this.offset)},t.exports=o},function(t,e,i){function o(t,e,i){if(this.groupId=t,this.subgroups={},this.subgroupStack={},this.subgroupStackAll=!1,this.doInnerStack=!1,this.subgroupIndex=0,this.subgroupOrderer=e&&e.subgroupOrder,this.itemSet=i,this.isVisible=null,this.stackDirty=!0,e&&e.nestedGroups&&(this.nestedGroups=e.nestedGroups,0==e.showNested?this.showNested=!1:this.showNested=!0),e&&e.subgroupStack)if("boolean"==typeof e.subgroupStack)this.doInnerStack=e.subgroupStack,this.subgroupStackAll=e.subgroupStack;else for(var o in e.subgroupStack)this.subgroupStack[o]=e.subgroupStack[o],this.doInnerStack=this.doInnerStack||e.subgroupStack[o];this.nestedInGroup=null,this.dom={},this.props={label:{width:0,height:0}},this.className=null,this.items={},this.visibleItems=[],this.itemsInRange=[],this.orderedItems={byStart:[],byEnd:[]},this.checkRangedItems=!1;var n=this;this.itemSet.body.emitter.on("checkRangedItems",function(){n.checkRangedItems=!0}),this._create(),this.setData(e)}var n=i(8),s=function(t){return t&&t.__esModule?t:{default:t}}(n),r=i(2),a=i(100);o.prototype._create=function(){var t=document.createElement("div");this.itemSet.options.groupEditable.order?t.className="vis-label draggable":t.className="vis-label",this.dom.label=t;var e=document.createElement("div");e.className="vis-inner",t.appendChild(e),this.dom.inner=e;var i=document.createElement("div");i.className="vis-group",i["timeline-group"]=this,this.dom.foreground=i,this.dom.background=document.createElement("div"),this.dom.background.className="vis-group",this.dom.axis=document.createElement("div"),this.dom.axis.className="vis-group",this.dom.marker=document.createElement("div"),this.dom.marker.style.visibility="hidden",this.dom.marker.style.position="absolute",this.dom.marker.innerHTML="",this.dom.background.appendChild(this.dom.marker)},o.prototype.setData=function(t){var e,i;if(this.itemSet.options&&this.itemSet.options.groupTemplate?(i=this.itemSet.options.groupTemplate.bind(this),e=i(t,this.dom.inner)):e=t&&t.content,e instanceof Element){for(this.dom.inner.appendChild(e);this.dom.inner.firstChild;)this.dom.inner.removeChild(this.dom.inner.firstChild);this.dom.inner.appendChild(e)}else e instanceof Object?i(t,this.dom.inner):this.dom.inner.innerHTML=void 0!==e&&null!==e?e:this.groupId||"";if(this.dom.label.title=t&&t.title||"",this.dom.inner.firstChild?r.removeClassName(this.dom.inner,"vis-hidden"):r.addClassName(this.dom.inner,"vis-hidden"),t&&t.nestedGroups){this.nestedGroups&&this.nestedGroups==t.nestedGroups||(this.nestedGroups=t.nestedGroups),void 0===t.showNested&&void 0!==this.showNested||(0==t.showNested?this.showNested=!1:this.showNested=!0),r.addClassName(this.dom.label,"vis-nesting-group");var o=this.itemSet.options.rtl?"collapsed-rtl":"collapsed";this.showNested?(r.removeClassName(this.dom.label,o),r.addClassName(this.dom.label,"expanded")):(r.removeClassName(this.dom.label,"expanded"),r.addClassName(this.dom.label,o))}else this.nestedGroups&&(this.nestedGroups=null,o=this.itemSet.options.rtl?"collapsed-rtl":"collapsed",r.removeClassName(this.dom.label,o),r.removeClassName(this.dom.label,"expanded"),r.removeClassName(this.dom.label,"vis-nesting-group"));t&&t.nestedInGroup&&(r.addClassName(this.dom.label,"vis-nested-group"),this.itemSet.options&&this.itemSet.options.rtl?this.dom.inner.style.paddingRight="30px":this.dom.inner.style.paddingLeft="30px");var n=t&&t.className||null;n!=this.className&&(this.className&&(r.removeClassName(this.dom.label,this.className),r.removeClassName(this.dom.foreground,this.className),r.removeClassName(this.dom.background,this.className),r.removeClassName(this.dom.axis,this.className)),r.addClassName(this.dom.label,n),r.addClassName(this.dom.foreground,n),r.addClassName(this.dom.background,n),r.addClassName(this.dom.axis,n),this.className=n),this.style&&(r.removeCssText(this.dom.label,this.style),this.style=null),t&&t.style&&(r.addCssText(this.dom.label,t.style),this.style=t.style)},o.prototype.getLabelWidth=function(){return this.props.label.width},o.prototype._didMarkerHeightChange=function(){var t=this.dom.marker.clientHeight;if(t!=this.lastMarkerHeight){this.lastMarkerHeight=t;var e={},i=0;r.forEach(this.items,function(t,o){if(t.dirty=!0,t.displayed){e[o]=t.redraw(!0),i=e[o].length}});if(i>0)for(var o=0;o0)for(var u=0;u0){var e=this;this.resetSubgroups(),r.forEach(this.visibleItems,function(i){void 0!==i.data.subgroup&&(e.subgroups[i.data.subgroup].height=Math.max(e.subgroups[i.data.subgroup].height,i.height+t.item.vertical),e.subgroups[i.data.subgroup].visible=!0)})}},o.prototype._isGroupVisible=function(t,e){return this.top<=t.body.domProps.centerContainer.height-t.body.domProps.scrollTop+e.axis&&this.top+this.height+e.axis>=-t.body.domProps.scrollTop},o.prototype._calculateHeight=function(t){var e,i=this.visibleItems;if(i.length>0){var o=i[0].top,n=i[0].top+i[0].height;if(r.forEach(i,function(t){o=Math.min(o,t.top),n=Math.max(n,t.top+t.height)}),o>t.axis){var s=o-t.axis;n-=s,r.forEach(i,function(t){t.top-=s})}e=n+t.item.vertical/2}else e=0;return e=Math.max(e,this.props.label.height)},o.prototype.show=function(){this.dom.label.parentNode||this.itemSet.dom.labelSet.appendChild(this.dom.label),this.dom.foreground.parentNode||this.itemSet.dom.foreground.appendChild(this.dom.foreground),this.dom.background.parentNode||this.itemSet.dom.background.appendChild(this.dom.background),this.dom.axis.parentNode||this.itemSet.dom.axis.appendChild(this.dom.axis)},o.prototype.hide=function(){var t=this.dom.label;t.parentNode&&t.parentNode.removeChild(t);var e=this.dom.foreground;e.parentNode&&e.parentNode.removeChild(e);var i=this.dom.background;i.parentNode&&i.parentNode.removeChild(i);var o=this.dom.axis;o.parentNode&&o.parentNode.removeChild(o)},o.prototype.add=function(t){if(this.items[t.id]=t,t.setParent(this),this.stackDirty=!0,void 0!==t.data.subgroup&&(this._addToSubgroup(t),this.orderSubgroups()),-1==this.visibleItems.indexOf(t)){var e=this.itemSet.body.range;this._checkIfVisible(t,this.visibleItems,e)}},o.prototype._addToSubgroup=function(t,e){e=e||t.data.subgroup,void 0!=e&&void 0===this.subgroups[e]&&(this.subgroups[e]={height:0,top:0,start:t.data.start,end:t.data.end||t.data.start,visible:!1,index:this.subgroupIndex,items:[],stack:this.subgroupStackAll||this.subgroupStack[e]||!1},this.subgroupIndex++),new Date(t.data.start)new Date(this.subgroups[e].end)&&(this.subgroups[e].end=i),this.subgroups[e].items.push(t)},o.prototype._updateSubgroupsSizes=function(){var t=this;if(t.subgroups)for(var e in t.subgroups){var i=t.subgroups[e].items[0].data.end||t.subgroups[e].items[0].data.start,o=t.subgroups[e].items[0].data.start,n=i-1;t.subgroups[e].items.forEach(function(t){new Date(t.data.start)new Date(n)&&(n=e)}),t.subgroups[e].start=o,t.subgroups[e].end=new Date(n-1)}},o.prototype.orderSubgroups=function(){if(void 0!==this.subgroupOrderer){var t,e=[];if("string"==typeof this.subgroupOrderer){for(t in this.subgroups)e.push({subgroup:t,sortField:this.subgroups[t].items[0].data[this.subgroupOrderer]});e.sort(function(t,e){return t.sortField-e.sortField})}else if("function"==typeof this.subgroupOrderer){for(t in this.subgroups)e.push(this.subgroups[t].items[0].data);e.sort(this.subgroupOrderer)}if(e.length>0)for(var i=0;i=0&&(i.items.splice(o,1),i.items.length?this._updateSubgroupsSizes():delete this.subgroups[e])}}},o.prototype.removeFromDataSet=function(t){this.itemSet.removeItem(t.id)},o.prototype.order=function(){for(var t=r.toArray(this.items),e=[],i=[],o=0;o0)for(var l=0;lh}),1==this.checkRangedItems)for(this.checkRangedItems=!1,l=0;lh})}var p={},f=0;for(l=0;l0)for(var v=0;v=0&&(r=e[s],!n(r));s--)void 0===o[r.id]&&(o[r.id]=!0,i.push(r));for(s=t+1;st.start},o.prototype._createDomElement=function(){this.dom||(this.dom={},this.dom.box=document.createElement("div"),this.dom.frame=document.createElement("div"),this.dom.frame.className="vis-item-overflow",this.dom.box.appendChild(this.dom.frame),this.dom.visibleFrame=document.createElement("div"),this.dom.visibleFrame.className="vis-item-visible-frame",this.dom.box.appendChild(this.dom.visibleFrame),this.dom.content=document.createElement("div"),this.dom.content.className="vis-item-content",this.dom.frame.appendChild(this.dom.content),this.dom.box["timeline-item"]=this,this.dirty=!0)},o.prototype._appendDomElement=function(){if(!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!this.dom.box.parentNode){var t=this.parent.dom.foreground;if(!t)throw new Error("Cannot redraw item: parent has no foreground container element");t.appendChild(this.dom.box)}this.displayed=!0},o.prototype._updateDirtyDomComponents=function(){if(this.dirty){this._updateContents(this.dom.content),this._updateDataAttributes(this.dom.box),this._updateStyle(this.dom.box);var t=this.editable.updateTime||this.editable.updateGroup,e=(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"")+(t?" vis-editable":" vis-readonly");this.dom.box.className=this.baseClassName+e,this.dom.content.style.maxWidth="none"}},o.prototype._getDomComponentsSizes=function(){return this.overflow="hidden"!==window.getComputedStyle(this.dom.frame).overflow,{content:{width:this.dom.content.offsetWidth},box:{height:this.dom.box.offsetHeight}}},o.prototype._updateDomComponentsSizes=function(t){this.props.content.width=t.content.width,this.height=t.box.height,this.dom.content.style.maxWidth="",this.dirty=!1},o.prototype._repaintDomAdditionals=function(){this._repaintOnItemUpdateTimeTooltip(this.dom.box),this._repaintDeleteButton(this.dom.box),this._repaintDragCenter(),this._repaintDragLeft(),this._repaintDragRight()},o.prototype.redraw=function(t){var e,i=[this._createDomElement.bind(this),this._appendDomElement.bind(this),this._updateDirtyDomComponents.bind(this),function(){this.dirty&&(e=this._getDomComponentsSizes.bind(this)())}.bind(this),function(){this.dirty&&this._updateDomComponentsSizes.bind(this)(e)}.bind(this),this._repaintDomAdditionals.bind(this)];if(t)return i;var o;return i.forEach(function(t){o=t()}),o},o.prototype.show=function(){this.displayed||this.redraw()},o.prototype.hide=function(){if(this.displayed){var t=this.dom.box;t.parentNode&&t.parentNode.removeChild(t),this.displayed=!1}},o.prototype.repositionX=function(t){var e,i,o=this.parent.width,n=this.conversion.toScreen(this.data.start),s=this.conversion.toScreen(this.data.end),r=void 0===this.data.align?this.options.align:this.data.align;!1===this.data.limitSize||void 0!==t&&!0!==t||(n<-o&&(n=-o),s>2*o&&(s=2*o));var a=Math.max(s-n+.5,1);switch(this.overflow?(this.options.rtl?this.right=n:this.left=n,this.width=a+this.props.content.width,i=this.props.content.width):(this.options.rtl?this.right=n:this.left=n,this.width=a,i=Math.min(s-n,this.props.content.width)),this.options.rtl?this.dom.box.style.right=this.right+"px":this.dom.box.style.left=this.left+"px",this.dom.box.style.width=a+"px",r){case"left":this.options.rtl?this.dom.content.style.right="0":this.dom.content.style.left="0";break;case"right":this.options.rtl?this.dom.content.style.right=Math.max(a-i,0)+"px":this.dom.content.style.left=Math.max(a-i,0)+"px";break;case"center":this.options.rtl?this.dom.content.style.right=Math.max((a-i)/2,0)+"px":this.dom.content.style.left=Math.max((a-i)/2,0)+"px";break;default:e=this.overflow?s>0?Math.max(-n,0):-i:n<0?-n:0,this.options.rtl?this.dom.content.style.right=e+"px":(this.dom.content.style.left=e+"px",this.dom.content.style.width="calc(100% - "+e+"px)")}},o.prototype.repositionY=function(){var t=this.options.orientation.item,e=this.dom.box;e.style.top="top"==t?this.top+"px":this.parent.height-this.top-this.height+"px"},o.prototype._repaintDragLeft=function(){if((this.selected||this.options.itemsAlwaysDraggable.range)&&this.options.editable.updateTime&&!this.dom.dragLeft){var t=document.createElement("div");t.className="vis-drag-left",t.dragLeftItem=this,this.dom.box.appendChild(t),this.dom.dragLeft=t}else this.selected||this.options.itemsAlwaysDraggable.range||!this.dom.dragLeft||(this.dom.dragLeft.parentNode&&this.dom.dragLeft.parentNode.removeChild(this.dom.dragLeft),this.dom.dragLeft=null)},o.prototype._repaintDragRight=function(){if((this.selected||this.options.itemsAlwaysDraggable.range)&&this.options.editable.updateTime&&!this.dom.dragRight){var t=document.createElement("div");t.className="vis-drag-right",t.dragRightItem=this,this.dom.box.appendChild(t),this.dom.dragRight=t}else this.selected||this.options.itemsAlwaysDraggable.range||!this.dom.dragRight||(this.dom.dragRight.parentNode&&this.dom.dragRight.parentNode.removeChild(this.dom.dragRight),this.dom.dragRight=null)},t.exports=o},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(19),s=o(n),r=i(6),a=o(r),h=i(0),d=o(h),l=i(1),u=o(l),c=i(2),p=i(179).default,f=function(){function t(e,i,o){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1;(0,d.default)(this,t),this.parent=e,this.changedOptions=[],this.container=i,this.allowCreation=!1,this.options={},this.initialized=!1,this.popupCounter=0,this.defaultOptions={enabled:!1,filter:!0,container:void 0,showButton:!0},c.extend(this.options,this.defaultOptions),this.configureOptions=o,this.moduleOptions={},this.domElements=[],this.popupDiv={},this.popupLimit=5,this.popupHistory={},this.colorPicker=new p(n),this.wrapper=void 0}return(0,u.default)(t,[{key:"setOptions",value:function(t){if(void 0!==t){this.popupHistory={},this._removePopup();var e=!0;"string"==typeof t?this.options.filter=t:t instanceof Array?this.options.filter=t.join():"object"===(void 0===t?"undefined":(0,a.default)(t))?(void 0!==t.container&&(this.options.container=t.container),void 0!==t.filter&&(this.options.filter=t.filter),void 0!==t.showButton&&(this.options.showButton=t.showButton),void 0!==t.enabled&&(e=t.enabled)):"boolean"==typeof t?(this.options.filter=!0,e=t):"function"==typeof t&&(this.options.filter=t,e=!0),!1===this.options.filter&&(e=!1),this.options.enabled=e}this._clean()}},{key:"setModuleOptions",value:function(t){this.moduleOptions=t,!0===this.options.enabled&&(this._clean(),void 0!==this.options.container&&(this.container=this.options.container),this._create())}},{key:"_create",value:function(){var t=this;this._clean(),this.changedOptions=[];var e=this.options.filter,i=0,o=!1;for(var n in this.configureOptions)this.configureOptions.hasOwnProperty(n)&&(this.allowCreation=!1,o=!1,"function"==typeof e?(o=e(n,[]),o=o||this._handleObject(this.configureOptions[n],[n],!0)):!0!==e&&-1===e.indexOf(n)||(o=!0),!1!==o&&(this.allowCreation=!0,i>0&&this._makeItem([]),this._makeHeader(n),this._handleObject(this.configureOptions[n],[n])),i++);if(!0===this.options.showButton){var s=document.createElement("div");s.className="vis-configuration vis-config-button",s.innerHTML="generate options",s.onclick=function(){t._printOptions()},s.onmouseover=function(){s.className="vis-configuration vis-config-button hover"},s.onmouseout=function(){s.className="vis-configuration vis-config-button"},this.optionsContainer=document.createElement("div"),this.optionsContainer.className="vis-configuration vis-config-option-container",this.domElements.push(this.optionsContainer),this.domElements.push(s)}this._push()}},{key:"_push",value:function(){this.wrapper=document.createElement("div"),this.wrapper.className="vis-configuration-wrapper",this.container.appendChild(this.wrapper);for(var t=0;t1?i-1:0),n=1;n2&&void 0!==arguments[2]&&arguments[2],o=document.createElement("div");return o.className="vis-configuration vis-config-label vis-config-s"+e.length,o.innerHTML=!0===i?""+t+":":t+":",o}},{key:"_makeDropdown",value:function(t,e,i){var o=document.createElement("select");o.className="vis-configuration vis-config-select";var n=0;void 0!==e&&-1!==t.indexOf(e)&&(n=t.indexOf(e));for(var s=0;ss&&1!==s&&(a.max=Math.ceil(1.2*e),d=a.max,h="range increased"),a.value=e}else a.value=o;var l=document.createElement("input");l.className="vis-configuration vis-config-rangeinput",l.value=a.value;var u=this;a.onchange=function(){l.value=this.value,u._update(Number(this.value),i)},a.oninput=function(){l.value=this.value};var c=this._makeLabel(i[i.length-1],i),p=this._makeItem(i,c,a,l);""!==h&&this.popupHistory[p]!==d&&(this.popupHistory[p]=d,this._setupPopup(h,p))}},{key:"_setupPopup",value:function(t,e){var i=this;if(!0===this.initialized&&!0===this.allowCreation&&this.popupCounter1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=!1,n=this.options.filter,s=!1;for(var r in t)if(t.hasOwnProperty(r)){o=!0;var a=t[r],h=c.copyAndExtendArray(e,r);if("function"==typeof n&&!1===(o=n(r,e))&&!(a instanceof Array)&&"string"!=typeof a&&"boolean"!=typeof a&&a instanceof Object&&(this.allowCreation=!1,o=this._handleObject(a,h,!0),this.allowCreation=!1===i),!1!==o){s=!0;var d=this._getValue(h);if(a instanceof Array)this._handleArray(a,d,h);else if("string"==typeof a)this._makeTextInput(a,d,h);else if("boolean"==typeof a)this._makeCheckbox(a,d,h);else if(a instanceof Object){var l=!0;if(-1!==e.indexOf("physics")&&this.moduleOptions.physics.solver!==r&&(l=!1),!0===l)if(void 0!==a.enabled){var u=c.copyAndExtendArray(h,"enabled"),p=this._getValue(u);if(!0===p){var f=this._makeLabel(r,h,!0);this._makeItem(h,f),s=this._handleObject(a,h)||s}else this._makeCheckbox(a,p,h)}else{var m=this._makeLabel(r,h,!0);this._makeItem(h,m),s=this._handleObject(a,h)||s}}else console.error("dont know how to handle",a,r,h)}}return s}},{key:"_handleArray",value:function(t,e,i){"string"==typeof t[0]&&"color"===t[0]?(this._makeColorField(t,e,i),t[1]!==e&&this.changedOptions.push({path:i,value:e})):"string"==typeof t[0]?(this._makeDropdown(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:e})):"number"==typeof t[0]&&(this._makeRange(t,e,i),t[0]!==e&&this.changedOptions.push({path:i,value:Number(e)}))}},{key:"_update",value:function(t,e){var i=this._constructOptions(t,e);this.parent.body&&this.parent.body.emitter&&this.parent.body.emitter.emit&&this.parent.body.emitter.emit("configChange",i),this.initialized=!0,this.parent.setOptions(i)}},{key:"_constructOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o=i;t="true"===t||t,t="false"!==t&&t;for(var n=0;nvar options = "+(0,s.default)(t,null,2)+""}},{key:"getOptions",value:function(){for(var t={},e=0;ethis.imageObj.height?i=this.imageObj.width/this.imageObj.height:o=this.imageObj.height/this.imageObj.width),t=2*this.options.size*i,e=2*this.options.size*o}else t=this.imageObj.width,e=this.imageObj.height;this.width=t,this.height=e,this.radius=.5*this.width}},{key:"_drawRawCircle",value:function(t,e,i,o){this.initContextForDraw(t,o),t.circle(e,i,o.size),this.performFill(t,o)}},{key:"_drawImageAtPosition",value:function(t,e){if(0!=this.imageObj.width){t.globalAlpha=1,this.enableShadow(t,e);var i=1;!0===this.options.shapeProperties.interpolation&&(i=this.imageObj.width/this.width/this.body.view.scale),this.imageObj.drawImageAtPosition(t,i,this.left,this.top,this.width,this.height),this.disableShadow(t,e)}}},{key:"_drawImageLabel",value:function(t,e,i,o,n){var s,r=0;if(void 0!==this.height){r=.5*this.height;var a=this.labelModule.getTextSize(t,o,n);a.lineCount>=1&&(r+=a.height/2)}s=i+r,this.options.label&&(this.labelOffset=r),this.labelModule.draw(t,e,s,o,n,"hanging")}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(19),s=o(n),r=i(6),a=o(r),h=i(29),d=o(h),l=i(0),u=o(l),c=i(1),p=o(c),f=i(2),m=i(117).default,v=i(48).default,g=i(215).default,y=i(217).default,b=i(218).default,_=i(219).default,w=function(){function t(e,i,o,n){if((0,u.default)(this,t),void 0===i)throw new Error("No body provided");this.options=f.bridgeObject(o),this.globalOptions=o,this.defaultOptions=n,this.body=i,this.id=void 0,this.fromId=void 0,this.toId=void 0,this.selected=!1,this.hover=!1,this.labelDirty=!0,this.baseWidth=this.options.width,this.baseFontSize=this.options.font.size,this.from=void 0,this.to=void 0,this.edgeType=void 0,this.connected=!1,this.labelModule=new m(this.body,this.options,!0),this.setOptions(e)}return(0,p.default)(t,[{key:"setOptions",value:function(e){if(e){t.parseOptions(this.options,e,!0,this.globalOptions),void 0!==e.id&&(this.id=e.id),void 0!==e.from&&(this.fromId=e.from),void 0!==e.to&&(this.toId=e.to),void 0!==e.title&&(this.title=e.title),void 0!==e.value&&(e.value=parseFloat(e.value));var i=[e,this.options,this.defaultOptions];this.chooser=v.choosify("edge",i),this.updateLabelModule(e);var o=this.updateEdgeType();return this._setInteractionWidths(),this.connect(),void 0===e.hidden&&void 0===e.physics||(o=!0),o}}},{key:"getFormattingValues",value:function(){var t=!0===this.options.arrows.to||!0===this.options.arrows.to.enabled,e=!0===this.options.arrows.from||!0===this.options.arrows.from.enabled,i=!0===this.options.arrows.middle||!0===this.options.arrows.middle.enabled,o=this.options.color.inherit,n={toArrow:t,toArrowScale:this.options.arrows.to.scaleFactor,toArrowType:this.options.arrows.to.type,middleArrow:i,middleArrowScale:this.options.arrows.middle.scaleFactor,middleArrowType:this.options.arrows.middle.type,fromArrow:e,fromArrowScale:this.options.arrows.from.scaleFactor,fromArrowType:this.options.arrows.from.type,arrowStrikethrough:this.options.arrowStrikethrough,color:o?void 0:this.options.color.color,inheritsColor:o,opacity:this.options.color.opacity,hidden:this.options.hidden,length:this.options.length,shadow:this.options.shadow.enabled,shadowColor:this.options.shadow.color,shadowSize:this.options.shadow.size,shadowX:this.options.shadow.x,shadowY:this.options.shadow.y,dashes:this.options.dashes,width:this.options.width};if(this.selected||this.hover)if(!0===this.chooser){if(this.selected){var s=this.options.selectionWidth;"function"==typeof s?n.width=s(n.width):"number"==typeof s&&(n.width+=s),n.width=Math.max(n.width,.3/this.body.view.scale),n.color=this.options.color.highlight,n.shadow=this.options.shadow.enabled}else if(this.hover){var r=this.options.hoverWidth;"function"==typeof r?n.width=r(n.width):"number"==typeof r&&(n.width+=r),n.width=Math.max(n.width,.3/this.body.view.scale),n.color=this.options.color.hover,n.shadow=this.options.shadow.enabled}}else"function"==typeof this.chooser&&(this.chooser(n,this.options.id,this.selected,this.hover),void 0!==n.color&&(n.inheritsColor=!1),!1===n.shadow&&(n.shadowColor===this.options.shadow.color&&n.shadowSize===this.options.shadow.size&&n.shadowX===this.options.shadow.x&&n.shadowY===this.options.shadow.y||(n.shadow=!0)));else n.shadow=this.options.shadow.enabled,n.width=Math.max(n.width,.3/this.body.view.scale);return n}},{key:"updateLabelModule",value:function(t){var e=[t,this.options,this.globalOptions,this.defaultOptions];this.labelModule.update(this.options,e),void 0!==this.labelModule.baseSize&&(this.baseFontSize=this.labelModule.baseSize)}},{key:"updateEdgeType",value:function(){var t=this.options.smooth,e=!1,i=!0;return void 0!==this.edgeType&&((this.edgeType instanceof y&&!0===t.enabled&&"dynamic"===t.type||this.edgeType instanceof g&&!0===t.enabled&&"cubicBezier"===t.type||this.edgeType instanceof b&&!0===t.enabled&&"dynamic"!==t.type&&"cubicBezier"!==t.type||this.edgeType instanceof _&&!1===t.type.enabled)&&(i=!1),!0===i&&(e=this.cleanup())),!0===i?!0===t.enabled?"dynamic"===t.type?(e=!0,this.edgeType=new y(this.options,this.body,this.labelModule)):"cubicBezier"===t.type?this.edgeType=new g(this.options,this.body,this.labelModule):this.edgeType=new b(this.options,this.body,this.labelModule):this.edgeType=new _(this.options,this.body,this.labelModule):this.edgeType.setOptions(this.options),e}},{key:"connect",value:function(){this.disconnect(),this.from=this.body.nodes[this.fromId]||void 0,this.to=this.body.nodes[this.toId]||void 0,this.connected=void 0!==this.from&&void 0!==this.to,!0===this.connected?(this.from.attachEdge(this),this.to.attachEdge(this)):(this.from&&this.from.detachEdge(this),this.to&&this.to.detachEdge(this)),this.edgeType.connect()}},{key:"disconnect",value:function(){this.from&&(this.from.detachEdge(this),this.from=void 0),this.to&&(this.to.detachEdge(this),this.to=void 0),this.connected=!1}},{key:"getTitle",value:function(){return this.title}},{key:"isSelected",value:function(){return this.selected}},{key:"getValue",value:function(){return this.options.value}},{key:"setValueRange",value:function(t,e,i){if(void 0!==this.options.value){var o=this.options.scaling.customScalingFunction(t,e,i,this.options.value),n=this.options.scaling.max-this.options.scaling.min;if(!0===this.options.scaling.label.enabled){var s=this.options.scaling.label.max-this.options.scaling.label.min;this.options.font.size=this.options.scaling.label.min+o*s}this.options.width=this.options.scaling.min+o*n}else this.options.width=this.baseWidth,this.options.font.size=this.baseFontSize;this._setInteractionWidths(),this.updateLabelModule()}},{key:"_setInteractionWidths",value:function(){"function"==typeof this.options.hoverWidth?this.edgeType.hoverWidth=this.options.hoverWidth(this.options.width):this.edgeType.hoverWidth=this.options.hoverWidth+this.options.width,"function"==typeof this.options.selectionWidth?this.edgeType.selectionWidth=this.options.selectionWidth(this.options.width):this.edgeType.selectionWidth=this.options.selectionWidth+this.options.width}},{key:"draw",value:function(t){var e=this.getFormattingValues();if(!e.hidden){var i=this.edgeType.getViaNode(),o={};this.edgeType.fromPoint=this.edgeType.from,this.edgeType.toPoint=this.edgeType.to,e.fromArrow&&(o.from=this.edgeType.getArrowData(t,"from",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.fromPoint=o.from.core)),e.toArrow&&(o.to=this.edgeType.getArrowData(t,"to",i,this.selected,this.hover,e),!1===e.arrowStrikethrough&&(this.edgeType.toPoint=o.to.core)),e.middleArrow&&(o.middle=this.edgeType.getArrowData(t,"middle",i,this.selected,this.hover,e)),this.edgeType.drawLine(t,e,this.selected,this.hover,i),this.drawArrows(t,o,e),this.drawLabel(t,i)}}},{key:"drawArrows",value:function(t,e,i){i.fromArrow&&this.edgeType.drawArrowHead(t,i,this.selected,this.hover,e.from),i.middleArrow&&this.edgeType.drawArrowHead(t,i,this.selected,this.hover,e.middle),i.toArrow&&this.edgeType.drawArrowHead(t,i,this.selected,this.hover,e.to)}},{key:"drawLabel",value:function(t,e){if(void 0!==this.options.label){var i=this.from,o=this.to;if(this.labelModule.differentState(this.selected,this.hover)&&this.labelModule.getTextSize(t,this.selected,this.hover),i.id!=o.id){this.labelModule.pointToSelf=!1;var n=this.edgeType.getPoint(.5,e);t.save();var s=this._getRotation(t);0!=s.angle&&(t.translate(s.x,s.y),t.rotate(s.angle)),this.labelModule.draw(t,n.x,n.y,this.selected,this.hover),t.restore()}else{this.labelModule.pointToSelf=!0;var r,a,h=this.options.selfReferenceSize;i.shape.width>i.shape.height?(r=i.x+.5*i.shape.width,a=i.y-h):(r=i.x+h,a=i.y-.5*i.shape.height),n=this._pointOnCircle(r,a,h,.125),this.labelModule.draw(t,n.x,n.y,this.selected,this.hover)}}}},{key:"getItemsOnPoint",value:function(t){var e=[];if(this.labelModule.visible()){var i=this._getRotation();v.pointInRect(this.labelModule.getSize(),t,i)&&e.push({edgeId:this.id,labelId:0})}var o={left:t.x,top:t.y};return this.isOverlappingWith(o)&&e.push({edgeId:this.id}),e}},{key:"isOverlappingWith",value:function(t){if(this.connected){var e=this.from.x,i=this.from.y,o=this.to.x,n=this.to.y,s=t.left,r=t.top;return this.edgeType.getDistanceToEdge(e,i,o,n,s,r)<10}return!1}},{key:"_getRotation",value:function(t){var e=this.edgeType.getViaNode(),i=this.edgeType.getPoint(.5,e);void 0!==t&&this.labelModule.calculateLabelSize(t,this.selected,this.hover,i.x,i.y);var o={x:i.x,y:this.labelModule.size.yLine,angle:0};if(!this.labelModule.visible())return o;if("horizontal"===this.options.font.align)return o;var n=this.from.y-this.to.y,s=this.from.x-this.to.x,r=Math.atan2(n,s);return(r<-1&&s<0||r>0&&s<0)&&(r+=Math.PI),o.angle=r,o}},{key:"_pointOnCircle",value:function(t,e,i,o){var n=2*o*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}}},{key:"select",value:function(){this.selected=!0}},{key:"unselect",value:function(){this.selected=!1}},{key:"cleanup",value:function(){return this.edgeType.cleanup()}},{key:"remove",value:function(){this.cleanup(),this.disconnect(),delete this.body.edges[this.id]}},{key:"endPointsValid",value:function(){return void 0!==this.body.nodes[this.fromId]&&void 0!==this.body.nodes[this.toId]}}],[{key:"parseOptions",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},n=arguments.length>4&&void 0!==arguments[4]&&arguments[4],r=["arrowStrikethrough","id","from","hidden","hoverWidth","labelHighlightBold","length","line","opacity","physics","scaling","selectionWidth","selfReferenceSize","to","title","value","width","font","chosen","widthConstraint"];if(f.selectiveDeepExtend(r,t,e,i),v.isValidLabel(e.label)?t.label=e.label:t.label=void 0,f.mergeOptions(t,e,"smooth",o),f.mergeOptions(t,e,"shadow",o),void 0!==e.dashes&&null!==e.dashes?t.dashes=e.dashes:!0===i&&null===e.dashes&&(t.dashes=(0,d.default)(o.dashes)),void 0!==e.scaling&&null!==e.scaling?(void 0!==e.scaling.min&&(t.scaling.min=e.scaling.min),void 0!==e.scaling.max&&(t.scaling.max=e.scaling.max),f.mergeOptions(t.scaling,e.scaling,"label",o.scaling)):!0===i&&null===e.scaling&&(t.scaling=(0,d.default)(o.scaling)),void 0!==e.arrows&&null!==e.arrows)if("string"==typeof e.arrows){var h=e.arrows.toLowerCase();t.arrows.to.enabled=-1!=h.indexOf("to"),t.arrows.middle.enabled=-1!=h.indexOf("middle"),t.arrows.from.enabled=-1!=h.indexOf("from")}else{if("object"!==(0,a.default)(e.arrows))throw new Error("The arrow newOptions can only be an object or a string. Refer to the documentation. You used:"+(0,s.default)(e.arrows));f.mergeOptions(t.arrows,e.arrows,"to",o.arrows),f.mergeOptions(t.arrows,e.arrows,"middle",o.arrows),f.mergeOptions(t.arrows,e.arrows,"from",o.arrows)}else!0===i&&null===e.arrows&&(t.arrows=(0,d.default)(o.arrows));if(void 0!==e.color&&null!==e.color){var l=e.color,u=t.color;if(n)f.deepExtend(u,o.color,!1,i);else for(var c in u)u.hasOwnProperty(c)&&delete u[c];if(f.isString(u))u.color=u,u.highlight=u,u.hover=u,u.inherit=!1,void 0===l.opacity&&(u.opacity=1);else{var p=!1;void 0!==l.color&&(u.color=l.color,p=!0),void 0!==l.highlight&&(u.highlight=l.highlight,p=!0),void 0!==l.hover&&(u.hover=l.hover,p=!0),void 0!==l.inherit&&(u.inherit=l.inherit),void 0!==l.opacity&&(u.opacity=Math.min(1,Math.max(0,l.opacity))),!0===p?u.inherit=!1:void 0===u.inherit&&(u.inherit="from")}}else!0===i&&null===e.color&&(t.color=f.bridgeObject(o.color));!0===i&&null===e.font&&(t.font=f.bridgeObject(o.font))}}]),t}();e.default=w},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(118),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_findBorderPositionBezier",value:function(t,e){var i,o,n,s,r,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this._getViaCoordinates(),h=0,d=0,l=1,u=this.to,c=!1;for(t.id===this.from.id&&(u=this.from,c=!0);d<=l&&h<10;){var p=.5*(d+l);if(i=this.getPoint(p,a),o=Math.atan2(u.y-i.y,u.x-i.x),n=u.distanceToBorder(e,o),s=Math.sqrt(Math.pow(i.x-u.x,2)+Math.pow(i.y-u.y,2)),r=n-s,Math.abs(r)<.2)break;r<0?!1===c?d=p:l=p:!1===c?l=p:d=p,h++}return i.t=p,i}},{key:"_getDistanceToBezierEdge",value:function(t,e,i,o,n,s,r){var a=1e9,h=void 0,d=void 0,l=void 0,u=void 0,c=void 0,p=t,f=e;for(d=1;d<10;d++)l=.1*d,u=Math.pow(1-l,2)*t+2*l*(1-l)*r.x+Math.pow(l,2)*i,c=Math.pow(1-l,2)*e+2*l*(1-l)*r.y+Math.pow(l,2)*o,d>0&&(h=this._getDistanceToLine(p,f,u,c,n,s),a=h1&&void 0!==arguments[1]?arguments[1]:[],o=1e9,n=-1e9,s=1e9,r=-1e9;if(i.length>0)for(var a=0;ae.shape.boundingBox.left&&(s=e.shape.boundingBox.left),re.shape.boundingBox.top&&(o=e.shape.boundingBox.top),n1&&void 0!==arguments[1]?arguments[1]:[],o=1e9,n=-1e9,s=1e9,r=-1e9;if(i.length>0)for(var a=0;ae.x&&(s=e.x),re.y&&(o=e.y),nh;)o(a,i=e[h++])&&(~s(d,i)||d.push(i));return d}},function(t,e,i){var o=i(22),n=i(41),s=i(56)("IE_PROTO"),r=Object.prototype;t.exports=Object.getPrototypeOf||function(t){return t=n(t),o(t,s)?t[s]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?r:null}},function(t,e,i){var o=i(50),n=i(13)("toStringTag"),s="Arguments"==o(function(){return arguments}()),r=function(t,e){try{return t[e]}catch(t){}};t.exports=function(t){var e,i,a;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(i=r(e=Object(t),n))?i:s?o(e):"Object"==(a=o(e))&&"function"==typeof e.callee?"Arguments":a}},function(t,e,i){var o=i(17),n=i(7),s=i(28);t.exports=function(t,e){var i=(n.Object||{})[t]||Object[t],r={};r[t]=e(i),o(o.S+o.F*s(function(){i(1)}),"Object",r)}},function(t,e,i){var o=i(84),n=i(58).concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return o(t,n)}},function(t,e,i){var o=i(42),n=i(39),s=i(25),r=i(53),a=i(22),h=i(81),d=Object.getOwnPropertyDescriptor;e.f=i(21)?d:function(t,e){if(t=s(t),e=r(e,!0),h)try{return d(t,e)}catch(t){}if(a(t,e))return n(!o.f.call(t,e),t[e])}},function(t,e,i){t.exports={default:i(162),__esModule:!0}},function(t,e,i){function o(t,e){this.x=void 0!==t?t:0,this.y=void 0!==e?e:0}t.exports=o},function(t,e,i){function o(t,e){if(void 0===t)throw new Error("No container element defined");if(this.container=t,this.visible=!e||void 0==e.visible||e.visible,this.visible){this.frame=document.createElement("DIV"),this.frame.style.width="100%",this.frame.style.position="relative",this.container.appendChild(this.frame),this.frame.prev=document.createElement("INPUT"),this.frame.prev.type="BUTTON",this.frame.prev.value="Prev",this.frame.appendChild(this.frame.prev),this.frame.play=document.createElement("INPUT"),this.frame.play.type="BUTTON",this.frame.play.value="Play",this.frame.appendChild(this.frame.play),this.frame.next=document.createElement("INPUT"),this.frame.next.type="BUTTON",this.frame.next.value="Next",this.frame.appendChild(this.frame.next),this.frame.bar=document.createElement("INPUT"),this.frame.bar.type="BUTTON",this.frame.bar.style.position="absolute",this.frame.bar.style.border="1px solid red",this.frame.bar.style.width="100px",this.frame.bar.style.height="6px",this.frame.bar.style.borderRadius="2px",this.frame.bar.style.MozBorderRadius="2px",this.frame.bar.style.border="1px solid #7F7F7F",this.frame.bar.style.backgroundColor="#E5E5E5",this.frame.appendChild(this.frame.bar),this.frame.slide=document.createElement("INPUT"),this.frame.slide.type="BUTTON",this.frame.slide.style.margin="0px",this.frame.slide.value=" ",this.frame.slide.style.position="relative",this.frame.slide.style.left="-100px",this.frame.appendChild(this.frame.slide);var i=this;this.frame.slide.onmousedown=function(t){i._onMouseDown(t)},this.frame.prev.onclick=function(t){i.prev(t)},this.frame.play.onclick=function(t){i.togglePlay(t)},this.frame.next.onclick=function(t){i.next(t)}}this.onChangeCallback=void 0,this.values=[],this.index=void 0,this.playTimeout=void 0,this.playInterval=1e3,this.playLoop=!0}var n=i(2);o.prototype.prev=function(){var t=this.getIndex();t>0&&(t--,this.setIndex(t))},o.prototype.next=function(){var t=this.getIndex();t0?this.setIndex(0):this.index=void 0},o.prototype.setIndex=function(t){if(!(tthis.values.length-1&&(o=this.values.length-1),o},o.prototype.indexToLeft=function(t){var e=parseFloat(this.frame.bar.style.width)-this.frame.slide.clientWidth-10;return t/(this.values.length-1)*e+3},o.prototype._onMouseMove=function(t){var e=t.clientX-this.startClientX,i=this.startSlideX+e,o=this.leftToIndex(i);this.setIndex(o),n.preventDefault()},o.prototype._onMouseUp=function(t){this.frame.style.cursor="auto",n.removeEventListener(document,"mousemove",this.onmousemove),n.removeEventListener(document,"mouseup",this.onmouseup),n.preventDefault()},t.exports=o},function(t,e,i){function o(t,e,i,o){this._start=0,this._end=0,this._step=1,this.prettyStep=!0,this.precision=5,this._current=0,this.setRange(t,e,i,o)}o.prototype.isNumeric=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.prototype.setRange=function(t,e,i,o){if(!this.isNumeric(t))throw new Error("Parameter 'start' is not numeric; value: "+t);if(!this.isNumeric(e))throw new Error("Parameter 'end' is not numeric; value: "+t);if(!this.isNumeric(i))throw new Error("Parameter 'step' is not numeric; value: "+t);this._start=t||0,this._end=e||0,this.setStep(i,o)},o.prototype.setStep=function(t,e){void 0===t||t<=0||(void 0!==e&&(this.prettyStep=e),!0===this.prettyStep?this._step=o.calculatePrettyStep(t):this._step=t)},o.calculatePrettyStep=function(t){var e=function(t){return Math.log(t)/Math.LN10},i=Math.pow(10,Math.round(e(t))),o=2*Math.pow(10,Math.round(e(t/2))),n=5*Math.pow(10,Math.round(e(t/5))),s=i;return Math.abs(o-t)<=Math.abs(s-t)&&(s=o),Math.abs(n-t)<=Math.abs(s-t)&&(s=n),s<=0&&(s=1),s},o.prototype.getCurrent=function(){return parseFloat(this._current.toPrecision(this.precision))},o.prototype.getStep=function(){return this._step},o.prototype.start=function(t){void 0===t&&(t=!1),this._current=this._start-this._start%this._step,t&&this.getCurrent()this._end},t.exports=o},function(t,e,i){function o(t){for(var e in t)if(t.hasOwnProperty(e))return!1;return!0}function n(t){return void 0===t||""===t||"string"!=typeof t?t:t.charAt(0).toUpperCase()+t.slice(1)}function s(t,e){return void 0===t||""===t?e:t+n(e)}function r(t,e,i,o){for(var n,r,a=0;ar&&(t=o(t)*r),i(e)>r&&(e=o(e)*r),this.cameraOffset.x=t,this.cameraOffset.y=e,this.calculateCameraOrientation()},o.prototype.getOffset=function(){return this.cameraOffset},o.prototype.setArmLocation=function(t,e,i){this.armLocation.x=t,this.armLocation.y=e,this.armLocation.z=i,this.calculateCameraOrientation()},o.prototype.setArmRotation=function(t,e){void 0!==t&&(this.armRotation.horizontal=t),void 0!==e&&(this.armRotation.vertical=e,this.armRotation.vertical<0&&(this.armRotation.vertical=0),this.armRotation.vertical>.5*Math.PI&&(this.armRotation.vertical=.5*Math.PI)),void 0===t&&void 0===e||this.calculateCameraOrientation()},o.prototype.getArmRotation=function(){var t={};return t.horizontal=this.armRotation.horizontal,t.vertical=this.armRotation.vertical,t},o.prototype.setArmLength=function(t){void 0!==t&&(this.armLength=t,this.armLength<.71&&(this.armLength=.71),this.armLength>5&&(this.armLength=5),this.setOffset(this.cameraOffset.x,this.cameraOffset.y),this.calculateCameraOrientation())}, +o.prototype.getArmLength=function(){return this.armLength},o.prototype.getCameraLocation=function(){return this.cameraLocation},o.prototype.getCameraRotation=function(){return this.cameraRotation},o.prototype.calculateCameraOrientation=function(){this.cameraLocation.x=this.armLocation.x-this.armLength*Math.sin(this.armRotation.horizontal)*Math.cos(this.armRotation.vertical),this.cameraLocation.y=this.armLocation.y-this.armLength*Math.cos(this.armRotation.horizontal)*Math.cos(this.armRotation.vertical),this.cameraLocation.z=this.armLocation.z+this.armLength*Math.sin(this.armRotation.vertical),this.cameraRotation.x=Math.PI/2-this.armRotation.vertical,this.cameraRotation.y=0,this.cameraRotation.z=-this.armRotation.horizontal;var t=this.cameraRotation.x,e=this.cameraRotation.z,i=this.cameraOffset.x,o=this.cameraOffset.y,n=Math.sin,s=Math.cos;this.cameraLocation.x=this.cameraLocation.x+i*s(e)+o*-n(e)*s(t),this.cameraLocation.y=this.cameraLocation.y+i*n(e)+o*s(e)*s(t),this.cameraLocation.z=this.cameraLocation.z+o*n(t)},t.exports=o},function(t,e,i){function o(t,e,i){this.dataGroup=t,this.column=e,this.graph=i,this.index=void 0,this.value=void 0,this.values=t.getDistinctValues(this.column),this.values.length>0&&this.selectValue(0),this.dataPoints=[],this.loaded=!1,this.onLoadCallback=void 0,i.animationPreload?(this.loaded=!1,this.loadInBackground()):this.loaded=!0}var n=i(12);o.prototype.isLoaded=function(){return this.loaded},o.prototype.getLoadedProgress=function(){for(var t=this.values.length,e=0;this.dataPoints[e];)e++;return Math.round(e/t*100)},o.prototype.getLabel=function(){return this.graph.filterLabel},o.prototype.getColumn=function(){return this.column},o.prototype.getSelectedValue=function(){if(void 0!==this.index)return this.values[this.index]},o.prototype.getValues=function(){return this.values},o.prototype.getValue=function(t){if(t>=this.values.length)throw new Error("Index out of range");return this.values[t]},o.prototype._getDataPoints=function(t){if(void 0===t&&(t=this.index),void 0===t)return[];var e;if(this.dataPoints[t])e=this.dataPoints[t];else{var i={};i.column=this.column,i.value=this.values[t];var o=new n(this.dataGroup.getDataSet(),{filter:function(t){return t[i.column]==i.value}}).get();e=this.dataGroup._getDataPoints(o),this.dataPoints[t]=e}return e},o.prototype.setOnLoadCallback=function(t){this.onLoadCallback=t},o.prototype.selectValue=function(t){if(t>=this.values.length)throw new Error("Index out of range");this.index=t,this.value=this.values[t]},o.prototype.loadInBackground=function(t){void 0===t&&(t=0);var e=this.graph.frame;if(t0){var n=i.groupsData.getDataSet();n.get().forEach(function(t){if(t.nestedGroups){0!=t.showNested&&(t.showNested=!0);var e=[];t.nestedGroups.forEach(function(i){var o=n.get(i);o&&(o.nestedInGroup=t.id,0==t.showNested&&(o.visible=!1),e=e.concat(o))}),n.update(e,o)}})}},update:function(t,e,o){i._onUpdateGroups(e.items)},remove:function(t,e,o){i._onRemoveGroups(e.items)}},this.items={},this.groups={},this.groupIds=[],this.selection=[],this.popup=null,this.touchParams={},this.groupTouchParams={},this._create(),this.setOptions(e)}var s=i(29),r=o(s),a=i(6),h=o(a),d=i(10),l=i(2),u=i(11),c=i(12),p=i(66),f=i(16),m=i(68),v=i(69),g=i(101),y=i(102),b=i(70),_=i(103),w=i(104).default,x="__ungrouped__",k="__background__";n.prototype=new f,n.types={background:_,box:g,range:b,point:y},n.prototype._create=function(){var t=document.createElement("div");t.className="vis-itemset",t["timeline-itemset"]=this,this.dom.frame=t;var e=document.createElement("div");e.className="vis-background",t.appendChild(e),this.dom.background=e;var i=document.createElement("div");i.className="vis-foreground",t.appendChild(i),this.dom.foreground=i;var o=document.createElement("div");o.className="vis-axis",this.dom.axis=o;var n=document.createElement("div");n.className="vis-labelset",this.dom.labelSet=n,this._updateUngrouped();var s=new v(k,null,this);s.show(),this.groups[k]=s,this.hammer=new d(this.body.dom.centerContainer),this.hammer.on("hammer.input",function(t){t.isFirst&&this._onTouch(t)}.bind(this)),this.hammer.on("panstart",this._onDragStart.bind(this)),this.hammer.on("panmove",this._onDrag.bind(this)),this.hammer.on("panend",this._onDragEnd.bind(this)),this.hammer.get("pan").set({threshold:5,direction:d.DIRECTION_HORIZONTAL}),this.hammer.on("tap",this._onSelectItem.bind(this)),this.hammer.on("press",this._onMultiSelectItem.bind(this)),this.hammer.on("doubletap",this._onAddItem.bind(this)),this.options.rtl?this.groupHammer=new d(this.body.dom.rightContainer):this.groupHammer=new d(this.body.dom.leftContainer),this.groupHammer.on("tap",this._onGroupClick.bind(this)),this.groupHammer.on("panstart",this._onGroupDragStart.bind(this)),this.groupHammer.on("panmove",this._onGroupDrag.bind(this)),this.groupHammer.on("panend",this._onGroupDragEnd.bind(this)),this.groupHammer.get("pan").set({threshold:5,direction:d.DIRECTION_VERTICAL}),this.body.dom.centerContainer.addEventListener("mouseover",this._onMouseOver.bind(this)),this.body.dom.centerContainer.addEventListener("mouseout",this._onMouseOut.bind(this)),this.body.dom.centerContainer.addEventListener("mousemove",this._onMouseMove.bind(this)),this.body.dom.centerContainer.addEventListener("contextmenu",this._onDragEnd.bind(this)),this.body.dom.centerContainer.addEventListener("mousewheel",this._onMouseWheel.bind(this)),this.show()},n.prototype.setOptions=function(t){if(t){var e=["type","rtl","align","order","stack","stackSubgroups","selectable","multiselect","multiselectPerGroup","groupOrder","dataAttributes","template","groupTemplate","visibleFrameTemplate","hide","snap","groupOrderSwap","showTooltips","tooltip","tooltipOnItemUpdateTime"];l.selectiveExtend(e,this.options,t),"itemsAlwaysDraggable"in t&&("boolean"==typeof t.itemsAlwaysDraggable?(this.options.itemsAlwaysDraggable.item=t.itemsAlwaysDraggable,this.options.itemsAlwaysDraggable.range=!1):"object"===(0,h.default)(t.itemsAlwaysDraggable)&&(l.selectiveExtend(["item","range"],this.options.itemsAlwaysDraggable,t.itemsAlwaysDraggable),this.options.itemsAlwaysDraggable.item||(this.options.itemsAlwaysDraggable.range=!1))),"orientation"in t&&("string"==typeof t.orientation?this.options.orientation.item="top"===t.orientation?"top":"bottom":"object"===(0,h.default)(t.orientation)&&"item"in t.orientation&&(this.options.orientation.item=t.orientation.item)),"margin"in t&&("number"==typeof t.margin?(this.options.margin.axis=t.margin,this.options.margin.item.horizontal=t.margin,this.options.margin.item.vertical=t.margin):"object"===(0,h.default)(t.margin)&&(l.selectiveExtend(["axis"],this.options.margin,t.margin),"item"in t.margin&&("number"==typeof t.margin.item?(this.options.margin.item.horizontal=t.margin.item,this.options.margin.item.vertical=t.margin.item):"object"===(0,h.default)(t.margin.item)&&l.selectiveExtend(["horizontal","vertical"],this.options.margin.item,t.margin.item)))),"editable"in t&&("boolean"==typeof t.editable?(this.options.editable.updateTime=t.editable,this.options.editable.updateGroup=t.editable,this.options.editable.add=t.editable,this.options.editable.remove=t.editable,this.options.editable.overrideItems=!1):"object"===(0,h.default)(t.editable)&&l.selectiveExtend(["updateTime","updateGroup","add","remove","overrideItems"],this.options.editable,t.editable)),"groupEditable"in t&&("boolean"==typeof t.groupEditable?(this.options.groupEditable.order=t.groupEditable,this.options.groupEditable.add=t.groupEditable,this.options.groupEditable.remove=t.groupEditable):"object"===(0,h.default)(t.groupEditable)&&l.selectiveExtend(["order","add","remove"],this.options.groupEditable,t.groupEditable));["onDropObjectOnItem","onAdd","onUpdate","onRemove","onMove","onMoving","onAddGroup","onMoveGroup","onRemoveGroup"].forEach(function(e){var i=t[e];if(i){if(!(i instanceof Function))throw new Error("option "+e+" must be a function "+e+"(item, callback)");this.options[e]=i}}.bind(this)),this.markDirty()}},n.prototype.markDirty=function(t){this.groupIds=[],t&&t.refreshItems&&l.forEach(this.items,function(t){t.dirty=!0,t.displayed&&t.redraw()})},n.prototype.destroy=function(){this.hide(),this.setItems(null),this.setGroups(null),this.hammer=null,this.body=null,this.conversion=null},n.prototype.hide=function(){this.dom.frame.parentNode&&this.dom.frame.parentNode.removeChild(this.dom.frame),this.dom.axis.parentNode&&this.dom.axis.parentNode.removeChild(this.dom.axis),this.dom.labelSet.parentNode&&this.dom.labelSet.parentNode.removeChild(this.dom.labelSet)},n.prototype.show=function(){this.dom.frame.parentNode||this.body.dom.center.appendChild(this.dom.frame),this.dom.axis.parentNode||this.body.dom.backgroundVertical.appendChild(this.dom.axis),this.dom.labelSet.parentNode||(this.options.rtl?this.body.dom.right.appendChild(this.dom.labelSet):this.body.dom.left.appendChild(this.dom.labelSet))},n.prototype.setSelection=function(t){var e,i,o,n;for(void 0==t&&(t=[]),Array.isArray(t)||(t=[t]),e=0,i=this.selection.length;et&&o.push(h.id):h.lefte&&o.push(h.id)}return o},n.prototype._deselect=function(t){for(var e=this.selection,i=0,o=e.length;i0){for(var w={},x=0;x<_;x++)l.forEach(b,function(t,e){w[e]=t[x]()});l.forEach(this.groups,function(t,e){if(e!==k){var i=w[e];s=i||s,g+=t.height}}),g=Math.max(g,y)}return g=Math.max(g,y),r.style.height=i(g),this.props.width=r.offsetWidth,this.props.height=g,this.dom.axis.style.top=i("top"==n?this.body.domProps.top.height+this.body.domProps.border.top:this.body.domProps.top.height+this.body.domProps.centerContainer.height),this.options.rtl?this.dom.axis.style.right="0":this.dom.axis.style.left="0",this.initialItemSetDrawn=!0,s=this._isResized()||s},n.prototype._firstGroup=function(){var t="top"==this.options.orientation.item?0:this.groupIds.length-1,e=this.groupIds[t];return this.groups[e]||this.groups[x]||null},n.prototype._updateUngrouped=function(){var t,e,i=this.groups[x];if(this.groupsData){if(i){i.hide(),delete this.groups[x];for(e in this.items)if(this.items.hasOwnProperty(e)){t=this.items[e],t.parent&&t.parent.remove(t);var o=this._getGroupId(t.data),n=this.groups[o];n&&n.add(t)||t.hide()}}}else if(!i){i=new m(null,null,this),this.groups[x]=i;for(e in this.items)this.items.hasOwnProperty(e)&&(t=this.items[e],i.add(t));i.show()}},n.prototype.getLabelSet=function(){return this.dom.labelSet},n.prototype.setItems=function(t){var e,i=this,o=this.itemsData;if(t){if(!(t instanceof u||t instanceof c))throw new TypeError("Data must be an instance of DataSet or DataView");this.itemsData=t}else this.itemsData=null;if(o&&(l.forEach(this.itemListeners,function(t,e){o.off(e,t)}),e=o.getIds(),this._onRemove(e)),this.itemsData){var n=this.id;l.forEach(this.itemListeners,function(t,e){i.itemsData.on(e,t,n)}),e=this.itemsData.getIds(),this._onAdd(e),this._updateUngrouped()}this.body.emitter.emit("_change",{queue:!0})},n.prototype.getItems=function(){return this.itemsData},n.prototype.setGroups=function(t){var e,i=this;if(this.groupsData&&(l.forEach(this.groupListeners,function(t,e){i.groupsData.off(e,t)}),e=this.groupsData.getIds(),this.groupsData=null,this._onRemoveGroups(e)),t){if(!(t instanceof u||t instanceof c))throw new TypeError("Data must be an instance of DataSet or DataView");this.groupsData=t}else this.groupsData=null;if(this.groupsData){var o=this.groupsData;this.groupsData instanceof c&&(o=this.groupsData.getDataSet()),o.get().forEach(function(t){t.nestedGroups&&t.nestedGroups.forEach(function(e){var i=o.get(e);i.nestedInGroup=t.id,0==t.showNested&&(i.visible=!1),o.update(i)})});var n=this.id;l.forEach(this.groupListeners,function(t,e){i.groupsData.on(e,t,n)}),e=this.groupsData.getIds(),this._onAddGroups(e)}this._updateUngrouped(),this._order(),this.body.emitter.emit("_change",{queue:!0})},n.prototype.getGroups=function(){return this.groupsData},n.prototype.removeItem=function(t){var e=this.itemsData.get(t),i=this.itemsData.getDataSet();e&&this.options.onRemove(e,function(e){e&&i.remove(t)})},n.prototype._getType=function(t){return t.type||this.options.type||(t.end?"range":"box")},n.prototype._getGroupId=function(t){return"background"==this._getType(t)&&void 0==t.group?k:this.groupsData?t.group:x},n.prototype._onUpdate=function(t){var e=this;t.forEach(function(t){var i,o=e.itemsData.get(t,e.itemOptions),s=e.items[t],r=o?e._getType(o):null,a=n.types[r];if(s&&(a&&s instanceof a?e._updateItem(s,o):(i=s.selected,e._removeItem(s),s=null)),!s&&o){if(!a)throw"rangeoverflow"==r?new TypeError('Item type "rangeoverflow" is deprecated. Use css styling instead: .vis-item.vis-range .vis-item-content {overflow: visible;}'):new TypeError('Unknown item type "'+r+'"');s=new a(o,e.conversion,e.options),s.id=t,e._addItem(s),i&&(this.selection.push(t),s.select())}}.bind(this)),this._order(),this.body.emitter.emit("_change",{queue:!0})},n.prototype._onAdd=n.prototype._onUpdate,n.prototype._onRemove=function(t){var e=0,i=this;t.forEach(function(t){var o=i.items[t];o&&(e++,i._removeItem(o))}),e&&(this._order(),this.body.emitter.emit("_change",{queue:!0}))},n.prototype._order=function(){l.forEach(this.groups,function(t){t.order()})},n.prototype._onUpdateGroups=function(t){this._onAddGroups(t)},n.prototype._onAddGroups=function(t){var e=this;t.forEach(function(t){var i=e.groupsData.get(t),o=e.groups[t];if(o)o.setData(i);else{if(t==x||t==k)throw new Error("Illegal group id. "+t+" is a reserved id.");var n=(0,r.default)(e.options);l.extend(n,{height:null}),o=new m(t,i,e),e.groups[t]=o;for(var s in e.items)if(e.items.hasOwnProperty(s)){var a=e.items[s];a.data.group==t&&o.add(a)}o.order(),o.show()}}),this.body.emitter.emit("_change",{queue:!0})},n.prototype._onRemoveGroups=function(t){var e=this.groups;t.forEach(function(t){var i=e[t];i&&(i.hide(),delete e[t])}),this.markDirty(),this.body.emitter.emit("_change",{queue:!0})},n.prototype._orderGroups=function(){if(this.groupsData){var t=this.groupsData.getIds({order:this.options.groupOrder});t=this._orderNestedGroups(t);var e=!l.equalArray(t,this.groupIds);if(e){var i=this.groups;t.forEach(function(t){i[t].hide()}),t.forEach(function(t){i[t].show()}),this.groupIds=t}return e}return!1},n.prototype._orderNestedGroups=function(t){var e=[];return t.forEach(function(t){var i=this.groupsData.get(t);if(i.nestedInGroup||e.push(t),i.nestedGroups){var o=this.groupsData.get({filter:function(e){return e.nestedInGroup==t},order:this.options.groupOrder}),n=o.map(function(t){return t.id});e=e.concat(n)}},this),e},n.prototype._addItem=function(t){this.items[t.id]=t;var e=this._getGroupId(t.data),i=this.groups[e];i?i&&i.data&&i.data.showNested&&(t.groupShowing=!0):t.groupShowing=!1,i&&i.add(t)},n.prototype._updateItem=function(t,e){t.setData(e);var i=this._getGroupId(t.data),o=this.groups[i];o?o&&o.data&&o.data.showNested&&(t.groupShowing=!0):t.groupShowing=!1},n.prototype._removeItem=function(t){t.hide(),delete this.items[t.id];var e=this.selection.indexOf(t.id);-1!=e&&this.selection.splice(e,1),t.parent&&t.parent.remove(t)},n.prototype._constructByEndArray=function(t){for(var e=[],i=0;in)return}}if(i&&i!=this.groupTouchParams.group){var a=e.get(i.groupId),h=e.get(this.groupTouchParams.group.groupId);h&&a&&(this.options.groupOrderSwap(h,a,e),e.update(h),e.update(a));var d=e.getIds({order:this.options.groupOrder});if(!l.equalArray(d,this.groupTouchParams.originalOrder))for(var u=this.groupTouchParams.originalOrder,p=this.groupTouchParams.group.groupId,f=Math.min(u.length,d.length),m=0,v=0,g=0;m=f)break;if(d[m+v]==p)v=1;else if(u[m+g]==p)g=1;else{var y=d.indexOf(u[m+g]),b=e.get(d[m+v]),_=e.get(u[m+g]);this.options.groupOrderSwap(b,_,e),e.update(b),e.update(_);var w=d[m+v];d[m+v]=u[m+g],d[y]=w,m++}}}}},n.prototype._onGroupDragEnd=function(t){if(this.options.groupEditable.order&&this.groupTouchParams.group){t.stopPropagation();var e=this,i=e.groupTouchParams.group.groupId,o=e.groupsData.getDataSet(),n=l.extend({},o.get(i));e.options.onMoveGroup(n,function(t){if(t)t[o._fieldId]=i,o.update(t);else{var n=o.getIds({order:e.options.groupOrder});if(!l.equalArray(n,e.groupTouchParams.originalOrder))for(var s=e.groupTouchParams.originalOrder,r=Math.min(s.length,n.length),a=0;a=r)break;var h=n.indexOf(s[a]),d=o.get(n[a]),u=o.get(s[a]);e.options.groupOrderSwap(d,u,o),o.update(d),o.update(u);var c=n[a];n[a]=s[a],n[h]=c,a++}}}),e.body.emitter.emit("groupDragged",{groupId:i})}},n.prototype._onSelectItem=function(t){if(this.options.selectable){var e=t.srcEvent&&(t.srcEvent.ctrlKey||t.srcEvent.metaKey),i=t.srcEvent&&t.srcEvent.shiftKey;if(e||i)return void this._onMultiSelectItem(t);var o=this.getSelection(),n=this.itemFromTarget(t),s=n?[n.id]:[];this.setSelection(s);var r=this.getSelection();(r.length>0||o.length>0)&&this.body.emitter.emit("select",{items:r,event:t})}},n.prototype._onMouseOver=function(t){var e=this.itemFromTarget(t);if(e){if(e!==this.itemFromRelatedTarget(t)){var i=e.getTitle();if(this.options.showTooltips&&i){null==this.popup&&(this.popup=new w(this.body.dom.root,this.options.tooltip.overflowMethod||"flip")),this.popup.setText(i);var o=this.body.dom.centerContainer;this.popup.setPosition(t.clientX-l.getAbsoluteLeft(o)+o.offsetLeft,t.clientY-l.getAbsoluteTop(o)+o.offsetTop),this.popup.show()}else null!=this.popup&&this.popup.hide();this.body.emitter.emit("itemover",{item:e.id,event:t})}}},n.prototype._onMouseOut=function(t){var e=this.itemFromTarget(t);if(e){e!==this.itemFromRelatedTarget(t)&&(null!=this.popup&&this.popup.hide(),this.body.emitter.emit("itemout",{item:e.id,event:t}))}},n.prototype._onMouseMove=function(t){if(this.itemFromTarget(t)&&this.options.showTooltips&&this.options.tooltip.followMouse&&this.popup&&!this.popup.hidden){var e=this.body.dom.centerContainer;this.popup.setPosition(t.clientX-l.getAbsoluteLeft(e)+e.offsetLeft,t.clientY-l.getAbsoluteTop(e)+e.offsetTop),this.popup.show()}},n.prototype._onMouseWheel=function(t){this.touchParams.itemIsDragging&&this._onDragEnd(t)},n.prototype._onUpdateItem=function(t){if(this.options.selectable&&this.options.editable.add){var e=this;if(t){var i=e.itemsData.get(t.id);this.options.onUpdate(i,function(t){t&&e.itemsData.getDataSet().update(t)})}}},n.prototype._onDropObjectOnItem=function(t){var e=this.itemFromTarget(t),i=JSON.parse(t.dataTransfer.getData("text"));this.options.onDropObjectOnItem(i,e)},n.prototype._onAddItem=function(t){if(this.options.selectable&&this.options.editable.add){var e,i,o=this,n=this.options.snap||null;this.options.rtl?(e=l.getAbsoluteRight(this.dom.frame),i=e-t.center.x):(e=l.getAbsoluteLeft(this.dom.frame),i=t.center.x-e);var s,r,a=this.body.util.toTime(i),h=this.body.util.getScale(),d=this.body.util.getStep();"drop"==t.type?(r=JSON.parse(t.dataTransfer.getData("text")),r.content=r.content?r.content:"new item",r.start=r.start?r.start:n?n(a,h,d):a,r.type=r.type||"box",r[this.itemsData._fieldId]=r.id||l.randomUUID(),"range"!=r.type||r.end||(s=this.body.util.toTime(i+this.props.width/5),r.end=n?n(s,h,d):s)):(r={start:n?n(a,h,d):a,content:"new item"},r[this.itemsData._fieldId]=l.randomUUID(),"range"===this.options.type&&(s=this.body.util.toTime(i+this.props.width/5),r.end=n?n(s,h,d):s));var u=this.groupFromTarget(t);u&&(r.group=u.groupId),r=this._cloneItemData(r),this.options.onAdd(r,function(e){e&&(o.itemsData.getDataSet().add(e),"drop"==t.type&&o.setSelection([e.id]))})}},n.prototype._onMultiSelectItem=function(t){if(this.options.selectable){var e=this.itemFromTarget(t);if(e){ +var i=this.options.multiselect?this.getSelection():[];if((t.srcEvent&&t.srcEvent.shiftKey||!1)&&this.options.multiselect){var o=this.itemsData.get(e.id).group,s=void 0;this.options.multiselectPerGroup&&i.length>0&&(s=this.itemsData.get(i[0]).group),this.options.multiselectPerGroup&&void 0!=s&&s!=o||i.push(e.id);var r=n._getItemRange(this.itemsData.get(i,this.itemOptions));if(!this.options.multiselectPerGroup||s==o){i=[];for(var a in this.items)if(this.items.hasOwnProperty(a)){var h=this.items[a],d=h.data.start,l=void 0!==h.data.end?h.data.end:d;!(d>=r.min&&l<=r.max)||this.options.multiselectPerGroup&&s!=this.itemsData.get(h.id).group||h instanceof _||i.push(h.id)}}}else{var u=i.indexOf(e.id);-1==u?i.push(e.id):i.splice(u,1)}this.setSelection(i),this.body.emitter.emit("select",{items:this.getSelection(),event:t})}}},n._getItemRange=function(t){var e=null,i=null;return t.forEach(function(t){(null==i||t.starte)&&(e=t.end):(null==e||t.start>e)&&(e=t.start)}),{min:i,max:e}},n.prototype.itemFromElement=function(t){for(var e=t;e;){if(e.hasOwnProperty("timeline-item"))return e["timeline-item"];e=e.parentNode}return null},n.prototype.itemFromTarget=function(t){return this.itemFromElement(t.target)},n.prototype.itemFromRelatedTarget=function(t){return this.itemFromElement(t.relatedTarget)},n.prototype.groupFromTarget=function(t){var e=t.center?t.center.y:t.clientY,i=this.groupIds;i.length<=0&&this.groupsData&&(i=this.groupsData.getIds({order:this.options.groupOrder}));for(var o=0;oa&&ea)return s}else if(0===o&&es&&(s=r.top+r.height)}while(a)}}o.height=s-o.top+.5*i.item.vertical},e.nostack=function(t,i,o,n){for(var s=0;so[r].index&&e.collisionByTimes(o[n],o[r])){s=o[r];break}null!=s&&(o[n].top=s.top+s.height)}while(s)}for(var a=0;ao[h].index&&(o[r].top+=o[h].height);for(var d=t[r],l=0;le.right&&t.top-i.vertical+.001e.top:t.left-i.horizontal+.001e.left&&t.top-i.vertical+.001e.top},e.collisionByTimes=function(t,e){return t.start<=e.start&&t.end>=e.start&&t.tope.top||e.start<=t.start&&e.end>=t.start&&e.topt.top}},function(t,e,i){function o(t,e,i){if(this.props={dot:{width:0,height:0},line:{width:0,height:0}},this.options=i,t&&void 0==t.start)throw new Error('Property "start" missing in item '+t);n.call(this,t,e,i)}var n=i(38);o.prototype=new n(null,null,null),o.prototype.isVisible=function(t){var e=this.options.align,i=this.width*t.getMillisecondsPerPixel();return"right"==e?this.data.start.getTime()>t.start&&this.data.start.getTime()-it.start&&this.data.start.getTime()t.start&&this.data.start.getTime()-i/2t.start&&this.data.startt.start},o.prototype._createDomElement=function(){this.dom||(this.dom={},this.dom.box=document.createElement("div"),this.dom.frame=document.createElement("div"),this.dom.frame.className="vis-item-overflow",this.dom.box.appendChild(this.dom.frame),this.dom.content=document.createElement("div"),this.dom.content.className="vis-item-content",this.dom.frame.appendChild(this.dom.content),this.dirty=!0)},o.prototype._appendDomElement=function(){if(!this.parent)throw new Error("Cannot redraw item: no parent attached");if(!this.dom.box.parentNode){var t=this.parent.dom.background;if(!t)throw new Error("Cannot redraw item: parent has no background container element");t.appendChild(this.dom.box)}this.displayed=!0},o.prototype._updateDirtyDomComponents=function(){if(this.dirty){this._updateContents(this.dom.content),this._updateDataAttributes(this.dom.content),this._updateStyle(this.dom.box);var t=(this.data.className?" "+this.data.className:"")+(this.selected?" vis-selected":"");this.dom.box.className=this.baseClassName+t}},o.prototype._getDomComponentsSizes=function(){return this.overflow="hidden"!==window.getComputedStyle(this.dom.content).overflow,{content:{width:this.dom.content.offsetWidth}}},o.prototype._updateDomComponentsSizes=function(t){this.props.content.width=t.content.width,this.height=0,this.dirty=!1},o.prototype._repaintDomAdditionals=function(){},o.prototype.redraw=function(t){var e,i=[this._createDomElement.bind(this),this._appendDomElement.bind(this),this._updateDirtyDomComponents.bind(this),function(){this.dirty&&(e=this._getDomComponentsSizes.bind(this)())}.bind(this),function(){this.dirty&&this._updateDomComponentsSizes.bind(this)(e)}.bind(this),this._repaintDomAdditionals.bind(this)];if(t)return i;var o;return i.forEach(function(t){o=t()}),o},o.prototype.show=r.prototype.show,o.prototype.hide=r.prototype.hide,o.prototype.repositionX=r.prototype.repositionX,o.prototype.repositionY=function(t){var e,i=this.options.orientation.item;if(void 0!==this.data.subgroup){var o=this.data.subgroup;this.dom.box.style.height=this.parent.subgroups[o].height+"px",this.dom.box.style.top="top"==i?this.parent.top+this.parent.subgroups[o].top+"px":this.parent.top+this.parent.height-this.parent.subgroups[o].top-this.parent.subgroups[o].height+"px",this.dom.box.style.bottom=""}else this.parent instanceof s?(e=Math.max(this.parent.height,this.parent.itemSet.body.domProps.center.height,this.parent.itemSet.body.domProps.centerContainer.height),this.dom.box.style.bottom="bottom"==i?"0":"",this.dom.box.style.top="top"==i?"0":""):(e=this.parent.height,this.dom.box.style.top=this.parent.top+"px",this.dom.box.style.bottom="");this.dom.box.style.height=e+"px"},t.exports=o},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=function(){function t(e,i){(0,s.default)(this,t),this.container=e,this.overflowMethod=i||"cap",this.x=0,this.y=0,this.padding=5,this.hidden=!1,this.frame=document.createElement("div"),this.frame.className="vis-tooltip",this.container.appendChild(this.frame)}return(0,a.default)(t,[{key:"setPosition",value:function(t,e){this.x=parseInt(t),this.y=parseInt(e)}},{key:"setText",value:function(t){t instanceof Element?(this.frame.innerHTML="",this.frame.appendChild(t)):this.frame.innerHTML=t}},{key:"show",value:function(t){if(void 0===t&&(t=!0),!0===t){var e=this.frame.clientHeight,i=this.frame.clientWidth,o=this.frame.parentNode.clientHeight,n=this.frame.parentNode.clientWidth,s=0,r=0;if("flip"==this.overflowMethod){var a=!1,h=!0;this.y-en-this.padding&&(a=!0),s=a?this.x-i:this.x,r=h?this.y-e:this.y}else r=this.y-e,r+e+this.padding>o&&(r=o-e-this.padding),rn&&(s=n-i-this.padding),s0){var r={};for(this._getRelevantData(s,r,o,n),this._applySampling(s,r),e=0;e0)switch(t.options.style){case"line":d.hasOwnProperty(s[e])||(d[s[e]]=m.calcPath(r[s[e]],t)),m.draw(d[s[e]],t,this.framework);case"point":case"points":"point"!=t.options.style&&"points"!=t.options.style&&1!=t.options.drawPoints.enabled||v.draw(r[s[e]],t,this.framework)}}}return a.cleanupElements(this.svgElements),!1},o.prototype._stack=function(t,e){var i,o,n,s,r;i=0;for(var a=0;at[a].x){r=e[h],s=0==h?r:e[h-1],i=h;break}}void 0===r&&(s=e[e.length-1],r=e[e.length-1]),o=r.x-s.x,n=r.y-s.y,t[a].y=0==o?t[a].orginalY+r.y:t[a].orginalY+n/o*(t[a].x-s.x)+s.y}},o.prototype._getRelevantData=function(t,e,i,o){var n,s,a,h;if(t.length>0)for(s=0;s0)for(var o=0;o0){var s=1,r=n.length,a=this.body.util.toGlobalScreen(n[n.length-1].x)-this.body.util.toGlobalScreen(n[0].x),h=r/a;s=Math.min(Math.ceil(.2*r),Math.max(1,Math.round(h)));for(var d=new Array(r),l=0;l0){for(s=0;s0&&(n=this.groups[t[s]],!0===r.stack&&"bar"===r.style?"left"===r.yAxisOrientation?a=a.concat(o):h=h.concat(o):i[t[s]]=n.getYRange(o,t[s]));f.getStackedYRange(a,i,t,"__barStackLeft","left"),f.getStackedYRange(h,i,t,"__barStackRight","right")}},o.prototype._updateYAxis=function(t,e){var i,o,n=!1,s=!1,r=!1,a=1e9,h=1e9,d=-1e9,l=-1e9;if(t.length>0){for(var u=0;ui?i:a,d=di?i:h,l=l=0&&t._redrawLabel(o-2,e.val,i,"vis-y-axis vis-major",t.props.majorCharHeight),!0===t.master&&(n?t._redrawLine(o,i,"vis-grid vis-horizontal vis-major",t.options.majorLinesOffset,t.props.majorLineWidth):t._redrawLine(o,i,"vis-grid vis-horizontal vis-minor",t.options.minorLinesOffset,t.props.minorLineWidth))});var r=0;void 0!==this.options[i].title&&void 0!==this.options[i].title.text&&(r=this.props.titleCharHeight);var h=!0===this.options.icons?Math.max(this.options.iconWidth,r)+this.options.labelOffsetX+15:r+this.options.labelOffsetX+15;return this.maxLabelSize>this.width-h&&!0===this.options.visible?(this.width=this.maxLabelSize+h,this.options.width=this.width+"px",a.cleanupElements(this.DOMelements.lines),a.cleanupElements(this.DOMelements.labels),this.redraw(),e=!0):this.maxLabelSizethis.minWidth?(this.width=Math.max(this.minWidth,this.maxLabelSize+h),this.options.width=this.width+"px",a.cleanupElements(this.DOMelements.lines),a.cleanupElements(this.DOMelements.labels),this.redraw(),e=!0):(a.cleanupElements(this.DOMelements.lines),a.cleanupElements(this.DOMelements.labels),e=!1),e},o.prototype.convertValue=function(t){return this.scale.convertValue(t)},o.prototype.screenToValue=function(t){return this.scale.screenToValue(t)},o.prototype._redrawLabel=function(t,e,i,o,n){var s=a.getDOMElement("div",this.DOMelements.labels,this.dom.frame);s.className=o,s.innerHTML=e,"left"===i?(s.style.left="-"+this.options.labelOffsetX+"px",s.style.textAlign="right"):(s.style.right="-"+this.options.labelOffsetX+"px",s.style.textAlign="left"),s.style.top=t-.5*n+this.options.labelOffsetY+"px",e+="";var r=Math.max(this.props.majorCharWidth,this.props.minorCharWidth);this.maxLabelSize6&&void 0!==arguments[6]&&arguments[6],a=arguments.length>7&&void 0!==arguments[7]&&arguments[7];if(this.majorSteps=[1,2,5,10],this.minorSteps=[.25,.5,1,2],this.customLines=null,this.containerHeight=n,this.majorCharHeight=s,this._start=t,this._end=e,this.scale=1,this.minorStepIdx=-1,this.magnitudefactor=1,this.determineScale(),this.zeroAlign=r,this.autoScaleStart=i,this.autoScaleEnd=o,this.formattingFunction=a,i||o){var h=this,d=function(t){var e=t-t%(h.magnitudefactor*h.minorSteps[h.minorStepIdx]);return t%(h.magnitudefactor*h.minorSteps[h.minorStepIdx])>h.magnitudefactor*h.minorSteps[h.minorStepIdx]*.5?e+h.magnitudefactor*h.minorSteps[h.minorStepIdx]:e};i&&(this._start-=2*this.magnitudefactor*this.minorSteps[this.minorStepIdx],this._start=d(this._start)),o&&(this._end+=this.magnitudefactor*this.minorSteps[this.minorStepIdx],this._end=d(this._end)),this.determineScale()}}o.prototype.setCharHeight=function(t){this.majorCharHeight=t},o.prototype.setHeight=function(t){this.containerHeight=t},o.prototype.determineScale=function(){var t=this._end-this._start;this.scale=this.containerHeight/t;var e=this.majorCharHeight/this.scale,i=t>0?Math.round(Math.log(t)/Math.LN10):0;this.minorStepIdx=-1,this.magnitudefactor=Math.pow(10,i);var o=0;i<0&&(o=i);for(var n=!1,s=o;Math.abs(s)<=Math.abs(i);s++){this.magnitudefactor=Math.pow(10,s);for(var r=0;r=e){n=!0,this.minorStepIdx=r;break}}if(!0===n)break}},o.prototype.is_major=function(t){return t%(this.magnitudefactor*this.majorSteps[this.minorStepIdx])==0},o.prototype.getStep=function(){return this.magnitudefactor*this.minorSteps[this.minorStepIdx]},o.prototype.getFirstMajor=function(){var t=this.magnitudefactor*this.majorSteps[this.minorStepIdx];return this.convertValue(this._start+(t-this._start%t)%t)},o.prototype.formatValue=function(t){var e=t.toPrecision(5);return"function"==typeof this.formattingFunction&&(e=this.formattingFunction(t)),"number"==typeof e?""+e:"string"==typeof e?e:t.toPrecision(5)},o.prototype.getLines=function(){for(var t=[],e=this.getStep(),i=(e-this._start%e)%e,o=this._start+i;this._end-o>1e-5;o+=e)o!=this._start&&t.push({major:this.is_major(o),y:this.convertValue(o),val:this.formatValue(o)});return t},o.prototype.followScale=function(t){var e=this.minorStepIdx,i=this._start,o=this._end,n=this,s=function(){n.magnitudefactor*=2},r=function(){n.magnitudefactor/=2};t.minorStepIdx<=1&&this.minorStepIdx<=1||t.minorStepIdx>1&&this.minorStepIdx>1||(t.minorStepIdxo+1e-5)r(),d=!1;else{if(!this.autoScaleStart&&this._start=0)){r(),d=!1;continue}console.warn("Can't adhere to given 'min' range, due to zeroalign")}this.autoScaleStart&&this.autoScaleEnd&&ue.x?1:-1})):this.itemsData=[]},o.prototype.getItems=function(){return this.itemsData},o.prototype.setZeroPosition=function(t){this.zeroPosition=t},o.prototype.setOptions=function(t){if(void 0!==t){var e=["sampling","style","sort","yAxisOrientation","barChart","zIndex","excludeFromStacking","excludeFromLegend"];r.selectiveDeepExtend(e,this.options,t),"function"==typeof t.drawPoints&&(t.drawPoints={onRender:t.drawPoints}),r.mergeOptions(this.options,t,"interpolation"),r.mergeOptions(this.options,t,"drawPoints"),r.mergeOptions(this.options,t,"shaded"),t.interpolation&&"object"==(0,s.default)(t.interpolation)&&t.interpolation.parametrization&&("uniform"==t.interpolation.parametrization?this.options.interpolation.alpha=0:"chordal"==t.interpolation.parametrization?this.options.interpolation.alpha=1:(this.options.interpolation.parametrization="centripetal",this.options.interpolation.alpha=.5))}},o.prototype.update=function(t){this.group=t,this.content=t.content||"graph",this.className=t.className||this.className||"vis-graph-group"+this.groupsUsingDefaultStyles[0]%10,this.visible=void 0===t.visible||t.visible,this.style=t.style,this.setOptions(t.options)},o.prototype.getLegend=function(t,e,i,o,n){if(void 0==i||null==i){i={svg:document.createElementNS("http://www.w3.org/2000/svg","svg"),svgElements:{},options:this.options,groups:[this]}}switch(void 0!=o&&null!=o||(o=0),void 0!=n&&null!=n||(n=.5*e),this.options.style){case"line":h.drawIcon(this,o,n,t,e,i);break;case"points":case"point":d.drawIcon(this,o,n,t,e,i);break;case"bar":a.drawIcon(this,o,n,t,e,i)}return{icon:i.svg,label:this.content,orientation:this.options.yAxisOrientation}},o.prototype.getYRange=function(t){for(var e=t[0].y,i=t[0].y,o=0;ot[o].y?t[o].y:e,i=i0&&(i=Math.min(i,Math.abs(e[o-1].screen_x-e[o].screen_x))),0===i&&(void 0===t[e[o].screen_x]&&(t[e[o].screen_x]={amount:0,resolved:0,accumulatedPositive:0,accumulatedNegative:0}),t[e[o].screen_x].amount+=1)},o._getSafeDrawData=function(t,e,i){var o,n;return t0?(o=t0){t.sort(function(t,e){return t.screen_x===e.screen_x?t.groupIde[s].screen_y?e[s].screen_y:o,n=nt[r].accumulatedNegative?t[r].accumulatedNegative:o,o=o>t[r].accumulatedPositive?t[r].accumulatedPositive:o,n=n0){return 1==e.options.interpolation.enabled?o._catmullRom(t,e):o._linear(t)}},o.drawIcon=function(t,e,i,o,s,r){var a,h,d=.5*s,l=n.getSVGElement("rect",r.svgElements,r.svg);if(l.setAttributeNS(null,"x",e),l.setAttributeNS(null,"y",i-d),l.setAttributeNS(null,"width",o),l.setAttributeNS(null,"height",2*d),l.setAttributeNS(null,"class","vis-outline"),a=n.getSVGElement("path",r.svgElements,r.svg),a.setAttributeNS(null,"class",t.className),void 0!==t.style&&a.setAttributeNS(null,"style",t.style),a.setAttributeNS(null,"d","M"+e+","+i+" L"+(e+o)+","+i),1==t.options.shaded.enabled&&(h=n.getSVGElement("path",r.svgElements,r.svg),"top"==t.options.shaded.orientation?h.setAttributeNS(null,"d","M"+e+", "+(i-d)+"L"+e+","+i+" L"+(e+o)+","+i+" L"+(e+o)+","+(i-d)):h.setAttributeNS(null,"d","M"+e+","+i+" L"+e+","+(i+d)+" L"+(e+o)+","+(i+d)+"L"+(e+o)+","+i),h.setAttributeNS(null,"class",t.className+" vis-icon-fill"),void 0!==t.options.shaded.style&&""!==t.options.shaded.style&&h.setAttributeNS(null,"style",t.options.shaded.style)),1==t.options.drawPoints.enabled){var u={style:t.options.drawPoints.style,styles:t.options.drawPoints.styles,size:t.options.drawPoints.size,className:t.className};n.drawPoint(e+.5*o,i,u,r.svgElements,r.svg)}},o.drawShading=function(t,e,i,o){if(1==e.options.shaded.enabled){var s=Number(o.svg.style.height.replace("px","")),r=n.getSVGElement("path",o.svgElements,o.svg),a="L";1==e.options.interpolation.enabled&&(a="C");var h,d=0;d="top"==e.options.shaded.orientation?0:"bottom"==e.options.shaded.orientation?s:Math.min(Math.max(0,e.zeroPosition),s),h="group"==e.options.shaded.orientation&&null!=i&&void 0!=i?"M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,a,!1)+" L"+i[i.length-1][0]+","+i[i.length-1][1]+" "+this.serializePath(i,a,!0)+i[0][0]+","+i[0][1]+" Z":"M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,a,!1)+" V"+d+" H"+t[0][0]+" Z",r.setAttributeNS(null,"class",e.className+" vis-fill"),void 0!==e.options.shaded.style&&r.setAttributeNS(null,"style",e.options.shaded.style),r.setAttributeNS(null,"d",h)}},o.draw=function(t,e,i){if(null!=t&&void 0!=t){var o=n.getSVGElement("path",i.svgElements,i.svg);o.setAttributeNS(null,"class",e.className),void 0!==e.style&&o.setAttributeNS(null,"style",e.style);var s="L";1==e.options.interpolation.enabled&&(s="C"),o.setAttributeNS(null,"d","M"+t[0][0]+","+t[0][1]+" "+this.serializePath(t,s,!1))}},o.serializePath=function(t,e,i){if(t.length<2)return"";var o,n=e;if(i)for(o=t.length-2;o>0;o--)n+=t[o][0]+","+t[o][1]+" ";else for(o=1;o0&&(f=1/f),m=3*v*(v+g),m>0&&(m=1/m),a={screen_x:(-b*o.screen_x+c*n.screen_x+_*s.screen_x)*f,screen_y:(-b*o.screen_y+c*n.screen_y+_*s.screen_y)*f},h={screen_x:(y*n.screen_x+p*s.screen_x-b*r.screen_x)*m,screen_y:(y*n.screen_y+p*s.screen_y-b*r.screen_y)*m},0==a.screen_x&&0==a.screen_y&&(a=n),0==h.screen_x&&0==h.screen_y&&(h=s),x.push([a.screen_x,a.screen_y]),x.push([h.screen_x,h.screen_y]),x.push([s.screen_x,s.screen_y]);return x},o._linear=function(t){for(var e=[],i=0;i");this.dom.textArea.innerHTML=r,this.dom.textArea.style.lineHeight=.75*this.options.iconSize+this.options.iconSpacing+"px"}},o.prototype.drawLegendIcons=function(){if(this.dom.frame.parentNode){var t=(0,s.default)(this.groups);t.sort(function(t,e){return t=0;i--){var a=s[i];a.nodes||(a.nodes=[]),-1===a.nodes.indexOf(n)&&a.nodes.push(n)}e.attr&&(n.attr=h(n.attr,e.attr))}function u(t,e){if(t.edges||(t.edges=[]),t.edges.push(e),t.edge){var i=h({},t.edge);e.attr=h(i,e.attr)}}function c(t,e,i,o,n){var s={from:e,to:i,type:o};return t.edge&&(s.attr=h({},t.edge)),s.attr=h(s.attr||{},n),s}function p(){for(F=I.NULL,L="";" "===z||"\t"===z||"\n"===z||"\r"===z;)s();do{var t=!1;if("#"===z){for(var e=A-1;" "===R.charAt(e)||"\t"===R.charAt(e);)e--;if("\n"===R.charAt(e)||""===R.charAt(e)){for(;""!=z&&"\n"!=z;)s();t=!0}}if("/"===z&&"/"===r()){for(;""!=z&&"\n"!=z;)s();t=!0}if("/"===z&&"*"===r()){for(;""!=z;){if("*"===z&&"/"===r()){s(),s();break}s()}t=!0}for(;" "===z||"\t"===z||"\n"===z||"\r"===z;)s()}while(t);if(""===z)return void(F=I.DELIMITER);var i=z+r();if(N[i])return F=I.DELIMITER,L=i,s(),void s();if(N[z])return F=I.DELIMITER,L=z,void s();if(a(z)||"-"===z){for(L+=z,s();a(z);)L+=z,s();return"false"===L?L=!1:"true"===L?L=!0:isNaN(Number(L))||(L=Number(L)),void(F=I.IDENTIFIER)}if('"'===z){for(s();""!=z&&('"'!=z||'"'===z&&'"'===r());)'"'===z?(L+=z,s()):"\\"===z&&"n"===r()?(L+="\n",s()):L+=z,s();if('"'!=z)throw x('End of string " expected');return s(),void(F=I.IDENTIFIER)}for(F=I.UNKNOWN;""!=z;)L+=z,s();throw new SyntaxError('Syntax error in part "'+k(L,30)+'"')}function f(){var t={};if(n(),p(),"strict"===L&&(t.strict=!0,p()),"graph"!==L&&"digraph"!==L||(t.type=L,p()),F===I.IDENTIFIER&&(t.id=L,p()),"{"!=L)throw x("Angle bracket { expected");if(p(),m(t),"}"!=L)throw x("Angle bracket } expected");if(p(),""!==L)throw x("End of file expected");return p(),delete t.node,delete t.edge,delete t.graph,t}function m(t){for(;""!==L&&"}"!=L;)v(t),";"===L&&p()}function v(t){var e=g(t);if(e)return void _(t,e);if(!y(t)){if(F!=I.IDENTIFIER)throw x("Identifier expected");var i=L;if(p(),"="===L){if(p(),F!=I.IDENTIFIER)throw x("Identifier expected");t[i]=L,p()}else b(t,i)}}function g(t){var e=null;if("subgraph"===L&&(e={},e.type="subgraph",p(),F===I.IDENTIFIER&&(e.id=L,p())),"{"===L){if(p(),e||(e={}),e.parent=t,e.node=t.node,e.edge=t.edge,e.graph=t.graph,m(e),"}"!=L)throw x("Angle bracket } expected");p(),delete e.node,delete e.edge,delete e.graph,delete e.parent,t.subgraphs||(t.subgraphs=[]),t.subgraphs.push(e)}return e}function y(t){return"node"===L?(p(),t.node=w(),"node"):"edge"===L?(p(),t.edge=w(),"edge"):"graph"===L?(p(),t.graph=w(),"graph"):null}function b(t,e){var i={id:e},o=w();o&&(i.attr=o),l(t,i),_(t,e)}function _(t,e){for(;"->"===L||"--"===L;){var i,o=L;p();var n=g(t);if(n)i=n;else{if(F!=I.IDENTIFIER)throw x("Identifier or subgraph expected");i=L,l(t,{id:i}),p()}u(t,c(t,e,i,o,w())),e=i}}function w(){for(var t=null,e={dashed:!0,solid:!1,dotted:[1,5]};"["===L;){for(p(),t={};""!==L&&"]"!=L;){if(F!=I.IDENTIFIER)throw x("Attribute name expected");var i=L;if(p(),"="!=L)throw x("Equal sign = expected");if(p(),F!=I.IDENTIFIER)throw x("Attribute value expected");var o=L;"style"===i&&(o=e[o]),d(t,i,o),p(),","==L&&p()}if("]"!=L)throw x("Bracket ] expected");p()}return t}function x(t){return new SyntaxError(t+', got "'+k(L,30)+'" (char '+A+")")}function k(t,e){return t.length<=e?t:t.substr(0,27)+"..."}function S(t,e,i){Array.isArray(t)?t.forEach(function(t){Array.isArray(e)?e.forEach(function(e){i(t,e)}):i(t,e)}):Array.isArray(e)?e.forEach(function(e){i(t,e)}):i(t,e)}function D(t,e,i){for(var o=e.split("."),n=o.pop(),s=t,r=0;r":!0,"--":!0},R="",A=0,z="",L="",F=I.NULL,B=/[a-zA-Z_0-9.:#]/;e.parseDOT=o,e.DOTToGraph=C},function(t,e,i){function o(t,e){var i=[],o=[],n={edges:{inheritColor:!1},nodes:{fixed:!1,parseColor:!1}};void 0!==e&&(void 0!==e.fixed&&(n.nodes.fixed=e.fixed),void 0!==e.parseColor&&(n.nodes.parseColor=e.parseColor),void 0!==e.inheritColor&&(n.edges.inheritColor=e.inheritColor));for(var s=t.edges,r=t.nodes,a=0;a2&&void 0!==arguments[2]&&arguments[2];(0,d.default)(this,t),this.body=e,this.pointToSelf=!1,this.baseSize=void 0,this.fontOptions={},this.setOptions(i),this.size={top:0,left:0,width:0,height:0,yLine:0},this.isEdgeLabel=o}return(0,u.default)(t,[{key:"setOptions",value:function(t){if(this.elementOptions=t,this.initFontOptions(t.font),p.isValidLabel(t.label)?this.labelDirty=!0:t.label="",void 0!==t.font&&null!==t.font)if("string"==typeof t.font)this.baseSize=this.fontOptions.size;else if("object"===(0,a.default)(t.font)){var e=t.font.size;void 0!==e&&(this.baseSize=e)}}},{key:"initFontOptions",value:function(e){var i=this;if(c.forEach(m,function(t){i.fontOptions[t]={}}),t.parseFontString(this.fontOptions,e))return void(this.fontOptions.vadjust=0);c.forEach(e,function(t,e){void 0!==t&&null!==t&&"object"!==(void 0===t?"undefined":(0,a.default)(t))&&(i.fontOptions[e]=t)})}},{key:"constrain",value:function(t){var e={constrainWidth:!1,maxWdt:-1,minWdt:-1,constrainHeight:!1,minHgt:-1,valign:"middle"},i=c.topMost(t,"widthConstraint");if("number"==typeof i)e.maxWdt=Number(i),e.minWdt=Number(i);else if("object"===(void 0===i?"undefined":(0,a.default)(i))){var o=c.topMost(t,["widthConstraint","maximum"]);"number"==typeof o&&(e.maxWdt=Number(o));var n=c.topMost(t,["widthConstraint","minimum"]);"number"==typeof n&&(e.minWdt=Number(n))}var s=c.topMost(t,"heightConstraint");if("number"==typeof s)e.minHgt=Number(s);else if("object"===(void 0===s?"undefined":(0,a.default)(s))){var r=c.topMost(t,["heightConstraint","minimum"]);"number"==typeof r&&(e.minHgt=Number(r));var h=c.topMost(t,["heightConstraint","valign"]);"string"==typeof h&&("top"!==h&&"bottom"!==h||(e.valign=h))}return e}},{key:"update",value:function(t,e){this.setOptions(t,!0),this.propagateFonts(e),c.deepExtend(this.fontOptions,this.constrain(e)),this.fontOptions.chooser=p.choosify("label",e)}},{key:"adjustSizes",value:function(t){var e=t?t.right+t.left:0;this.fontOptions.constrainWidth&&(this.fontOptions.maxWdt-=e,this.fontOptions.minWdt-=e);var i=t?t.top+t.bottom:0;this.fontOptions.constrainHeight&&(this.fontOptions.minHgt-=i)}},{key:"addFontOptionsToPile",value:function(t,e){for(var i=0;i5&&void 0!==arguments[5]?arguments[5]:"middle";if(void 0!==this.elementOptions.label){var r=this.fontOptions.size*this.body.view.scale;this.elementOptions.label&&r=this.elementOptions.scaling.label.maxVisible&&(r=Number(this.elementOptions.scaling.label.maxVisible)/this.body.view.scale),this.calculateLabelSize(t,o,n,e,i,s),this._drawBackground(t),this._drawText(t,e,this.size.yLine,s,r))}}},{key:"_drawBackground",value:function(t){if(void 0!==this.fontOptions.background&&"none"!==this.fontOptions.background){t.fillStyle=this.fontOptions.background;var e=this.getSize();t.fillRect(e.left,e.top,e.width,e.height)}}},{key:"_drawText",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"middle",n=arguments[4],r=this._setAlignment(t,e,i,o),a=(0,s.default)(r,2);e=a[0],i=a[1],t.textAlign="left",e-=this.size.width/2,this.fontOptions.valign&&this.size.height>this.size.labelHeight&&("top"===this.fontOptions.valign&&(i-=(this.size.height-this.size.labelHeight)/2),"bottom"===this.fontOptions.valign&&(i+=(this.size.height-this.size.labelHeight)/2));for(var h=0;h0&&(t.lineWidth=c.strokeWidth,t.strokeStyle=v,t.lineJoin="round"),t.fillStyle=m,c.strokeWidth>0&&t.strokeText(c.text,e+l,i+c.vadjust),t.fillText(c.text,e+l,i+c.vadjust),l+=c.width}i+=d.height}}}},{key:"_setAlignment",value:function(t,e,i,o){if(this.isEdgeLabel&&"horizontal"!==this.fontOptions.align&&!1===this.pointToSelf){e=0,i=0;"top"===this.fontOptions.align?(t.textBaseline="alphabetic",i-=4):"bottom"===this.fontOptions.align?(t.textBaseline="hanging",i+=4):t.textBaseline="middle"}else t.textBaseline=o;return[e,i]}},{key:"_getColor",value:function(t,e,i){var o=t||"#000000",n=i||"#ffffff";if(e<=this.elementOptions.scaling.label.drawThreshold){var s=Math.max(0,Math.min(1,1-(this.elementOptions.scaling.label.drawThreshold-e)));o=c.overrideOpacity(o,s),n=c.overrideOpacity(n,s)}return[o,n]}},{key:"getTextSize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this._processLabel(t,e,i),{width:this.size.width,height:this.size.height,lineCount:this.lineCount}}},{key:"getSize",value:function(){var t=this.size.left,e=this.size.top-1;if(this.isEdgeLabel){var i=.5*-this.size.width;switch(this.fontOptions.align){case"middle":t=i,e=.5*-this.size.height;break;case"top":t=i,e=-(this.size.height+2);break;case"bottom":t=i,e=2}}return{left:t,top:e,width:this.size.width,height:this.size.height}}},{key:"calculateLabelSize",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"middle";this._processLabel(t,e,i),this.size.left=o-.5*this.size.width,this.size.top=n-.5*this.size.height,this.size.yLine=n+.5*(1-this.lineCount)*this.fontOptions.size,"hanging"===s&&(this.size.top+=.5*this.fontOptions.size,this.size.top+=4,this.size.yLine+=4)}},{key:"getFormattingValues",value:function(t,e,i,o){var n=function(t,e,i){return"normal"===e?"mod"===i?"":t[i]:void 0!==t[e][i]?t[e][i]:t[i]},s={color:n(this.fontOptions,o,"color"),size:n(this.fontOptions,o,"size"),face:n(this.fontOptions,o,"face"),mod:n(this.fontOptions,o,"mod"),vadjust:n(this.fontOptions,o,"vadjust"),strokeWidth:this.fontOptions.strokeWidth,strokeColor:this.fontOptions.strokeColor};(e||i)&&("normal"===o&&!0===this.fontOptions.chooser&&this.elementOptions.labelHighlightBold?s.mod="bold":"function"==typeof this.fontOptions.chooser&&this.fontOptions.chooser(s,this.elementOptions.id,e,i));var r="";return void 0!==s.mod&&""!==s.mod&&(r+=s.mod+" "),r+=s.size+"px "+s.face,t.font=r.replace(/"/g,""),s.font=t.font,s.height=s.size,s}},{key:"differentState",value:function(t,e){return t!==this.selectedState||e!==this.hoverState}},{key:"_processLabelText",value:function(t,e,i,o){return new f(t,this,e,i).process(o)}},{key:"_processLabel",value:function(t,e,i){if(!1!==this.labelDirty||this.differentState(e,i)){var o=this._processLabelText(t,e,i,this.elementOptions.label);this.fontOptions.minWdt>0&&o.width0&&o.heighto.shape.height?(e=o.x+.5*o.shape.width,i=o.y-n):(e=o.x+n,i=o.y-.5*o.shape.height),[e,i,n]}},{key:"_pointOnCircle",value:function(t,e,i,o){var n=2*o*Math.PI;return{x:t+i*Math.cos(n),y:e-i*Math.sin(n)}}},{key:"_findBorderPositionCircle",value:function(t,e,i){for(var o=i.x,n=i.y,s=i.low,r=i.high,a=i.direction,h=0,d=this.options.selfReferenceSize,l=void 0,u=void 0,c=void 0,p=void 0,f=void 0,m=.5*(s+r);s<=r&&h<10&&(m=.5*(s+r),l=this._pointOnCircle(o,n,d,m),u=Math.atan2(t.y-l.y,t.x-l.x),c=t.distanceToBorder(e,u),p=Math.sqrt(Math.pow(l.x-t.x,2)+Math.pow(l.y-t.y,2)),f=c-p,!(Math.abs(f)<.05));)f>0?a>0?s=m:r=m:a>0?r=m:s=m,h++;return l.t=m,l}},{key:"getLineWidth",value:function(t,e){return!0===t?Math.max(this.selectionWidth,.3/this.body.view.scale):!0===e?Math.max(this.hoverWidth,.3/this.body.view.scale):Math.max(this.options.width,.3/this.body.view.scale)}},{key:"getColor",value:function(t,e,i,o){if(!1!==e.inheritsColor){if("both"===e.inheritsColor&&this.from.id!==this.to.id){var n=t.createLinearGradient(this.from.x,this.from.y,this.to.x,this.to.y),s=void 0,r=void 0;return s=this.from.options.color.highlight.border,r=this.to.options.color.highlight.border,!1===this.from.selected&&!1===this.to.selected?(s=l.overrideOpacity(this.from.options.color.border,e.opacity),r=l.overrideOpacity(this.to.options.color.border,e.opacity)):!0===this.from.selected&&!1===this.to.selected?r=this.to.options.color.border:!1===this.from.selected&&!0===this.to.selected&&(s=this.from.options.color.border),n.addColorStop(0,s),n.addColorStop(1,r),n}return"to"===e.inheritsColor?l.overrideOpacity(this.to.options.color.border,e.opacity):l.overrideOpacity(this.from.options.color.border,e.opacity)}return l.overrideOpacity(e.color,e.opacity)}},{key:"_circle", +value:function(t,e,i,o,n){this.enableShadow(t,e),t.beginPath(),t.arc(i,o,n,0,2*Math.PI,!1),t.stroke(),this.disableShadow(t,e)}},{key:"getDistanceToEdge",value:function(t,e,i,o,n,r,a,h){var d=0;if(this.from!=this.to)d=this._getDistanceToEdge(t,e,i,o,n,r,a);else{var l=this._getCircleData(void 0),u=(0,s.default)(l,3),c=u[0],p=u[1],f=u[2],m=c-n,v=p-r;d=Math.abs(Math.sqrt(m*m+v*v)-f)}return d}},{key:"_getDistanceToLine",value:function(t,e,i,o,n,s){var r=i-t,a=o-e,h=r*r+a*a,d=((n-t)*r+(s-e)*a)/h;d>1?d=1:d<0&&(d=0);var l=t+d*r,u=e+d*a,c=l-n,p=u-s;return Math.sqrt(c*c+p*p)}},{key:"getArrowData",value:function(t,e,i,o,n,r){var a=void 0,h=void 0,d=void 0,l=void 0,u=void 0,c=void 0,p=void 0,f=r.width;if("from"===e?(d=this.from,l=this.to,u=.1,c=r.fromArrowScale,p=r.fromArrowType):"to"===e?(d=this.to,l=this.from,u=-.1,c=r.toArrowScale,p=r.toArrowType):(d=this.to,l=this.from,c=r.middleArrowScale,p=r.middleArrowType),d!=l)if("middle"!==e)if(!0===this.options.smooth.enabled){h=this.findBorderPosition(d,t,{via:i});var m=this.getPoint(Math.max(0,Math.min(1,h.t+u)),i);a=Math.atan2(h.y-m.y,h.x-m.x)}else a=Math.atan2(d.y-l.y,d.x-l.x),h=this.findBorderPosition(d,t);else a=Math.atan2(d.y-l.y,d.x-l.x),h=this.getPoint(.5,i);else{var v=this._getCircleData(t),g=(0,s.default)(v,3),y=g[0],b=g[1],_=g[2];"from"===e?(h=this.findBorderPosition(this.from,t,{x:y,y:b,low:.25,high:.6,direction:-1}),a=-2*h.t*Math.PI+1.5*Math.PI+.1*Math.PI):"to"===e?(h=this.findBorderPosition(this.from,t,{x:y,y:b,low:.6,high:1,direction:1}),a=-2*h.t*Math.PI+1.5*Math.PI-1.1*Math.PI):(h=this._pointOnCircle(y,b,_,.175),a=3.9269908169872414)}"middle"===e&&c<0&&(f*=-1);var w=15*c+3*f;return{point:h,core:{x:h.x-.9*w*Math.cos(a),y:h.y-.9*w*Math.sin(a)},angle:a,length:w,type:p}}},{key:"drawArrowHead",value:function(t,e,i,o,n){t.strokeStyle=this.getColor(t,e,i,o),t.fillStyle=t.strokeStyle,t.lineWidth=e.width,u.draw(t,n),this.enableShadow(t,e),t.fill(),this.disableShadow(t,e)}},{key:"enableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor=e.shadowColor,t.shadowBlur=e.shadowSize,t.shadowOffsetX=e.shadowX,t.shadowOffsetY=e.shadowY)}},{key:"disableShadow",value:function(t,e){!0===e.shadow&&(t.shadowColor="rgba(0,0,0,0)",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0)}}]),t}();e.default=c},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(4),a=o(r),h=i(5),d=o(h),l=i(0),u=o(l),c=i(1),p=o(c),f=function(){function t(){(0,u.default)(this,t)}return(0,p.default)(t,null,[{key:"transform",value:function(t,e){t instanceof Array||(t=[t]);for(var i=e.point.x,o=e.point.y,n=e.angle,s=e.length,r=0;r0){var t=void 0,e=this.body.nodes,i=this.physicsBody.physicsNodeIndices,o=i.length,n=this._formBarnesHutTree(e,i);this.barnesHutTree=n;for(var s=0;s0&&this._getForceContributions(n.root,t)}}},{key:"_getForceContributions",value:function(t,e){this._getForceContribution(t.children.NW,e),this._getForceContribution(t.children.NE,e),this._getForceContribution(t.children.SW,e),this._getForceContribution(t.children.SE,e)}},{key:"_getForceContribution",value:function(t,e){if(t.childrenCount>0){var i=void 0,o=void 0,n=void 0;i=t.centerOfMass.x-e.x,o=t.centerOfMass.y-e.y,n=Math.sqrt(i*i+o*o),n*t.calcSize>this.thetaInversed?this._calculateForces(n,i,o,e,t):4===t.childrenCount?this._getForceContributions(t,e):t.children.data.id!=e.id&&this._calculateForces(n,i,o,e,t)}}},{key:"_calculateForces",value:function(t,e,i,o,n){0===t&&(t=.1,e=t),this.overlapAvoidanceFactor<1&&o.shape.radius&&(t=Math.max(.1+this.overlapAvoidanceFactor*o.shape.radius,t-o.shape.radius));var s=this.options.gravitationalConstant*n.mass*o.options.mass/Math.pow(t,3),r=e*s,a=i*s;this.physicsBody.forces[o.id].x+=r,this.physicsBody.forces[o.id].y+=a}},{key:"_formBarnesHutTree",value:function(t,e){for(var i=void 0,o=e.length,n=t[e[0]].x,s=t[e[0]].y,r=t[e[0]].x,a=t[e[0]].y,h=1;h0&&(lr&&(r=l),ua&&(a=u))}var c=Math.abs(r-n)-Math.abs(a-s);c>0?(s-=.5*c,a+=.5*c):(n+=.5*c,r-=.5*c);var p=Math.max(1e-5,Math.abs(r-n)),f=.5*p,m=.5*(n+r),v=.5*(s+a),g={root:{centerOfMass:{x:0,y:0},mass:0,range:{minX:m-f,maxX:m+f,minY:v-f,maxY:v+f},size:p,calcSize:1/p,children:{data:null},maxWidth:0,level:0,childrenCount:4}};this._splitBranch(g.root);for(var y=0;y0&&this._placeInTree(g.root,i);return g}},{key:"_updateBranchMass",value:function(t,e){var i=t.centerOfMass,o=t.mass+e.options.mass,n=1/o;i.x=i.x*t.mass+e.x*e.options.mass,i.x*=n,i.y=i.y*t.mass+e.y*e.options.mass,i.y*=n,t.mass=o;var s=Math.max(Math.max(e.height,e.radius),e.width);t.maxWidth=t.maxWidthe.x?o.maxY>e.y?"NW":"SW":o.maxY>e.y?"NE":"SE",this._placeInRegion(t,e,n)}},{key:"_placeInRegion",value:function(t,e,i){var o=t.children[i];switch(o.childrenCount){case 0:o.children.data=e,o.childrenCount=1,this._updateBranchMass(o,e);break;case 1:o.children.data.x===e.x&&o.children.data.y===e.y?(e.x+=this.seededRandom(),e.y+=this.seededRandom()):(this._splitBranch(o),this._placeInTree(o,e));break;case 4:this._placeInTree(o,e)}}},{key:"_splitBranch",value:function(t){var e=null;1===t.childrenCount&&(e=t.children.data,t.mass=0,t.centerOfMass.x=0,t.centerOfMass.y=0),t.childrenCount=4,t.children.data=null,this._insertRegion(t,"NW"),this._insertRegion(t,"NE"),this._insertRegion(t,"SW"),this._insertRegion(t,"SE"),null!=e&&this._placeInTree(t,e)}},{key:"_insertRegion",value:function(t,e){var i=void 0,o=void 0,n=void 0,s=void 0,r=.5*t.size;switch(e){case"NW":i=t.range.minX,o=t.range.minX+r,n=t.range.minY,s=t.range.minY+r;break;case"NE":i=t.range.minX+r,o=t.range.maxX,n=t.range.minY,s=t.range.minY+r;break;case"SW":i=t.range.minX,o=t.range.minX+r,n=t.range.minY+r,s=t.range.maxY;break;case"SE":i=t.range.minX+r,o=t.range.maxX,n=t.range.minY+r,s=t.range.maxY}t.children[e]={centerOfMass:{x:0,y:0},mass:0,range:{minX:i,maxX:o,minY:n,maxY:s},size:.5*t.size,calcSize:2*t.calcSize,children:{data:null},maxWidth:0,level:t.level+1,childrenCount:0}}},{key:"_debug",value:function(t,e){void 0!==this.barnesHutTree&&(t.lineWidth=1,this._drawBranch(this.barnesHutTree.root,t,e))}},{key:"_drawBranch",value:function(t,e,i){void 0===i&&(i="#FF0000"),4===t.childrenCount&&(this._drawBranch(t.children.NW,e),this._drawBranch(t.children.NE,e),this._drawBranch(t.children.SE,e),this._drawBranch(t.children.SW,e)),e.strokeStyle=i,e.beginPath(),e.moveTo(t.range.minX,t.range.minY),e.lineTo(t.range.maxX,t.range.minY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.minY),e.lineTo(t.range.maxX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.maxX,t.range.maxY),e.lineTo(t.range.minX,t.range.maxY),e.stroke(),e.beginPath(),e.moveTo(t.range.minX,t.range.maxY),e.lineTo(t.range.minX,t.range.minY),e.stroke()}}]),t}();e.default=h},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=function(){function t(e,i,o){(0,s.default)(this,t),this.body=e,this.physicsBody=i,this.setOptions(o)}return(0,a.default)(t,[{key:"setOptions",value:function(t){this.options=t}},{key:"solve",value:function(){for(var t=void 0,e=void 0,i=void 0,o=void 0,n=this.body.nodes,s=this.physicsBody.physicsNodeIndices,r=this.physicsBody.forces,a=0;a=t.length?(this._t=void 0,n(1)):"keys"==e?n(0,i):"values"==e?n(0,t[i]):n(0,[i,t[i]])},"values"),s.Arguments=s.Array,o("keys"),o("values"),o("entries")},function(t,e){t.exports=function(){}},function(t,e){t.exports=function(t,e){return{value:e,done:!!t}}},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,e,i){var o=i(54),n=i(39),s=i(59),r={};i(26)(r,i(13)("iterator"),function(){return this}),t.exports=function(t,e,i){t.prototype=o(r,{next:n(1,i)}),s(t,e+" Iterator")}},function(t,e,i){var o=i(20),n=i(27),s=i(33);t.exports=i(21)?Object.defineProperties:function(t,e){n(t);for(var i,r=s(e),a=r.length,h=0;a>h;)o.f(t,i=r[h++],e[i]);return t}},function(t,e,i){var o=i(25),n=i(132),s=i(133);t.exports=function(t){return function(e,i,r){var a,h=o(e),d=n(h.length),l=s(r,d);if(t&&i!=i){for(;d>l;)if((a=h[l++])!=a)return!0}else for(;d>l;l++)if((t||l in h)&&h[l]===i)return t||l||0;return!t&&-1}}},function(t,e,i){var o=i(55),n=Math.min;t.exports=function(t){return t>0?n(o(t),9007199254740991):0}},function(t,e,i){var o=i(55),n=Math.max,s=Math.min;t.exports=function(t,e){return t=o(t),t<0?n(t+e,0):s(t,e)}},function(t,e,i){var o=i(18).document;t.exports=o&&o.documentElement},function(t,e,i){var o=i(55),n=i(51);t.exports=function(t){return function(e,i){var s,r,a=String(n(e)),h=o(i),d=a.length;return h<0||h>=d?t?"":void 0:(s=a.charCodeAt(h),s<55296||s>56319||h+1===d||(r=a.charCodeAt(h+1))<56320||r>57343?t?a.charAt(h):s:t?a.slice(h,h+2):r-56320+(s-55296<<10)+65536)}}},function(t,e,i){var o=i(27),n=i(137);t.exports=i(7).getIterator=function(t){var e=n(t);if("function"!=typeof e)throw TypeError(t+" is not iterable!");return o(e.call(t))}},function(t,e,i){var o=i(86),n=i(13)("iterator"),s=i(31);t.exports=i(7).getIteratorMethod=function(t){if(void 0!=t)return t[n]||t["@@iterator"]||s[o(t)]}},function(t,e,i){i(139);var o=i(7).Object;t.exports=function(t,e){return o.create(t,e)}},function(t,e,i){var o=i(17);o(o.S,"Object",{create:i(54)})},function(t,e,i){i(141),t.exports=i(7).Object.keys},function(t,e,i){var o=i(41),n=i(33);i(87)("keys",function(){return function(t){return n(o(t))}})},function(t,e,i){t.exports={default:i(143),__esModule:!0}},function(t,e,i){i(60),i(49),t.exports=i(61).f("iterator")},function(t,e,i){t.exports={default:i(145),__esModule:!0}},function(t,e,i){i(146),i(151),i(152),i(153),t.exports=i(7).Symbol},function(t,e,i){var o=i(18),n=i(22),s=i(21),r=i(17),a=i(83),h=i(147).KEY,d=i(28),l=i(57),u=i(59),c=i(40),p=i(13),f=i(61),m=i(62),v=i(148),g=i(149),y=i(27),b=i(25),_=i(53),w=i(39),x=i(54),k=i(150),S=i(89),D=i(20),M=i(33),C=S.f,O=D.f,E=k.f,T=o.Symbol,P=o.JSON,I=P&&P.stringify,N=p("_hidden"),R=p("toPrimitive"),A={}.propertyIsEnumerable,z=l("symbol-registry"),L=l("symbols"),F=l("op-symbols"),B=Object.prototype,j="function"==typeof T,H=o.QObject,W=!H||!H.prototype||!H.prototype.findChild,Y=s&&d(function(){return 7!=x(O({},"a",{get:function(){return O(this,"a",{value:7}).a}})).a})?function(t,e,i){var o=C(B,e);o&&delete B[e],O(t,e,i),o&&t!==B&&O(B,e,o)}:O,G=function(t){var e=L[t]=x(T.prototype);return e._k=t,e},V=j&&"symbol"==typeof T.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof T},U=function(t,e,i){return t===B&&U(F,e,i),y(t),e=_(e,!0),y(i),n(L,e)?(i.enumerable?(n(t,N)&&t[N][e]&&(t[N][e]=!1),i=x(i,{enumerable:w(0,!1)})):(n(t,N)||O(t,N,w(1,{})),t[N][e]=!0),Y(t,e,i)):O(t,e,i)},q=function(t,e){y(t);for(var i,o=v(e=b(e)),n=0,s=o.length;s>n;)U(t,i=o[n++],e[i]);return t},X=function(t,e){return void 0===e?x(t):q(x(t),e)},Z=function(t){var e=A.call(this,t=_(t,!0));return!(this===B&&n(L,t)&&!n(F,t))&&(!(e||!n(this,t)||!n(L,t)||n(this,N)&&this[N][t])||e)},K=function(t,e){if(t=b(t),e=_(e,!0),t!==B||!n(L,e)||n(F,e)){var i=C(t,e);return!i||!n(L,e)||n(t,N)&&t[N][e]||(i.enumerable=!0),i}},J=function(t){for(var e,i=E(b(t)),o=[],s=0;i.length>s;)n(L,e=i[s++])||e==N||e==h||o.push(e);return o},$=function(t){for(var e,i=t===B,o=E(i?F:b(t)),s=[],r=0;o.length>r;)!n(L,e=o[r++])||i&&!n(B,e)||s.push(L[e]);return s};j||(T=function(){if(this instanceof T)throw TypeError("Symbol is not a constructor!");var t=c(arguments.length>0?arguments[0]:void 0),e=function(i){this===B&&e.call(F,i),n(this,N)&&n(this[N],t)&&(this[N][t]=!1),Y(this,t,w(1,i))};return s&&W&&Y(B,t,{configurable:!0,set:e}),G(t)},a(T.prototype,"toString",function(){return this._k}),S.f=K,D.f=U,i(88).f=k.f=J,i(42).f=Z,i(63).f=$,s&&!i(52)&&a(B,"propertyIsEnumerable",Z,!0),f.f=function(t){return G(p(t))}),r(r.G+r.W+r.F*!j,{Symbol:T});for(var Q="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),tt=0;Q.length>tt;)p(Q[tt++]);for(var et=M(p.store),it=0;et.length>it;)m(et[it++]);r(r.S+r.F*!j,"Symbol",{for:function(t){return n(z,t+="")?z[t]:z[t]=T(t)},keyFor:function(t){if(!V(t))throw TypeError(t+" is not a symbol!");for(var e in z)if(z[e]===t)return e},useSetter:function(){W=!0},useSimple:function(){W=!1}}),r(r.S+r.F*!j,"Object",{create:X,defineProperty:U,defineProperties:q,getOwnPropertyDescriptor:K,getOwnPropertyNames:J,getOwnPropertySymbols:$}),P&&r(r.S+r.F*(!j||d(function(){var t=T();return"[null]"!=I([t])||"{}"!=I({a:t})||"{}"!=I(Object(t))})),"JSON",{stringify:function(t){if(void 0!==t&&!V(t)){for(var e,i,o=[t],n=1;arguments.length>n;)o.push(arguments[n++]);return e=o[1],"function"==typeof e&&(i=e),!i&&g(e)||(e=function(t,e){if(i&&(e=i.call(this,t,e)),!V(e))return e}),o[1]=e,I.apply(P,o)}}}),T.prototype[R]||i(26)(T.prototype,R,T.prototype.valueOf),u(T,"Symbol"),u(Math,"Math",!0),u(o.JSON,"JSON",!0)},function(t,e,i){var o=i(40)("meta"),n=i(32),s=i(22),r=i(20).f,a=0,h=Object.isExtensible||function(){return!0},d=!i(28)(function(){return h(Object.preventExtensions({}))}),l=function(t){r(t,o,{value:{i:"O"+ ++a,w:{}}})},u=function(t,e){if(!n(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!s(t,o)){if(!h(t))return"F";if(!e)return"E";l(t)}return t[o].i},c=function(t,e){if(!s(t,o)){if(!h(t))return!0;if(!e)return!1;l(t)}return t[o].w},p=function(t){return d&&f.NEED&&h(t)&&!s(t,o)&&l(t),t},f=t.exports={KEY:o,NEED:!1,fastKey:u,getWeak:c,onFreeze:p}},function(t,e,i){var o=i(33),n=i(63),s=i(42);t.exports=function(t){var e=o(t),i=n.f;if(i)for(var r,a=i(t),h=s.f,d=0;a.length>d;)h.call(t,r=a[d++])&&e.push(r);return e}},function(t,e,i){var o=i(50);t.exports=Array.isArray||function(t){return"Array"==o(t)}},function(t,e,i){var o=i(25),n=i(88).f,s={}.toString,r="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],a=function(t){try{return n(t)}catch(t){return r.slice()}};t.exports.f=function(t){return r&&"[object Window]"==s.call(t)?a(t):n(o(t))}},function(t,e){},function(t,e,i){i(62)("asyncIterator")},function(t,e,i){i(62)("observable")},function(t,e,i){(function(t){!function(e,i){t.exports=i()}(0,function(){function e(){return Co.apply(null,arguments)}function i(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function o(t){return null!=t&&"[object Object]"===Object.prototype.toString.call(t)}function n(t){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(t).length;var e;for(e in t)if(t.hasOwnProperty(e))return!1;return!0}function s(t){return void 0===t}function r(t){return"number"==typeof t||"[object Number]"===Object.prototype.toString.call(t)}function a(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function h(t,e){var i,o=[];for(i=0;i0)for(i=0;i0?"future":"past"];return D(i)?i(e):i.replace(/%s/i,e)}function A(t,e){var i=t.toLowerCase();Lo[i]=Lo[i+"s"]=Lo[e]=t}function z(t){return"string"==typeof t?Lo[t]||Lo[t.toLowerCase()]:void 0}function L(t){var e,i,o={};for(i in t)d(t,i)&&(e=z(i))&&(o[e]=t[i]);return o}function F(t,e){Fo[t]=e}function B(t){var e=[];for(var i in t)e.push({unit:i,priority:Fo[i]});return e.sort(function(t,e){return t.priority-e.priority}),e}function j(t,e,i){var o=""+Math.abs(t),n=e-o.length;return(t>=0?i?"+":"":"-")+Math.pow(10,Math.max(0,n)).toString().substr(1)+o}function H(t,e,i,o){var n=o;"string"==typeof o&&(n=function(){return this[o]()}),t&&(Wo[t]=n),e&&(Wo[e[0]]=function(){return j(n.apply(this,arguments),e[1],e[2])}),i&&(Wo[i]=function(){return this.localeData().ordinal(n.apply(this,arguments),t)})}function W(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function Y(t){var e,i,o=t.match(Bo);for(e=0,i=o.length;e=0&&jo.test(t);)t=t.replace(jo,i),jo.lastIndex=0,o-=1;return t}function U(t,e,i){an[t]=D(e)?e:function(t,o){return t&&i?i:e}}function q(t,e){return d(an,t)?an[t](e._strict,e._locale):new RegExp(X(t))}function X(t){return Z(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,i,o,n){return e||i||o||n}))}function Z(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function K(t,e){var i,o=e;for("string"==typeof t&&(t=[t]),r(e)&&(o=function(t,i){i[e]=_(t)}),i=0;i=0&&isFinite(a.getFullYear())&&a.setFullYear(t),a}function _t(t){var e=new Date(Date.UTC.apply(null,arguments));return t<100&&t>=0&&isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t),e}function wt(t,e,i){var o=7+e-i;return-(7+_t(t,0,o).getUTCDay()-e)%7+o-1}function xt(t,e,i,o,n){var s,r,a=(7+i-o)%7,h=wt(t,o,n),d=1+7*(e-1)+a+h;return d<=0?(s=t-1,r=Q(s)+d):d>Q(t)?(s=t+1,r=d-Q(t)):(s=t,r=d),{year:s,dayOfYear:r}}function kt(t,e,i){var o,n,s=wt(t.year(),e,i),r=Math.floor((t.dayOfYear()-s-1)/7)+1;return r<1?(n=t.year()-1,o=r+St(n,e,i)):r>St(t.year(),e,i)?(o=r-St(t.year(),e,i),n=t.year()+1):(n=t.year(),o=r),{week:o,year:n}}function St(t,e,i){var o=wt(t,e,i),n=wt(t+1,e,i);return(Q(t)-o+n)/7}function Dt(t){return kt(t,this._week.dow,this._week.doy).week}function Mt(){return this._week.dow}function Ct(){return this._week.doy}function Ot(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")}function Et(t){var e=kt(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")}function Tt(t,e){return"string"!=typeof t?t:isNaN(t)?(t=e.weekdaysParse(t),"number"==typeof t?t:null):parseInt(t,10)}function Pt(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}function It(t,e){return t?i(this._weekdays)?this._weekdays[t.day()]:this._weekdays[this._weekdays.isFormat.test(e)?"format":"standalone"][t.day()]:i(this._weekdays)?this._weekdays:this._weekdays.standalone}function Nt(t){return t?this._weekdaysShort[t.day()]:this._weekdaysShort}function Rt(t){return t?this._weekdaysMin[t.day()]:this._weekdaysMin}function At(t,e,i){var o,n,s,r=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],o=0;o<7;++o)s=u([2e3,1]).day(o),this._minWeekdaysParse[o]=this.weekdaysMin(s,"").toLocaleLowerCase(),this._shortWeekdaysParse[o]=this.weekdaysShort(s,"").toLocaleLowerCase(),this._weekdaysParse[o]=this.weekdays(s,"").toLocaleLowerCase();return i?"dddd"===e?(n=yn.call(this._weekdaysParse,r),-1!==n?n:null):"ddd"===e?(n=yn.call(this._shortWeekdaysParse,r),-1!==n?n:null):(n=yn.call(this._minWeekdaysParse,r),-1!==n?n:null):"dddd"===e?-1!==(n=yn.call(this._weekdaysParse,r))?n:-1!==(n=yn.call(this._shortWeekdaysParse,r))?n:(n=yn.call(this._minWeekdaysParse,r),-1!==n?n:null):"ddd"===e?-1!==(n=yn.call(this._shortWeekdaysParse,r))?n:-1!==(n=yn.call(this._weekdaysParse,r))?n:(n=yn.call(this._minWeekdaysParse,r),-1!==n?n:null):-1!==(n=yn.call(this._minWeekdaysParse,r))?n:-1!==(n=yn.call(this._weekdaysParse,r))?n:(n=yn.call(this._shortWeekdaysParse,r),-1!==n?n:null)}function zt(t,e,i){var o,n,s;if(this._weekdaysParseExact)return At.call(this,t,e,i);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),o=0;o<7;o++){if(n=u([2e3,1]).day(o),i&&!this._fullWeekdaysParse[o]&&(this._fullWeekdaysParse[o]=new RegExp("^"+this.weekdays(n,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[o]=new RegExp("^"+this.weekdaysShort(n,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[o]=new RegExp("^"+this.weekdaysMin(n,"").replace(".",".?")+"$","i")),this._weekdaysParse[o]||(s="^"+this.weekdays(n,"")+"|^"+this.weekdaysShort(n,"")+"|^"+this.weekdaysMin(n,""),this._weekdaysParse[o]=new RegExp(s.replace(".",""),"i")),i&&"dddd"===e&&this._fullWeekdaysParse[o].test(t))return o;if(i&&"ddd"===e&&this._shortWeekdaysParse[o].test(t))return o;if(i&&"dd"===e&&this._minWeekdaysParse[o].test(t))return o;if(!i&&this._weekdaysParse[o].test(t))return o}}function Lt(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=Tt(t,this.localeData()),this.add(t-e,"d")):e}function Ft(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")}function Bt(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=Pt(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7}function jt(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||Yt.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(d(this,"_weekdaysRegex")||(this._weekdaysRegex=En),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)}function Ht(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||Yt.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(d(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Tn),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Wt(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||Yt.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(d(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Pn),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Yt(){function t(t,e){return e.length-t.length}var e,i,o,n,s,r=[],a=[],h=[],d=[];for(e=0;e<7;e++)i=u([2e3,1]).day(e),o=this.weekdaysMin(i,""),n=this.weekdaysShort(i,""),s=this.weekdays(i,""),r.push(o),a.push(n),h.push(s),d.push(o),d.push(n),d.push(s);for(r.sort(t),a.sort(t),h.sort(t),d.sort(t),e=0;e<7;e++)a[e]=Z(a[e]),h[e]=Z(h[e]),d[e]=Z(d[e]);this._weekdaysRegex=new RegExp("^("+d.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+r.join("|")+")","i")}function Gt(){return this.hours()%12||12}function Vt(){return this.hours()||24}function Ut(t,e){H(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function qt(t,e){return e._meridiemParse}function Xt(t){return"p"===(t+"").toLowerCase().charAt(0)}function Zt(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"}function Kt(t){return t?t.toLowerCase().replace("_","-"):t}function Jt(t){for(var e,i,o,n,s=0;s0;){if(o=$t(n.slice(0,e).join("-")))return o;if(i&&i.length>=e&&w(n,i,!0)>=e-1)break;e--}s++}return null}function $t(e){var i=null;if(!zn[e]&&void 0!==t&&t&&t.exports)try{i=In._abbr;!function(){var t=new Error('Cannot find module "./locale"');throw t.code="MODULE_NOT_FOUND",t}(),Qt(i)}catch(t){}return zn[e]}function Qt(t,e){var i;return t&&(i=s(e)?ie(t):te(t,e))&&(In=i),In._abbr}function te(t,e){if(null!==e){var i=An;if(e.abbr=t,null!=zn[t])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),i=zn[t]._config;else if(null!=e.parentLocale){if(null==zn[e.parentLocale])return Ln[e.parentLocale]||(Ln[e.parentLocale]=[]),Ln[e.parentLocale].push({name:t,config:e}),null;i=zn[e.parentLocale]._config}return zn[t]=new O(C(i,e)),Ln[t]&&Ln[t].forEach(function(t){te(t.name,t.config)}),Qt(t),zn[t]}return delete zn[t],null}function ee(t,e){if(null!=e){var i,o=An;null!=zn[t]&&(o=zn[t]._config),e=C(o,e),i=new O(e),i.parentLocale=zn[t],zn[t]=i,Qt(t)}else null!=zn[t]&&(null!=zn[t].parentLocale?zn[t]=zn[t].parentLocale:null!=zn[t]&&delete zn[t]);return zn[t]}function ie(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return In;if(!i(t)){if(e=$t(t))return e;t=[t]}return Jt(t)}function oe(){return Io(zn)}function ne(t){var e,i=t._a;return i&&-2===p(t).overflow&&(e=i[ln]<0||i[ln]>11?ln:i[un]<1||i[un]>ht(i[dn],i[ln])?un:i[cn]<0||i[cn]>24||24===i[cn]&&(0!==i[pn]||0!==i[fn]||0!==i[mn])?cn:i[pn]<0||i[pn]>59?pn:i[fn]<0||i[fn]>59?fn:i[mn]<0||i[mn]>999?mn:-1,p(t)._overflowDayOfYear&&(eun)&&(e=un),p(t)._overflowWeeks&&-1===e&&(e=vn),p(t)._overflowWeekday&&-1===e&&(e=gn),p(t).overflow=e),t}function se(t,e,i){return null!=t?t:null!=e?e:i}function re(t){var i=new Date(e.now());return t._useUTC?[i.getUTCFullYear(),i.getUTCMonth(),i.getUTCDate()]:[i.getFullYear(),i.getMonth(),i.getDate()]}function ae(t){var e,i,o,n,s=[];if(!t._d){for(o=re(t),t._w&&null==t._a[un]&&null==t._a[ln]&&he(t),null!=t._dayOfYear&&(n=se(t._a[dn],o[dn]),(t._dayOfYear>Q(n)||0===t._dayOfYear)&&(p(t)._overflowDayOfYear=!0),i=_t(n,0,t._dayOfYear),t._a[ln]=i.getUTCMonth(),t._a[un]=i.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=s[e]=o[e];for(;e<7;e++)t._a[e]=s[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[cn]&&0===t._a[pn]&&0===t._a[fn]&&0===t._a[mn]&&(t._nextDay=!0,t._a[cn]=0),t._d=(t._useUTC?_t:bt).apply(null,s),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[cn]=24),t._w&&void 0!==t._w.d&&t._w.d!==t._d.getDay()&&(p(t).weekdayMismatch=!0)}}function he(t){var e,i,o,n,s,r,a,h;if(e=t._w,null!=e.GG||null!=e.W||null!=e.E)s=1,r=4,i=se(e.GG,t._a[dn],kt(De(),1,4).year),o=se(e.W,1),((n=se(e.E,1))<1||n>7)&&(h=!0);else{s=t._locale._week.dow,r=t._locale._week.doy;var d=kt(De(),s,r);i=se(e.gg,t._a[dn],d.year),o=se(e.w,d.week),null!=e.d?((n=e.d)<0||n>6)&&(h=!0):null!=e.e?(n=e.e+s,(e.e<0||e.e>6)&&(h=!0)):n=s}o<1||o>St(i,s,r)?p(t)._overflowWeeks=!0:null!=h?p(t)._overflowWeekday=!0:(a=xt(i,o,n,s,r),t._a[dn]=a.year,t._dayOfYear=a.dayOfYear)}function de(t){var e,i,o,n,s,r,a=t._i,h=Fn.exec(a)||Bn.exec(a);if(h){for(p(t).iso=!0,e=0,i=Hn.length;e0&&p(t).unusedInput.push(r),a=a.slice(a.indexOf(o)+o.length),d+=o.length),Wo[s]?(o?p(t).empty=!1:p(t).unusedTokens.push(s),$(s,o,t)):t._strict&&!o&&p(t).unusedTokens.push(s);p(t).charsLeftOver=h-d,a.length>0&&p(t).unusedInput.push(a),t._a[cn]<=12&&!0===p(t).bigHour&&t._a[cn]>0&&(p(t).bigHour=void 0),p(t).parsedDateParts=t._a.slice(0),p(t).meridiem=t._meridiem,t._a[cn]=ye(t._locale,t._a[cn],t._meridiem),ae(t),ne(t)}function ye(t,e,i){var o;return null==i?e:null!=t.meridiemHour?t.meridiemHour(e,i):null!=t.isPM?(o=t.isPM(i),o&&e<12&&(e+=12),o||12!==e||(e=0),e):e}function be(t){var e,i,o,n,s;if(0===t._f.length)return p(t).invalidFormat=!0,void(t._d=new Date(NaN));for(n=0;nthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ue(){if(!s(this._isDSTShifted))return this._isDSTShifted;var t={};if(v(t,this),t=xe(t),t._a){var e=t._isUTC?u(t._a):De(t._a);this._isDSTShifted=this.isValid()&&w(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function qe(){return!!this.isValid()&&!this._isUTC}function Xe(){return!!this.isValid()&&this._isUTC}function Ze(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Ke(t,e){var i,o,n,s=t,a=null;return Ne(t)?s={ms:t._milliseconds,d:t._days,M:t._months}:r(t)?(s={},e?s[e]=t:s.milliseconds=t):(a=Jn.exec(t))?(i="-"===a[1]?-1:1,s={y:0,d:_(a[un])*i,h:_(a[cn])*i,m:_(a[pn])*i,s:_(a[fn])*i,ms:_(Re(1e3*a[mn]))*i}):(a=$n.exec(t))?(i="-"===a[1]?-1:(a[1],1),s={y:Je(a[2],i),M:Je(a[3],i),w:Je(a[4],i),d:Je(a[5],i),h:Je(a[6],i),m:Je(a[7],i),s:Je(a[8],i)}):null==s?s={}:"object"==typeof s&&("from"in s||"to"in s)&&(n=Qe(De(s.from),De(s.to)),s={},s.ms=n.milliseconds,s.M=n.months),o=new Ie(s),Ne(t)&&d(t,"_locale")&&(o._locale=t._locale),o}function Je(t,e){var i=t&&parseFloat(t.replace(",","."));return(isNaN(i)?0:i)*e}function $e(t,e){var i={milliseconds:0,months:0};return i.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(i.months,"M").isAfter(e)&&--i.months,i.milliseconds=+e-+t.clone().add(i.months,"M"),i}function Qe(t,e){var i;return t.isValid()&&e.isValid()?(e=Le(e,t),t.isBefore(e)?i=$e(t,e):(i=$e(e,t),i.milliseconds=-i.milliseconds,i.months=-i.months),i):{milliseconds:0,months:0}}function ti(t,e){return function(i,o){var n,s;return null===o||isNaN(+o)||(S(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),s=i,i=o,o=s),i="string"==typeof i?+i:i,n=Ke(i,o),ei(this,n,t),this}}function ei(t,i,o,n){var s=i._milliseconds,r=Re(i._days),a=Re(i._months);t.isValid()&&(n=null==n||n,a&&pt(t,ot(t,"Month")+a*o),r&&nt(t,"Date",ot(t,"Date")+r*o),s&&t._d.setTime(t._d.valueOf()+s*o),n&&e.updateOffset(t,r||a))}function ii(t,e){var i=t.diff(e,"days",!0);return i<-6?"sameElse":i<-1?"lastWeek":i<0?"lastDay":i<1?"sameDay":i<2?"nextDay":i<7?"nextWeek":"sameElse"}function oi(t,i){var o=t||De(),n=Le(o,this).startOf("day"),s=e.calendarFormat(this,n)||"sameElse",r=i&&(D(i[s])?i[s].call(this,o):i[s]);return this.format(r||this.localeData().calendar(s,this,De(o)))}function ni(){return new g(this)}function si(t,e){var i=y(t)?t:De(t);return!(!this.isValid()||!i.isValid())&&(e=z(s(e)?"millisecond":e),"millisecond"===e?this.valueOf()>i.valueOf():i.valueOf()9999?G(t,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):D(Date.prototype.toISOString)?this.toDate().toISOString():G(t,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function mi(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var i="["+t+'("]',o=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",n=e+'[")]';return this.format(i+o+"-MM-DD[T]HH:mm:ss.SSS"+n)}function vi(t){t||(t=this.isUtc()?e.defaultFormatUtc:e.defaultFormat);var i=G(this,t);return this.localeData().postformat(i)}function gi(t,e){return this.isValid()&&(y(t)&&t.isValid()||De(t).isValid())?Ke({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function yi(t){return this.from(De(),t)}function bi(t,e){return this.isValid()&&(y(t)&&t.isValid()||De(t).isValid())?Ke({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function _i(t){return this.to(De(),t)}function wi(t){var e;return void 0===t?this._locale._abbr:(e=ie(t),null!=e&&(this._locale=e),this)}function xi(){return this._locale}function ki(t){switch(t=z(t)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===t&&this.weekday(0),"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this}function Si(t){return void 0===(t=z(t))||"millisecond"===t?this:("date"===t&&(t="day"),this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms"))}function Di(){return this._d.valueOf()-6e4*(this._offset||0)}function Mi(){return Math.floor(this.valueOf()/1e3)}function Ci(){return new Date(this.valueOf())}function Oi(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]}function Ei(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}}function Ti(){return this.isValid()?this.toISOString():null}function Pi(){return f(this)}function Ii(){return l({},p(this))}function Ni(){return p(this).overflow}function Ri(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Ai(t,e){H(0,[t,t.length],0,e)}function zi(t){return ji.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function Li(t){return ji.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)}function Fi(){return St(this.year(),1,4)}function Bi(){var t=this.localeData()._week;return St(this.year(),t.dow,t.doy)}function ji(t,e,i,o,n){var s;return null==t?kt(this,o,n).year:(s=St(t,o,n),e>s&&(e=s),Hi.call(this,t,e,i,o,n))}function Hi(t,e,i,o,n){var s=xt(t,e,i,o,n),r=_t(s.year,0,s.dayOfYear);return this.year(r.getUTCFullYear()),this.month(r.getUTCMonth()),this.date(r.getUTCDate()),this}function Wi(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)}function Yi(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")}function Gi(t,e){e[mn]=_(1e3*("0."+t))}function Vi(){return this._isUTC?"UTC":""}function Ui(){return this._isUTC?"Coordinated Universal Time":""}function qi(t){return De(1e3*t)}function Xi(){return De.apply(null,arguments).parseZone()}function Zi(t){return t}function Ki(t,e,i,o){var n=ie(),s=u().set(o,e);return n[i](s,t)}function Ji(t,e,i){if(r(t)&&(e=t,t=void 0),t=t||"",null!=e)return Ki(t,e,i,"month");var o,n=[];for(o=0;o<12;o++)n[o]=Ki(t,o,i,"month");return n}function $i(t,e,i,o){"boolean"==typeof t?(r(e)&&(i=e,e=void 0),e=e||""):(e=t,i=e,t=!1,r(e)&&(i=e,e=void 0),e=e||"");var n=ie(),s=t?n._week.dow:0;if(null!=i)return Ki(e,(i+s)%7,o,"day");var a,h=[];for(a=0;a<7;a++)h[a]=Ki(e,(a+s)%7,o,"day");return h}function Qi(t,e){return Ji(t,e,"months")}function to(t,e){return Ji(t,e,"monthsShort")}function eo(t,e,i){return $i(t,e,i,"weekdays")}function io(t,e,i){return $i(t,e,i,"weekdaysShort")}function oo(t,e,i){return $i(t,e,i,"weekdaysMin")}function no(){var t=this._data;return this._milliseconds=ds(this._milliseconds),this._days=ds(this._days),this._months=ds(this._months),t.milliseconds=ds(t.milliseconds),t.seconds=ds(t.seconds),t.minutes=ds(t.minutes),t.hours=ds(t.hours),t.months=ds(t.months),t.years=ds(t.years),this}function so(t,e,i,o){var n=Ke(e,i);return t._milliseconds+=o*n._milliseconds,t._days+=o*n._days,t._months+=o*n._months,t._bubble()}function ro(t,e){return so(this,t,e,1)}function ao(t,e){return so(this,t,e,-1)}function ho(t){return t<0?Math.floor(t):Math.ceil(t)}function lo(){var t,e,i,o,n,s=this._milliseconds,r=this._days,a=this._months,h=this._data;return s>=0&&r>=0&&a>=0||s<=0&&r<=0&&a<=0||(s+=864e5*ho(co(a)+r),r=0,a=0),h.milliseconds=s%1e3,t=b(s/1e3),h.seconds=t%60,e=b(t/60),h.minutes=e%60,i=b(e/60),h.hours=i%24,r+=b(i/24),n=b(uo(r)),a+=n, +r-=ho(co(n)),o=b(a/12),a%=12,h.days=r,h.months=a,h.years=o,this}function uo(t){return 4800*t/146097}function co(t){return 146097*t/4800}function po(t){if(!this.isValid())return NaN;var e,i,o=this._milliseconds;if("month"===(t=z(t))||"year"===t)return e=this._days+o/864e5,i=this._months+uo(e),"month"===t?i:i/12;switch(e=this._days+Math.round(co(this._months)),t){case"week":return e/7+o/6048e5;case"day":return e+o/864e5;case"hour":return 24*e+o/36e5;case"minute":return 1440*e+o/6e4;case"second":return 86400*e+o/1e3;case"millisecond":return Math.floor(864e5*e)+o;default:throw new Error("Unknown unit "+t)}}function fo(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*_(this._months/12):NaN}function mo(t){return function(){return this.as(t)}}function vo(){return Ke(this)}function go(t){return t=z(t),this.isValid()?this[t+"s"]():NaN}function yo(t){return function(){return this.isValid()?this._data[t]:NaN}}function bo(){return b(this.days()/7)}function _o(t,e,i,o,n){return n.relativeTime(e||1,!!i,t,o)}function wo(t,e,i){var o=Ke(t).abs(),n=Ds(o.as("s")),s=Ds(o.as("m")),r=Ds(o.as("h")),a=Ds(o.as("d")),h=Ds(o.as("M")),d=Ds(o.as("y")),l=n<=Ms.ss&&["s",n]||n0,l[4]=i,_o.apply(null,l)}function xo(t){return void 0===t?Ds:"function"==typeof t&&(Ds=t,!0)}function ko(t,e){return void 0!==Ms[t]&&(void 0===e?Ms[t]:(Ms[t]=e,"s"===t&&(Ms.ss=e-1),!0))}function So(t){if(!this.isValid())return this.localeData().invalidDate();var e=this.localeData(),i=wo(this,!t,e);return t&&(i=e.pastFuture(+this,i)),e.postformat(i)}function Do(t){return(t>0)-(t<0)||+t}function Mo(){if(!this.isValid())return this.localeData().invalidDate();var t,e,i,o=Cs(this._milliseconds)/1e3,n=Cs(this._days),s=Cs(this._months);t=b(o/60),e=b(t/60),o%=60,t%=60,i=b(s/12),s%=12;var r=i,a=s,h=n,d=e,l=t,u=o?o.toFixed(3).replace(/\.?0+$/,""):"",c=this.asSeconds();if(!c)return"P0D";var p=c<0?"-":"",f=Do(this._months)!==Do(c)?"-":"",m=Do(this._days)!==Do(c)?"-":"",v=Do(this._milliseconds)!==Do(c)?"-":"";return p+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(h?m+h+"D":"")+(d||l||u?"T":"")+(d?v+d+"H":"")+(l?v+l+"M":"")+(u?v+u+"S":"")}var Co,Oo;Oo=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),i=e.length>>>0,o=0;o68?1900:2e3)};var yn,bn=it("FullYear",!0);yn=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;ethis?this:t:m()}),Xn=function(){return Date.now?Date.now():+new Date},Zn=["year","quarter","month","week","day","hour","minute","second","millisecond"];Ae("Z",":"),Ae("ZZ",""),U("Z",nn),U("ZZ",nn),K(["Z","ZZ"],function(t,e,i){i._useUTC=!0,i._tzm=ze(nn,t)});var Kn=/([\+\-]|\d\d)/gi;e.updateOffset=function(){};var Jn=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,$n=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;Ke.fn=Ie.prototype,Ke.invalid=Pe;var Qn=ti(1,"add"),ts=ti(-1,"subtract");e.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",e.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var es=k("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});H(0,["gg",2],0,function(){return this.weekYear()%100}),H(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Ai("gggg","weekYear"),Ai("ggggg","weekYear"),Ai("GGGG","isoWeekYear"),Ai("GGGGG","isoWeekYear"),A("weekYear","gg"),A("isoWeekYear","GG"),F("weekYear",1),F("isoWeekYear",1),U("G",en),U("g",en),U("GG",Xo,Go),U("gg",Xo,Go),U("GGGG",$o,Uo),U("gggg",$o,Uo),U("GGGGG",Qo,qo),U("ggggg",Qo,qo),J(["gggg","ggggg","GGGG","GGGGG"],function(t,e,i,o){e[o.substr(0,2)]=_(t)}),J(["gg","GG"],function(t,i,o,n){i[n]=e.parseTwoDigitYear(t)}),H("Q",0,"Qo","quarter"),A("quarter","Q"),F("quarter",7),U("Q",Yo),K("Q",function(t,e){e[ln]=3*(_(t)-1)}),H("D",["DD",2],"Do","date"),A("date","D"),F("date",9),U("D",Xo),U("DD",Xo,Go),U("Do",function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient}),K(["D","DD"],un),K("Do",function(t,e){e[un]=_(t.match(Xo)[0],10)});var is=it("Date",!0);H("DDD",["DDDD",3],"DDDo","dayOfYear"),A("dayOfYear","DDD"),F("dayOfYear",4),U("DDD",Jo),U("DDDD",Vo),K(["DDD","DDDD"],function(t,e,i){i._dayOfYear=_(t)}),H("m",["mm",2],0,"minute"),A("minute","m"),F("minute",14),U("m",Xo),U("mm",Xo,Go),K(["m","mm"],pn);var os=it("Minutes",!1);H("s",["ss",2],0,"second"),A("second","s"),F("second",15),U("s",Xo),U("ss",Xo,Go),K(["s","ss"],fn);var ns=it("Seconds",!1);H("S",0,0,function(){return~~(this.millisecond()/100)}),H(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),H(0,["SSS",3],0,"millisecond"),H(0,["SSSS",4],0,function(){return 10*this.millisecond()}),H(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),H(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),H(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),H(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),H(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),A("millisecond","ms"),F("millisecond",16),U("S",Jo,Yo),U("SS",Jo,Go),U("SSS",Jo,Vo);var ss;for(ss="SSSS";ss.length<=9;ss+="S")U(ss,tn);for(ss="S";ss.length<=9;ss+="S")K(ss,Gi);var rs=it("Milliseconds",!1);H("z",0,0,"zoneAbbr"),H("zz",0,0,"zoneName");var as=g.prototype;as.add=Qn,as.calendar=oi,as.clone=ni,as.diff=ui,as.endOf=Si,as.format=vi,as.from=gi,as.fromNow=yi,as.to=bi,as.toNow=_i,as.get=st,as.invalidAt=Ni,as.isAfter=si,as.isBefore=ri,as.isBetween=ai,as.isSame=hi,as.isSameOrAfter=di,as.isSameOrBefore=li,as.isValid=Pi,as.lang=es,as.locale=wi,as.localeData=xi,as.max=qn,as.min=Un,as.parsingFlags=Ii,as.set=rt,as.startOf=ki,as.subtract=ts,as.toArray=Oi,as.toObject=Ei,as.toDate=Ci,as.toISOString=fi,as.inspect=mi,as.toJSON=Ti,as.toString=pi,as.unix=Mi,as.valueOf=Di,as.creationData=Ri,as.year=bn,as.isLeapYear=et,as.weekYear=zi,as.isoWeekYear=Li,as.quarter=as.quarters=Wi,as.month=ft,as.daysInMonth=mt,as.week=as.weeks=Ot,as.isoWeek=as.isoWeeks=Et,as.weeksInYear=Bi,as.isoWeeksInYear=Fi,as.date=is,as.day=as.days=Lt,as.weekday=Ft,as.isoWeekday=Bt,as.dayOfYear=Yi,as.hour=as.hours=Rn,as.minute=as.minutes=os,as.second=as.seconds=ns,as.millisecond=as.milliseconds=rs,as.utcOffset=Be,as.utc=He,as.local=We,as.parseZone=Ye,as.hasAlignedHourOffset=Ge,as.isDST=Ve,as.isLocal=qe,as.isUtcOffset=Xe,as.isUtc=Ze,as.isUTC=Ze,as.zoneAbbr=Vi,as.zoneName=Ui,as.dates=k("dates accessor is deprecated. Use date instead.",is),as.months=k("months accessor is deprecated. Use month instead",ft),as.years=k("years accessor is deprecated. Use year instead",bn),as.zone=k("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",je),as.isDSTShifted=k("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Ue);var hs=O.prototype;hs.calendar=E,hs.longDateFormat=T,hs.invalidDate=P,hs.ordinal=I,hs.preparse=Zi,hs.postformat=Zi,hs.relativeTime=N,hs.pastFuture=R,hs.set=M,hs.months=dt,hs.monthsShort=lt,hs.monthsParse=ct,hs.monthsRegex=gt,hs.monthsShortRegex=vt,hs.week=Dt,hs.firstDayOfYear=Ct,hs.firstDayOfWeek=Mt,hs.weekdays=It,hs.weekdaysMin=Rt,hs.weekdaysShort=Nt,hs.weekdaysParse=zt,hs.weekdaysRegex=jt,hs.weekdaysShortRegex=Ht,hs.weekdaysMinRegex=Wt,hs.isPM=Xt,hs.meridiem=Zt,Qt("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===_(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),e.lang=k("moment.lang is deprecated. Use moment.locale instead.",Qt),e.langData=k("moment.langData is deprecated. Use moment.localeData instead.",ie);var ds=Math.abs,ls=mo("ms"),us=mo("s"),cs=mo("m"),ps=mo("h"),fs=mo("d"),ms=mo("w"),vs=mo("M"),gs=mo("y"),ys=yo("milliseconds"),bs=yo("seconds"),_s=yo("minutes"),ws=yo("hours"),xs=yo("days"),ks=yo("months"),Ss=yo("years"),Ds=Math.round,Ms={ss:44,s:45,m:45,h:22,d:26,M:11},Cs=Math.abs,Os=Ie.prototype;return Os.isValid=Te,Os.abs=no,Os.add=ro,Os.subtract=ao,Os.as=po,Os.asMilliseconds=ls,Os.asSeconds=us,Os.asMinutes=cs,Os.asHours=ps,Os.asDays=fs,Os.asWeeks=ms,Os.asMonths=vs,Os.asYears=gs,Os.valueOf=fo,Os._bubble=lo,Os.clone=vo,Os.get=go,Os.milliseconds=ys,Os.seconds=bs,Os.minutes=_s,Os.hours=ws,Os.days=xs,Os.weeks=bo,Os.months=ks,Os.years=Ss,Os.humanize=So,Os.toISOString=Mo,Os.toString=Mo,Os.toJSON=Mo,Os.locale=wi,Os.localeData=xi,Os.toIsoString=k("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Mo),Os.lang=es,H("X",0,0,"unix"),H("x",0,0,"valueOf"),U("x",en),U("X",sn),K("X",function(t,e,i){i._d=new Date(1e3*parseFloat(t,10))}),K("x",function(t,e,i){i._d=new Date(_(t))}),e.version="2.19.1",function(t){Co=t}(De),e.fn=as,e.min=Ce,e.max=Oe,e.now=Xn,e.utc=u,e.unix=qi,e.months=Qi,e.isDate=a,e.locale=Qt,e.invalid=m,e.duration=Ke,e.isMoment=y,e.weekdays=eo,e.parseZone=Xi,e.localeData=ie,e.isDuration=Ne,e.monthsShort=to,e.weekdaysMin=oo,e.defineLocale=te,e.updateLocale=ee,e.locales=oe,e.weekdaysShort=io,e.normalizeUnits=z,e.relativeTimeRounding=xo,e.relativeTimeThreshold=ko,e.calendarFormat=ii,e.prototype=as,e})}).call(e,i(155)(t))},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e){function i(t){throw new Error("Cannot find module '"+t+"'.")}i.keys=function(){return[]},i.resolve=i,t.exports=i,i.id=156},function(t,e,i){(function(e){function i(t,e,i){var o=e&&i||0,n=0;for(e=e||[],t.toLowerCase().replace(/[0-9a-f]{2}/g,function(t){n<16&&(e[o+n++]=u[t])});n<16;)e[o+n++]=0;return e}function o(t,e){var i=e||0,o=l;return o[t[i++]]+o[t[i++]]+o[t[i++]]+o[t[i++]]+"-"+o[t[i++]]+o[t[i++]]+"-"+o[t[i++]]+o[t[i++]]+"-"+o[t[i++]]+o[t[i++]]+"-"+o[t[i++]]+o[t[i++]]+o[t[i++]]+o[t[i++]]+o[t[i++]]+o[t[i++]]}function n(t,e,i){var n=e&&i||0,s=e||[];t=t||{};var r=void 0!==t.clockseq?t.clockseq:m,a=void 0!==t.msecs?t.msecs:(new Date).getTime(),h=void 0!==t.nsecs?t.nsecs:g+1,d=a-v+(h-g)/1e4;if(d<0&&void 0===t.clockseq&&(r=r+1&16383),(d<0||a>v)&&void 0===t.nsecs&&(h=0),h>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");v=a,g=h,m=r,a+=122192928e5;var l=(1e4*(268435455&a)+h)%4294967296;s[n++]=l>>>24&255,s[n++]=l>>>16&255,s[n++]=l>>>8&255,s[n++]=255&l;var u=a/4294967296*1e4&268435455;s[n++]=u>>>8&255,s[n++]=255&u,s[n++]=u>>>24&15|16,s[n++]=u>>>16&255,s[n++]=r>>>8|128,s[n++]=255&r;for(var c=t.node||f,p=0;p<6;p++)s[n+p]=c[p];return e||o(s)}function s(t,e,i){var n=e&&i||0;"string"==typeof t&&(e="binary"==t?new Array(16):null,t=null),t=t||{};var s=t.random||(t.rng||r)();if(s[6]=15&s[6]|64,s[8]=63&s[8]|128,e)for(var a=0;a<16;a++)e[n+a]=s[a];return e||o(s)}var r,a="undefined"!=typeof window?window:void 0!==e?e:null;if(a&&a.crypto&&crypto.getRandomValues){var h=new Uint8Array(16);r=function(){return crypto.getRandomValues(h),h}}if(!r){var d=new Array(16);r=function(){for(var t,e=0;e<16;e++)0==(3&e)&&(t=4294967296*Math.random()),d[e]=t>>>((3&e)<<3)&255;return d}}for(var l=[],u={},c=0;c<256;c++)l[c]=(c+256).toString(16).substr(1),u[l[c]]=c;var p=r(),f=[1|p[0],p[1],p[2],p[3],p[4],p[5]],m=16383&(p[6]<<8|p[7]),v=0,g=0,y=s;y.v1=n,y.v4=s,y.parse=i,y.unparse=o,t.exports=y}).call(e,i(158))},function(t,e){var i;i=function(){return this}();try{i=i||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(i=window)}t.exports=i},function(t,e,i){e.util=i(2),e.DOMutil=i(14),e.DataSet=i(11),e.DataView=i(12),e.Queue=i(43),e.Graph3d=i(161),e.graph3d={Camera:i(95),Filter:i(96),Point2d:i(91),Point3d:i(34),Slider:i(92),StepNumber:i(93)},e.moment=i(9),e.Hammer=i(10),e.keycharm=i(35)},function(t,e,i){var o=i(7),n=o.JSON||(o.JSON={stringify:JSON.stringify});t.exports=function(t){return n.stringify.apply(n,arguments)}},function(t,e,i){function o(t,e,i){if(!(this instanceof o))throw new SyntaxError("Constructor must be called with the new operator");this.containerElement=t,this.dataGroup=new _,this.dataPoints=null,this.create(),f.setDefaults(o.DEFAULTS,this),this.colX=void 0,this.colY=void 0,this.colZ=void 0,this.colValue=void 0,this.setOptions(i),this.setData(e)}function n(t){return"clientX"in t?t.clientX:t.targetTouches[0]&&t.targetTouches[0].clientX||0}function s(t){return"clientY"in t?t.clientY:t.targetTouches[0]&&t.targetTouches[0].clientY||0}var r=i(90),a=function(t){return t&&t.__esModule?t:{default:t}}(r),h=i(44),d=i(2),l=i(34),u=i(91),c=i(92),p=i(93),f=i(94),m=i(15).default,v=i(15),g=v.printStyle,y=i(172),b=y.allOptions,_=i(173);o.STYLE=f.STYLE;o.DEFAULTS={width:"400px",height:"400px",filterLabel:"time",legendLabel:"value",xLabel:"x",yLabel:"y",zLabel:"z",xValueLabel:function(t){return t},yValueLabel:function(t){return t},zValueLabel:function(t){return t},showXAxis:!0,showYAxis:!0,showZAxis:!0,showGrid:!0,showPerspective:!0,showShadow:!1,keepAspectRatio:!0,verticalRatio:.5,dotSizeRatio:.02,dotSizeMinFraction:.5,dotSizeMaxFraction:2.5,showAnimationControls:void 0,animationInterval:1e3,animationPreload:!1,animationAutoStart:void 0,axisColor:"#4D4D4D",gridColor:"#D3D3D3",xCenter:"55%",yCenter:"50%",style:o.STYLE.DOT,tooltip:!1,tooltipStyle:{content:{padding:"10px",border:"1px solid #4d4d4d",color:"#1a1a1a",background:"rgba(255,255,255,0.7)",borderRadius:"2px",boxShadow:"5px 5px 10px rgba(128,128,128,0.5)"},line:{height:"40px",width:"0",borderLeft:"1px solid #4d4d4d"},dot:{height:"0",width:"0",border:"5px solid #4d4d4d",borderRadius:"5px"}},dataColor:{fill:"#7DC1FF",stroke:"#3267D2",strokeWidth:1},cameraPosition:{horizontal:1,vertical:.5,distance:1.7},showLegend:void 0,backgroundColor:void 0,xBarWidth:void 0,yBarWidth:void 0,valueMin:void 0,valueMax:void 0,xMin:void 0,xMax:void 0,xStep:void 0,yMin:void 0,yMax:void 0,yStep:void 0,zMin:void 0,zMax:void 0,zStep:void 0},h(o.prototype),o.prototype._setScale=function(){this.scale=new l(1/this.xRange.range(),1/this.yRange.range(),1/this.zRange.range()),this.keepAspectRatio&&(this.scale.x0&&(r[n-1].pointNext=r[n]);return r},o.prototype.create=function(){for(;this.containerElement.hasChildNodes();)this.containerElement.removeChild(this.containerElement.firstChild);this.frame=document.createElement("div"),this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas);var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t),this.frame.filter=document.createElement("div"),this.frame.filter.style.position="absolute",this.frame.filter.style.bottom="0px",this.frame.filter.style.left="0px",this.frame.filter.style.width="100%",this.frame.appendChild(this.frame.filter);var e=this,i=function(t){e._onMouseDown(t)},o=function(t){e._onTouchStart(t)},n=function(t){e._onWheel(t)},s=function(t){e._onTooltip(t)},r=function(t){e._onClick(t)};d.addEventListener(this.frame.canvas,"mousedown",i),d.addEventListener(this.frame.canvas,"touchstart",o),d.addEventListener(this.frame.canvas,"mousewheel",n),d.addEventListener(this.frame.canvas,"mousemove",s),d.addEventListener(this.frame.canvas,"click",r),this.containerElement.appendChild(this.frame)},o.prototype._setSize=function(t,e){this.frame.style.width=t,this.frame.style.height=e,this._resizeCanvas()},o.prototype._resizeCanvas=function(){this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=this.frame.canvas.clientWidth,this.frame.canvas.height=this.frame.canvas.clientHeight,this.frame.filter.style.width=this.frame.canvas.clientWidth-20+"px"},o.prototype.animationStart=function(){if(this.animationAutoStart&&this.dataGroup.dataFilter){if(!this.frame.filter||!this.frame.filter.slider)throw new Error("No animation available");this.frame.filter.slider.play()}},o.prototype.animationStop=function(){this.frame.filter&&this.frame.filter.slider&&this.frame.filter.slider.stop()},o.prototype._resizeCenter=function(){"%"===this.xCenter.charAt(this.xCenter.length-1)?this.currentXCenter=parseFloat(this.xCenter)/100*this.frame.canvas.clientWidth:this.currentXCenter=parseFloat(this.xCenter),"%"===this.yCenter.charAt(this.yCenter.length-1)?this.currentYCenter=parseFloat(this.yCenter)/100*(this.frame.canvas.clientHeight-this.frame.filter.clientHeight):this.currentYCenter=parseFloat(this.yCenter)},o.prototype.getCameraPosition=function(){var t=this.camera.getArmRotation();return t.distance=this.camera.getArmLength(),t},o.prototype._readData=function(t){this.dataPoints=this.dataGroup.initializeData(this,t,this.style),this._initializeRanges(),this._redrawFilter()},o.prototype.setData=function(t){void 0!==t&&null!==t&&(this._readData(t),this.redraw(),this.animationStart())},o.prototype.setOptions=function(t){if(void 0!==t){!0===m.validate(t,b)&&console.log("%cErrors have been found in the supplied options object.",g),this.animationStop(),f.setOptions(t,this),this.setPointDrawingMethod(),this._setSize(this.width,this.height),this.setData(this.dataGroup.getDataTable()),this.animationStart()}},o.prototype.setPointDrawingMethod=function(){var t=void 0;switch(this.style){case o.STYLE.BAR:t=o.prototype._redrawBarGraphPoint;break;case o.STYLE.BARCOLOR:t=o.prototype._redrawBarColorGraphPoint;break;case o.STYLE.BARSIZE:t=o.prototype._redrawBarSizeGraphPoint;break;case o.STYLE.DOT:t=o.prototype._redrawDotGraphPoint;break;case o.STYLE.DOTLINE:t=o.prototype._redrawDotLineGraphPoint;break;case o.STYLE.DOTCOLOR:t=o.prototype._redrawDotColorGraphPoint;break;case o.STYLE.DOTSIZE:t=o.prototype._redrawDotSizeGraphPoint;break;case o.STYLE.SURFACE:t=o.prototype._redrawSurfaceGraphPoint;break;case o.STYLE.GRID:t=o.prototype._redrawGridGraphPoint;break;case o.STYLE.LINE:t=o.prototype._redrawLineGraphPoint;break;default:throw new Error("Can not determine point drawing method for graph style '"+this.style+"'")}this._pointDrawingMethod=t},o.prototype.redraw=function(){if(void 0===this.dataPoints)throw new Error("Graph data not initialized");this._resizeCanvas(),this._resizeCenter(),this._redrawSlider(),this._redrawClear(),this._redrawAxis(),this._redrawDataGraph(),this._redrawInfo(),this._redrawLegend()},o.prototype._getContext=function(){var t=this.frame.canvas,e=t.getContext("2d");return e.lineJoin="round",e.lineCap="round",e},o.prototype._redrawClear=function(){var t=this.frame.canvas;t.getContext("2d").clearRect(0,0,t.width,t.height)},o.prototype._dotSize=function(){return this.frame.clientWidth*this.dotSizeRatio},o.prototype._getLegendWidth=function(){var t;if(this.style===o.STYLE.DOTSIZE){t=this._dotSize()*this.dotSizeMaxFraction}else t=this.style===o.STYLE.BARSIZE?this.xBarWidth:20;return t},o.prototype._redrawLegend=function(){if(!0===this.showLegend&&this.style!==o.STYLE.LINE&&this.style!==o.STYLE.BARSIZE){var t=this.style===o.STYLE.BARSIZE||this.style===o.STYLE.DOTSIZE,e=this.style===o.STYLE.DOTSIZE||this.style===o.STYLE.DOTCOLOR||this.style===o.STYLE.BARCOLOR,i=Math.max(.25*this.frame.clientHeight,100),n=this.margin,s=this._getLegendWidth(),r=this.frame.clientWidth-this.margin,a=r-s,h=n+i,d=this._getContext();if(d.lineWidth=1,d.font="14px arial",!1===t){var l,c=i;for(l=0;l0?(t.textAlign="center",t.textBaseline="top",s.y+=n):Math.sin(2*o)<0?(t.textAlign="right",t.textBaseline="middle"):(t.textAlign="left",t.textBaseline="middle"),t.fillStyle=this.axisColor,t.fillText(i,s.x,s.y)},o.prototype.drawAxisLabelY=function(t,e,i,o,n){void 0===n&&(n=0);var s=this._convert3Dto2D(e);Math.cos(2*o)<0?(t.textAlign="center",t.textBaseline="top",s.y+=n):Math.sin(2*o)>0?(t.textAlign="right",t.textBaseline="middle"):(t.textAlign="left",t.textBaseline="middle"),t.fillStyle=this.axisColor,t.fillText(i,s.x,s.y)},o.prototype.drawAxisLabelZ=function(t,e,i,o){void 0===o&&(o=0);var n=this._convert3Dto2D(e);t.textAlign="right",t.textBaseline="middle",t.fillStyle=this.axisColor,t.fillText(i,n.x-o,n.y)},o.prototype._line3d=function(t,e,i,o){var n=this._convert3Dto2D(e),s=this._convert3Dto2D(i);this._line(t,n,s,o)},o.prototype._redrawAxis=function(){var t,e,i,o,n,s,r,a,h,d,c,f=this._getContext();f.font=24/this.camera.getArmLength()+"px arial";var m,v=.025/this.scale.x,g=.025/this.scale.y,y=5/this.camera.getArmLength(),b=this.camera.getArmRotation().horizontal,_=new u(Math.cos(b),Math.sin(b)),w=this.xRange,x=this.yRange,k=this.zRange;for(f.lineWidth=1,o=void 0===this.defaultXStep,i=new p(w.min,w.max,this.xStep,o),i.start(!0);!i.end();){var S=i.getCurrent();if(this.showGrid?(t=new l(S,x.min,k.min),e=new l(S,x.max,k.min),this._line3d(f,t,e,this.gridColor)):this.showXAxis&&(t=new l(S,x.min,k.min),e=new l(S,x.min+v,k.min),this._line3d(f,t,e,this.axisColor),t=new l(S,x.max,k.min),e=new l(S,x.max-v,k.min),this._line3d(f,t,e,this.axisColor)),this.showXAxis){r=_.x>0?x.min:x.max,m=new l(S,r,k.min);var D=" "+this.xValueLabel(S)+" ";this.drawAxisLabelX(f,m,D,b,y)}i.next()}for(f.lineWidth=1,o=void 0===this.defaultYStep,i=new p(x.min,x.max,this.yStep,o),i.start(!0);!i.end();){var M=i.getCurrent();if(this.showGrid?(t=new l(w.min,M,k.min),e=new l(w.max,M,k.min),this._line3d(f,t,e,this.gridColor)):this.showYAxis&&(t=new l(w.min,M,k.min),e=new l(w.min+g,M,k.min),this._line3d(f,t,e,this.axisColor),t=new l(w.max,M,k.min),e=new l(w.max-g,M,k.min),this._line3d(f,t,e,this.axisColor)),this.showYAxis){s=_.y>0?w.min:w.max,m=new l(s,M,k.min);var C=" "+this.yValueLabel(M)+" ";this.drawAxisLabelY(f,m,C,b,y)}i.next()}if(this.showZAxis){for(f.lineWidth=1,o=void 0===this.defaultZStep,i=new p(k.min,k.max,this.zStep,o),i.start(!0),s=_.x>0?w.min:w.max,r=_.y<0?x.min:x.max;!i.end();){var O=i.getCurrent(),E=new l(s,r,O),T=this._convert3Dto2D(E);e=new u(T.x-y,T.y),this._line(f,T,e,this.axisColor);var P=this.zValueLabel(O)+" ";this.drawAxisLabelZ(f,E,P,5),i.next()}f.lineWidth=1,t=new l(s,r,k.min),e=new l(s,r,k.max),this._line3d(f,t,e,this.axisColor)}if(this.showXAxis){var I,N;f.lineWidth=1,I=new l(w.min,x.min,k.min),N=new l(w.max,x.min,k.min),this._line3d(f,I,N,this.axisColor),I=new l(w.min,x.max,k.min),N=new l(w.max,x.max,k.min),this._line3d(f,I,N,this.axisColor)}this.showYAxis&&(f.lineWidth=1,t=new l(w.min,x.min,k.min),e=new l(w.min,x.max,k.min),this._line3d(f,t,e,this.axisColor),t=new l(w.max,x.min,k.min),e=new l(w.max,x.max,k.min),this._line3d(f,t,e,this.axisColor));var R=this.xLabel;R.length>0&&this.showXAxis&&(c=.1/this.scale.y,s=(w.max+3*w.min)/4,r=_.x>0?x.min-c:x.max+c,n=new l(s,r,k.min),this.drawAxisLabelX(f,n,R,b));var A=this.yLabel;A.length>0&&this.showYAxis&&(d=.1/this.scale.x,s=_.y>0?w.min-d:w.max+d,r=(x.max+3*x.min)/4,n=new l(s,r,k.min),this.drawAxisLabelY(f,n,A,b));var z=this.zLabel;z.length>0&&this.showZAxis&&(h=30,s=_.x>0?w.min:w.max,r=_.y<0?x.min:x.max,a=(k.max+3*k.min)/4,n=new l(s,r,a),this.drawAxisLabelZ(f,n,z,h))},o.prototype._hsv2rgb=function(t,e,i){var o,n,s,r,a,h;switch(r=i*e,a=Math.floor(t/60),h=r*(1-Math.abs(t/60%2-1)),a){case 0:o=r,n=h,s=0;break;case 1:o=h,n=r,s=0;break;case 2:o=0,n=r,s=h;break;case 3:o=0,n=h,s=r;break;case 4:o=h,n=0,s=r;break;case 5:o=r,n=0,s=h;break;default:o=0,n=0,s=0}return"RGB("+parseInt(255*o)+","+parseInt(255*n)+","+parseInt(255*s)+")"},o.prototype._getStrokeWidth=function(t){return void 0!==t?this.showPerspective?1/-t.trans.z*this.dataColor.strokeWidth:-this.eye.z/this.camera.getArmLength()*this.dataColor.strokeWidth:this.dataColor.strokeWidth},o.prototype._redrawBar=function(t,e,i,o,n,s){var r,a=this,h=e.point,d=this.zRange.min,u=[{point:new l(h.x-i,h.y-o,h.z)},{point:new l(h.x+i,h.y-o,h.z)},{point:new l(h.x+i,h.y+o,h.z)},{point:new l(h.x-i,h.y+o,h.z)}],c=[{point:new l(h.x-i,h.y-o,d)},{point:new l(h.x+i,h.y-o,d)},{point:new l(h.x+i,h.y+o,d)},{point:new l(h.x-i,h.y+o,d)}];u.forEach(function(t){t.screen=a._convert3Dto2D(t.point)}),c.forEach(function(t){t.screen=a._convert3Dto2D(t.point)});var p=[{corners:u,center:l.avg(c[0].point,c[2].point)},{corners:[u[0],u[1],c[1],c[0]],center:l.avg(c[1].point,c[0].point)},{corners:[u[1],u[2],c[2],c[1]],center:l.avg(c[2].point,c[1].point)},{corners:[u[2],u[3],c[3],c[2]],center:l.avg(c[3].point,c[2].point)},{corners:[u[3],u[0],c[0],c[3]],center:l.avg(c[0].point,c[3].point)}];e.surfaces=p;for(var f=0;f0}if(a){var p,f=(e.point.z+i.point.z+o.point.z+n.point.z)/4,m=240*(1-(f-this.zRange.min)*this.scale.z/this.verticalRatio);this.showShadow?(p=Math.min(1+u.x/c/2,1),s=this._hsv2rgb(m,1,p),r=s):(p=1,s=this._hsv2rgb(m,1,p),r=this.axisColor)}else s="gray",r=this.axisColor;t.lineWidth=this._getStrokeWidth(e);var v=[e,i,n,o];this._polygon(t,v,s,r)}},o.prototype._drawGridLine=function(t,e,i){if(void 0!==e&&void 0!==i){var o=(e.point.z+i.point.z)/2,n=240*(1-(o-this.zRange.min)*this.scale.z/this.verticalRatio);t.lineWidth=2*this._getStrokeWidth(e),t.strokeStyle=this._hsv2rgb(n,1,1),this._line(t,e.screen,i.screen)}},o.prototype._redrawGridGraphPoint=function(t,e){this._drawGridLine(t,e,e.pointRight),this._drawGridLine(t,e,e.pointTop)},o.prototype._redrawLineGraphPoint=function(t,e){void 0!==e.pointNext&&(t.lineWidth=this._getStrokeWidth(e),t.strokeStyle=this.dataColor.stroke,this._line(t,e.screen,e.pointNext.screen))},o.prototype._redrawDataGraph=function(){var t,e=this._getContext();if(!(void 0===this.dataPoints||this.dataPoints.length<=0))for(this._calcTranslations(this.dataPoints),t=0;t0?1:t<0?-1:0}var o=e[0],n=e[1],s=e[2],r=i((n.x-o.x)*(t.y-o.y)-(n.y-o.y)*(t.x-o.x)),a=i((s.x-n.x)*(t.y-n.y)-(s.y-n.y)*(t.x-n.x)),h=i((o.x-s.x)*(t.y-s.y)-(o.y-s.y)*(t.x-s.x));return!(0!=r&&0!=a&&r!=a||0!=a&&0!=h&&a!=h||0!=r&&0!=h&&r!=h)},o.prototype._dataPointFromXY=function(t,e){var i,n=null,s=null,r=null,a=new u(t,e);if(this.style===o.STYLE.BAR||this.style===o.STYLE.BARCOLOR||this.style===o.STYLE.BARSIZE)for(i=this.dataPoints.length-1;i>=0;i--){n=this.dataPoints[i];var h=n.surfaces;if(h)for(var d=h.length-1;d>=0;d--){var l=h[d],c=l.corners,p=[c[0].screen,c[1].screen,c[2].screen],f=[c[2].screen,c[3].screen,c[0].screen];if(this._insideTriangle(a,p)||this._insideTriangle(a,f))return n}}else for(i=0;i"+this.xLabel+":"+t.point.x+""+this.yLabel+":"+t.point.y+""+this.zLabel+":"+t.point.z+"",e.style.left="0",e.style.top="0",this.frame.appendChild(e),this.frame.appendChild(i),this.frame.appendChild(o);var n=e.offsetWidth,s=e.offsetHeight,r=i.offsetHeight,h=o.offsetWidth,d=o.offsetHeight,l=t.screen.x-n/2;l=Math.min(Math.max(l,10),this.frame.clientWidth-10-n),i.style.left=t.screen.x+"px",i.style.top=t.screen.y-r+"px",e.style.left=l+"px",e.style.top=t.screen.y-r-s+"px",o.style.left=t.screen.x-h/2+"px",o.style.top=t.screen.y-d/2+"px"},o.prototype._hideTooltip=function(){if(this.tooltip){this.tooltip.dataPoint=null;for(var t in this.tooltip.dom)if(this.tooltip.dom.hasOwnProperty(t)){var e=this.tooltip.dom[t];e&&e.parentNode&&e.parentNode.removeChild(e)}}},o.prototype.setCameraPosition=function(t){f.setCameraPosition(t,this),this.redraw()},o.prototype.setSize=function(t,e){this._setSize(t,e),this.redraw()},t.exports=o},function(t,e,i){i(163),t.exports=i(7).Object.assign},function(t,e,i){var o=i(17);o(o.S+o.F,"Object",{assign:i(164)})},function(t,e,i){var o=i(33),n=i(63),s=i(42),r=i(41),a=i(78),h=Object.assign;t.exports=!h||i(28)(function(){var t={},e={},i=Symbol(),o="abcdefghijklmnopqrst";return t[i]=7,o.split("").forEach(function(t){e[t]=t}),7!=h({},t)[i]||Object.keys(h({},e)).join("")!=o})?function(t,e){for(var i=r(t),h=arguments.length,d=1,l=n.f,u=s.f;h>d;)for(var c,p=a(arguments[d++]),f=l?o(p).concat(l(p)):o(p),m=f.length,v=0;m>v;)u.call(p,c=f[v++])&&(i[c]=p[c]);return i}:h},function(t,e,i){t.exports={default:i(166),__esModule:!0}},function(t,e,i){i(167),t.exports=i(7).Math.sign},function(t,e,i){var o=i(17);o(o.S,"Math",{sign:i(168)})},function(t,e){t.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:t<0?-1:1}},function(t,e,i){t.exports={default:i(170),__esModule:!0}},function(t,e,i){i(171);var o=i(7).Object;t.exports=function(t,e,i){return o.defineProperty(t,e,i)}},function(t,e,i){var o=i(17);o(o.S+o.F*!i(21),"Object",{defineProperty:i(20).f})},function(t,e,i){Object.defineProperty(e,"__esModule",{value:!0});var o="string",n="boolean",s="number",r={fill:{string:o},stroke:{string:o},strokeWidth:{number:s},__type__:{string:o,object:"object",undefined:"undefined"}},a={animationAutoStart:{boolean:n,undefined:"undefined"},animationInterval:{number:s},animationPreload:{boolean:n},axisColor:{string:o},backgroundColor:r,xBarWidth:{number:s,undefined:"undefined"},yBarWidth:{number:s,undefined:"undefined"},cameraPosition:{distance:{number:s},horizontal:{number:s},vertical:{number:s},__type__:{object:"object"}},xCenter:{string:o},yCenter:{string:o},dataColor:r,dotSizeMinFraction:{number:s},dotSizeMaxFraction:{number:s},dotSizeRatio:{number:s},filterLabel:{string:o},gridColor:{string:o},onclick:{function:"function"},keepAspectRatio:{boolean:n},xLabel:{string:o},yLabel:{string:o},zLabel:{string:o},legendLabel:{string:o},xMin:{number:s,undefined:"undefined"},yMin:{number:s,undefined:"undefined"},zMin:{number:s,undefined:"undefined"},xMax:{number:s,undefined:"undefined"},yMax:{number:s,undefined:"undefined"},zMax:{number:s,undefined:"undefined"},showAnimationControls:{boolean:n,undefined:"undefined"},showGrid:{boolean:n},showLegend:{boolean:n,undefined:"undefined"},showPerspective:{boolean:n},showShadow:{boolean:n},showXAxis:{boolean:n},showYAxis:{boolean:n},showZAxis:{boolean:n},xStep:{number:s,undefined:"undefined"},yStep:{number:s,undefined:"undefined"},zStep:{number:s,undefined:"undefined"},style:{number:s,string:["bar","bar-color","bar-size","dot","dot-line","dot-color","dot-size","line","grid","surface"]},tooltip:{boolean:n,function:"function"},tooltipStyle:{content:{color:{string:o},background:{string:o},border:{string:o},borderRadius:{string:o},boxShadow:{string:o},padding:{string:o},__type__:{object:"object"}},line:{borderLeft:{string:o},height:{string:o},width:{string:o},__type__:{object:"object"}},dot:{border:{string:o},borderRadius:{string:o},height:{string:o},width:{string:o},__type__:{object:"object"}},__type__:{object:"object"}},xValueLabel:{function:"function"},yValueLabel:{function:"function"},zValueLabel:{function:"function"},valueMax:{number:s,undefined:"undefined"},valueMin:{number:s,undefined:"undefined"},verticalRatio:{number:s},height:{string:o},width:{string:o},__type__:{object:"object"}};e.allOptions=a},function(t,e,i){function o(){this.dataTable=null}var n=i(11),s=i(12),r=i(174),a=i(96),h=i(94),d=i(34);o.prototype.initializeData=function(t,e,i){if(void 0!==e){Array.isArray(e)&&(e=new n(e));var o;if(!(e instanceof n||e instanceof s))throw new Error("Array, DataSet, or DataView expected");if(o=e.get(),0!=o.length){this.style=i,this.dataSet&&this.dataSet.off("*",this._onChange),this.dataSet=e,this.dataTable=o;var r=this;this._onChange=function(){t.setData(r.dataSet)},this.dataSet.on("*",this._onChange),this.colX="x",this.colY="y",this.colZ="z";var h=t.hasBars(i);if(h&&(void 0!==t.defaultXBarWidth?this.xBarWidth=t.defaultXBarWidth:this.xBarWidth=this.getSmallestDifference(o,this.colX)||1,void 0!==t.defaultYBarWidth?this.yBarWidth=t.defaultYBarWidth:this.yBarWidth=this.getSmallestDifference(o,this.colY)||1),this._initializeRange(o,this.colX,t,h),this._initializeRange(o,this.colY,t,h),this._initializeRange(o,this.colZ,t,!1),o[0].hasOwnProperty("style")){this.colValue="style";var d=this.getColumnRange(o,this.colValue);this._setRangeDefaults(d,t.defaultValueMin,t.defaultValueMax),this.valueRange=d}this.getDataTable()[0].hasOwnProperty("filter")&&void 0===this.dataFilter&&(this.dataFilter=new a(this,"filter",t),this.dataFilter.setOnLoadCallback(function(){t.redraw()}));return this.dataFilter?this.dataFilter._getDataPoints():this._getDataPoints(this.getDataTable())}}},o.prototype._collectRangeSettings=function(t,e){if(-1==["x","y","z"].indexOf(t))throw new Error("Column '"+t+"' invalid");var i=t.toUpperCase();return{barWidth:this[t+"BarWidth"],min:e["default"+i+"Min"],max:e["default"+i+"Max"],step:e["default"+i+"Step"],range_label:t+"Range",step_label:t+"Step"}},o.prototype._initializeRange=function(t,e,i,o){var n=this._collectRangeSettings(e,i),s=this.getColumnRange(t,e);o&&"z"!=e&&s.expand(n.barWidth/2),this._setRangeDefaults(s,n.min,n.max),this[n.range_label]=s,this[n.step_label]=void 0!==n.step?n.step:s.range()/5},o.prototype.getDistinctValues=function(t,e){void 0===e&&(e=this.dataTable);for(var i=[],o=0;os)&&(o=s)}return o},o.prototype.getColumnRange=function(t,e){for(var i=new r,o=0;o0&&(e[i-1].pointNext=e[i]);return e},o.prototype._checkValueField=function(t){if(this.style===h.STYLE.BARCOLOR||this.style===h.STYLE.BARSIZE||this.style===h.STYLE.DOTCOLOR||this.style===h.STYLE.DOTSIZE){if(void 0===this.colValue)throw new Error("Expected data to have field 'style' for graph style '"+this.style+"'");if(void 0===t[0][this.colValue])throw new Error("Expected data to have field '"+this.colValue+"' for graph style '"+this.style+"'")}},t.exports=o},function(t,e,i){function o(){this.min=void 0,this.max=void 0}o.prototype.adjust=function(t){void 0!==t&&((void 0===this.min||this.min>t)&&(this.min=t),(void 0===this.max||this.maxi)throw new Error("Passed expansion value makes range invalid");this.min=e,this.max=i}},o.prototype.range=function(){return this.max-this.min},o.prototype.center=function(){return(this.min+this.max)/2},t.exports=o},function(t,e,i){var o,n,s;!function(i){n=[],o=i,void 0!==(s="function"==typeof o?o.apply(e,n):o)&&(t.exports=s)}(function(){var t=null;return function e(i,o){function n(t){return t.match(/[^ ]+/g)}function s(e){if("hammer.input"!==e.type){if(e.srcEvent._handled||(e.srcEvent._handled={}),e.srcEvent._handled[e.type])return;e.srcEvent._handled[e.type]=!0}var i=!1;e.stopPropagation=function(){i=!0};var o=e.srcEvent.stopPropagation.bind(e.srcEvent);"function"==typeof o&&(e.srcEvent.stopPropagation=function(){o(),e.stopPropagation()}),e.firstTarget=t;for(var n=t;n&&!i;){var s=n.hammer;if(s)for(var r,a=0;a0?d._handlers[t]=o:(i.off(t,s),delete d._handlers[t]))}),d},d.emit=function(e,o){t=o.target,i.emit(e,o)},d.destroy=function(){var t=i.element.hammer,e=t.indexOf(d);-1!==e&&t.splice(e,1),t.length||delete i.element.hammer,d._handlers={},i.destroy()},d}})},function(t,e,i){var o;!function(n,s,r,a){function h(t,e,i){return setTimeout(p(t,i),e)}function d(t,e,i){return!!Array.isArray(t)&&(l(t,i[e],i),!0)}function l(t,e,i){var o;if(t)if(t.forEach)t.forEach(e,i);else if(t.length!==a)for(o=0;o\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",s=n.console&&(n.console.warn||n.console.log);return s&&s.call(n.console,o,i),t.apply(this,arguments)}}function c(t,e,i){var o,n=e.prototype;o=t.prototype=Object.create(n),o.constructor=t,o._super=n,i&&ft(o,i)}function p(t,e){return function(){return t.apply(e,arguments)}}function f(t,e){return typeof t==gt?t.apply(e?e[0]||a:a,e):t}function m(t,e){return t===a?e:t}function v(t,e,i){l(_(e),function(e){t.addEventListener(e,i,!1)})}function g(t,e,i){l(_(e),function(e){t.removeEventListener(e,i,!1)})}function y(t,e){for(;t;){if(t==e)return!0;t=t.parentNode}return!1}function b(t,e){return t.indexOf(e)>-1}function _(t){return t.trim().split(/\s+/g)}function w(t,e,i){if(t.indexOf&&!i)return t.indexOf(e);for(var o=0;oi[e]}):o.sort()),o}function S(t,e){for(var i,o,n=e[0].toUpperCase()+e.slice(1),s=0;s1&&!i.firstMultiple?i.firstMultiple=N(e):1===n&&(i.firstMultiple=!1);var s=i.firstInput,r=i.firstMultiple,a=r?r.center:s.center,h=e.center=R(o);e.timeStamp=_t(),e.deltaTime=e.timeStamp-s.timeStamp,e.angle=F(a,h),e.distance=L(a,h),P(i,e),e.offsetDirection=z(e.deltaX,e.deltaY);var d=A(e.deltaTime,e.deltaX,e.deltaY);e.overallVelocityX=d.x,e.overallVelocityY=d.y,e.overallVelocity=bt(d.x)>bt(d.y)?d.x:d.y,e.scale=r?j(r.pointers,o):1,e.rotation=r?B(r.pointers,o):0,e.maxPointers=i.prevInput?e.pointers.length>i.prevInput.maxPointers?e.pointers.length:i.prevInput.maxPointers:e.pointers.length,I(i,e);var l=t.element;y(e.srcEvent.target,l)&&(l=e.srcEvent.target),e.target=l}function P(t,e){var i=e.center,o=t.offsetDelta||{},n=t.prevDelta||{},s=t.prevInput||{};e.eventType!==Et&&s.eventType!==Pt||(n=t.prevDelta={x:s.deltaX||0,y:s.deltaY||0},o=t.offsetDelta={x:i.x,y:i.y}),e.deltaX=n.x+(i.x-o.x),e.deltaY=n.y+(i.y-o.y)}function I(t,e){var i,o,n,s,r=t.lastInterval||e,h=e.timeStamp-r.timeStamp;if(e.eventType!=It&&(h>Ot||r.velocity===a)){var d=e.deltaX-r.deltaX,l=e.deltaY-r.deltaY,u=A(h,d,l);o=u.x,n=u.y,i=bt(u.x)>bt(u.y)?u.x:u.y,s=z(d,l),t.lastInterval=e}else i=r.velocity,o=r.velocityX,n=r.velocityY,s=r.direction;e.velocity=i,e.velocityX=o,e.velocityY=n,e.direction=s}function N(t){for(var e=[],i=0;i=bt(e)?t<0?Rt:At:e<0?zt:Lt}function L(t,e,i){i||(i=Ht);var o=e[i[0]]-t[i[0]],n=e[i[1]]-t[i[1]];return Math.sqrt(o*o+n*n)}function F(t,e,i){i||(i=Ht);var o=e[i[0]]-t[i[0]],n=e[i[1]]-t[i[1]];return 180*Math.atan2(n,o)/Math.PI}function B(t,e){return F(e[1],e[0],Wt)+F(t[1],t[0],Wt)}function j(t,e){return L(e[0],e[1],Wt)/L(t[0],t[1],Wt)}function H(){this.evEl=Gt,this.evWin=Vt,this.pressed=!1,C.apply(this,arguments)}function W(){this.evEl=Xt,this.evWin=Zt,C.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function Y(){this.evTarget=Jt,this.evWin=$t,this.started=!1,C.apply(this,arguments)}function G(t,e){var i=x(t.touches),o=x(t.changedTouches);return e&(Pt|It)&&(i=k(i.concat(o),"identifier",!0)),[i,o]}function V(){this.evTarget=te,this.targetIds={},C.apply(this,arguments)}function U(t,e){var i=x(t.touches),o=this.targetIds;if(e&(Et|Tt)&&1===i.length)return o[i[0].identifier]=!0,[i,i];var n,s,r=x(t.changedTouches),a=[],h=this.target;if(s=i.filter(function(t){return y(t.target,h)}),e===Et)for(n=0;n-1&&o.splice(t,1)};setTimeout(n,ee)}}function K(t){for(var e=t.srcEvent.clientX,i=t.srcEvent.clientY,o=0;o-1&&this.requireFail.splice(e,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(t){return!!this.simultaneous[t.id]},emit:function(t){function e(e){i.manager.emit(e,t)}var i=this,o=this.state;o=fe&&e(i.options.event+tt(o))},tryEmit:function(t){if(this.canEmit())return this.emit(t);this.state=32},canEmit:function(){for(var t=0;te.threshold&&n&e.direction},attrTest:function(t){return ot.prototype.attrTest.call(this,t)&&(this.state&ce||!(this.state&ce)&&this.directionTest(t))},emit:function(t){this.pX=t.deltaX,this.pY=t.deltaY;var e=et(t.direction);e&&(t.additionalEvent=this.options.event+e),this._super.emit.call(this,t)}}),c(st,ot,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[ae]},attrTest:function(t){return this._super.attrTest.call(this,t)&&(Math.abs(t.scale-1)>this.options.threshold||this.state&ce)},emit:function(t){if(1!==t.scale){var e=t.scale<1?"in":"out";t.additionalEvent=this.options.event+e}this._super.emit.call(this,t)}}),c(rt,Q,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[se]},process:function(t){var e=this.options,i=t.pointers.length===e.pointers,o=t.distancee.time;if(this._input=t,!o||!i||t.eventType&(Pt|It)&&!n)this.reset();else if(t.eventType&Et)this.reset(),this._timer=h(function(){this.state=me,this.tryEmit()},e.time,this);else if(t.eventType&Pt)return me;return 32},reset:function(){clearTimeout(this._timer)},emit:function(t){this.state===me&&(t&&t.eventType&Pt?this.manager.emit(this.options.event+"up",t):(this._input.timeStamp=_t(),this.manager.emit(this.options.event,this._input)))}}),c(at,ot,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[ae]},attrTest:function(t){return this._super.attrTest.call(this,t)&&(Math.abs(t.rotation)>this.options.threshold||this.state&ce)}}),c(ht,ot,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Ft|Bt,pointers:1},getTouchAction:function(){return nt.prototype.getTouchAction.call(this)},attrTest:function(t){var e,i=this.options.direction;return i&(Ft|Bt)?e=t.overallVelocity:i&Ft?e=t.overallVelocityX:i&Bt&&(e=t.overallVelocityY),this._super.attrTest.call(this,t)&&i&t.offsetDirection&&t.distance>this.options.threshold&&t.maxPointers==this.options.pointers&&bt(e)>this.options.velocity&&t.eventType&Pt},emit:function(t){var e=et(t.offsetDirection);e&&this.manager.emit(this.options.event+e,t),this.manager.emit(this.options.event,t)}}),c(dt,Q,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[re]},process:function(t){var e=this.options,i=t.pointers.length===e.pointers,o=t.distanced+i?s+=h()+u-i+t.itemSet.options.margin.item.vertical:r=!1,s=Math.min(s,o-i),{shouldScroll:r,scrollOffset:s,itemTop:l}}var a=i(9),h=i(2),d=i(11),l=i(12),u=i(64),c=i(65),p=i(45),f=i(67),m=i(46),v=i(99),g=i(15).printStyle,y=i(105).allOptions,b=i(105).configureOptions,_=i(71).default,w=i(15).default;o.prototype=new c,o.prototype._createConfigurator=function(){return new _(this,this.dom.container,b)},o.prototype.redraw=function(){this.itemSet&&this.itemSet.markDirty({refreshItems:!0}),this._redraw()},o.prototype.setOptions=function(t){if(!0===w.validate(t,y)&&console.log("%cErrors have been found in the supplied options object.",g),c.prototype.setOptions.call(this,t),"type"in t&&t.type!==this.options.type){this.options.type=t.type;var e=this.itemsData;if(e){var i=this.getSelection();this.setItems(null),this.setItems(e),this.setSelection(i)}}},o.prototype.setItems=function(t){var e;e=t?t instanceof d||t instanceof l?t:new d(t,{type:{start:"Date",end:"Date"}}):null,this.itemsData=e,this.itemSet&&this.itemSet.setItems(e)},o.prototype.setGroups=function(t){var e;if(t){var i=function(t){return!1!==t.visible};e=t instanceof d||t instanceof l?new l(t,{filter:i}):new d(t.filter(i))}else e=null;this.groupsData=e,this.itemSet.setGroups(e)},o.prototype.setData=function(t){t&&t.groups&&this.setGroups(t.groups),t&&t.items&&this.setItems(t.items)},o.prototype.setSelection=function(t,e){this.itemSet&&this.itemSet.setSelection(t),e&&e.focus&&this.focus(t,e)},o.prototype.getSelection=function(){return this.itemSet&&this.itemSet.getSelection()||[]},o.prototype.focus=function(t,e){if(this.itemsData&&void 0!=t){var i=Array.isArray(t)?t:[t],o=this.itemsData.getDataSet().get(i,{type:{start:"Date",end:"Date"}}),n=null,s=null;if(o.forEach(function(t){var e=t.start.valueOf(),i="end"in t?t.end.valueOf():t.start.valueOf();(null===n||es)&&(s=i)}),null!==n&&null!==s){var a=this,h=this.itemSet.items[i[0]],d=-1*this._getScrollTop(),l=null,u=function(t,e,i){var o=r(a,h);if(l||(l=o),l.itemTop!=o.itemTop||l.shouldScroll){l.itemTop!=o.itemTop&&o.shouldScroll&&(l=o,d=-1*a._getScrollTop());var n=d,s=l.scrollOffset,u=i?s:n+(s-n)*t;a._setScrollTop(-u),e||a._redraw()}},c=function(){var t=r(a,h);t.shouldScroll&&t.itemTop!=l.itemTop&&(a._setScrollTop(-t.scrollOffset),a._redraw())},p=function(){c(),setTimeout(c,100)},f=(n+s)/2,m=Math.max(this.range.end-this.range.start,1.1*(s-n)),v=!e||void 0===e.animation||e.animation;v||(l={shouldScroll:!1,scrollOffset:-1,itemTop:-1}),this.range.setRange(f-m/2,f+m/2,{animation:v},p,u)}}},o.prototype.fit=function(t,e){var i,o=!t||void 0===t.animation||t.animation,n=this.itemsData&&this.itemsData.getDataSet();1===n.length&&void 0===n.get()[0].end?(i=this.getDataRange(),this.moveTo(i.min.valueOf(),{animation:o},e)):(i=this.getItemRange(),this.range.setRange(i.min,i.max,{animation:o},e))},o.prototype.getItemRange=function(){var t=this.getDataRange(),e=null!==t.min?t.min.valueOf():null,i=null!==t.max?t.max.valueOf():null,o=null,r=null;if(null!=e&&null!=i){var a=i-e;a<=0&&(a=10);var d=a/this.props.center.width,l={},u=0;h.forEach(this.itemSet.items,function(t,e){if(t.groupShowing){l[e]=t.redraw(!0),u=l[e].length}});if(u>0)for(var c=0;ci&&(i=h,r=t)}.bind(this)),o&&r){var p=o.getWidthLeft()+10,f=r.getWidthRight()+10,m=this.props.center.width-p-f;m>0&&(this.options.rtl?(e=n(o)-f*a/m,i=s(r)+p*a/m):(e=n(o)-p*a/m,i=s(r)+f*a/m))}}return{min:null!=e?new Date(e):null,max:null!=i?new Date(i):null}},o.prototype.getDataRange=function(){var t=null,e=null,i=this.itemsData&&this.itemsData.getDataSet();return i&&i.forEach(function(i){var o=h.convert(i.start,"Date").valueOf(),n=h.convert(void 0!=i.end?i.end:i.start,"Date").valueOf();(null===t||oe)&&(e=n)}),{min:null!=t?new Date(t):null,max:null!=e?new Date(e):null}},o.prototype.getEventProperties=function(t){var e,i=t.center?t.center.x:t.clientX,o=t.center?t.center.y:t.clientY;e=this.options.rtl?h.getAbsoluteRight(this.dom.centerContainer)-i:i-h.getAbsoluteLeft(this.dom.centerContainer);var n=o-h.getAbsoluteTop(this.dom.centerContainer),s=this.itemSet.itemFromTarget(t),r=this.itemSet.groupFromTarget(t),a=m.customTimeFromTarget(t),d=this.itemSet.options.snap||null,l=this.body.util.getScale(),u=this.body.util.getStep(),c=this._toTime(e),p=d?d(c,l,u):c,f=h.getTarget(t),v=null;return null!=s?v="item":null!=a?v="custom-time":h.hasParent(f,this.timeAxis.dom.foreground)?v="axis":this.timeAxis2&&h.hasParent(f,this.timeAxis2.dom.foreground)?v="axis":h.hasParent(f,this.itemSet.dom.labelSet)?v="group-label":h.hasParent(f,this.currentTime.bar)?v="current-time":h.hasParent(f,this.dom.center)&&(v="background"),{event:t,item:s?s.id:null,group:r?r.groupId:null,what:v,pageX:t.srcEvent?t.srcEvent.pageX:t.pageX,pageY:t.srcEvent?t.srcEvent.pageY:t.pageY,x:e,y:n,time:c,snappedTime:p}},o.prototype.toggleRollingMode=function(){this.range.rolling?this.range.stopRolling():(void 0==this.options.rollingMode&&this.setOptions(this.options),this.range.startRolling())},t.exports=o},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(19),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(10),u=i(37),c=i(2),p=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;(0,a.default)(this,t),this.pixelRatio=e,this.generated=!1,this.centerCoordinates={x:144.5,y:144.5},this.r=289*.49,this.color={r:255,g:255,b:255,a:1},this.hueCircle=void 0,this.initialColor={r:255,g:255,b:255,a:1},this.previousColor=void 0,this.applied=!1,this.updateCallback=function(){},this.closeCallback=function(){},this._create()}return(0,d.default)(t,[{key:"insertTo",value:function(t){void 0!==this.hammer&&(this.hammer.destroy(),this.hammer=void 0),this.container=t,this.container.appendChild(this.frame),this._bindHammer(),this._setSize()}},{key:"setUpdateCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker update callback is not a function.");this.updateCallback=t}},{key:"setCloseCallback",value:function(t){if("function"!=typeof t)throw new Error("Function attempted to set as colorPicker closing callback is not a function.");this.closeCallback=t}},{key:"_isColorString",value:function(t){var e={black:"#000000",navy:"#000080",darkblue:"#00008B",mediumblue:"#0000CD",blue:"#0000FF",darkgreen:"#006400",green:"#008000",teal:"#008080",darkcyan:"#008B8B",deepskyblue:"#00BFFF",darkturquoise:"#00CED1",mediumspringgreen:"#00FA9A",lime:"#00FF00",springgreen:"#00FF7F",aqua:"#00FFFF",cyan:"#00FFFF",midnightblue:"#191970",dodgerblue:"#1E90FF",lightseagreen:"#20B2AA",forestgreen:"#228B22",seagreen:"#2E8B57",darkslategray:"#2F4F4F",limegreen:"#32CD32",mediumseagreen:"#3CB371",turquoise:"#40E0D0",royalblue:"#4169E1",steelblue:"#4682B4",darkslateblue:"#483D8B",mediumturquoise:"#48D1CC",indigo:"#4B0082",darkolivegreen:"#556B2F",cadetblue:"#5F9EA0",cornflowerblue:"#6495ED",mediumaquamarine:"#66CDAA",dimgray:"#696969",slateblue:"#6A5ACD",olivedrab:"#6B8E23",slategray:"#708090",lightslategray:"#778899",mediumslateblue:"#7B68EE",lawngreen:"#7CFC00",chartreuse:"#7FFF00",aquamarine:"#7FFFD4",maroon:"#800000",purple:"#800080",olive:"#808000",gray:"#808080",skyblue:"#87CEEB",lightskyblue:"#87CEFA",blueviolet:"#8A2BE2",darkred:"#8B0000",darkmagenta:"#8B008B",saddlebrown:"#8B4513",darkseagreen:"#8FBC8F",lightgreen:"#90EE90",mediumpurple:"#9370D8",darkviolet:"#9400D3",palegreen:"#98FB98",darkorchid:"#9932CC",yellowgreen:"#9ACD32",sienna:"#A0522D",brown:"#A52A2A",darkgray:"#A9A9A9",lightblue:"#ADD8E6",greenyellow:"#ADFF2F",paleturquoise:"#AFEEEE",lightsteelblue:"#B0C4DE",powderblue:"#B0E0E6",firebrick:"#B22222",darkgoldenrod:"#B8860B",mediumorchid:"#BA55D3",rosybrown:"#BC8F8F",darkkhaki:"#BDB76B",silver:"#C0C0C0",mediumvioletred:"#C71585",indianred:"#CD5C5C",peru:"#CD853F",chocolate:"#D2691E",tan:"#D2B48C",lightgrey:"#D3D3D3",palevioletred:"#D87093",thistle:"#D8BFD8",orchid:"#DA70D6",goldenrod:"#DAA520",crimson:"#DC143C",gainsboro:"#DCDCDC",plum:"#DDA0DD",burlywood:"#DEB887",lightcyan:"#E0FFFF",lavender:"#E6E6FA",darksalmon:"#E9967A",violet:"#EE82EE",palegoldenrod:"#EEE8AA",lightcoral:"#F08080",khaki:"#F0E68C",aliceblue:"#F0F8FF",honeydew:"#F0FFF0",azure:"#F0FFFF",sandybrown:"#F4A460",wheat:"#F5DEB3",beige:"#F5F5DC",whitesmoke:"#F5F5F5",mintcream:"#F5FFFA",ghostwhite:"#F8F8FF",salmon:"#FA8072",antiquewhite:"#FAEBD7",linen:"#FAF0E6",lightgoldenrodyellow:"#FAFAD2",oldlace:"#FDF5E6",red:"#FF0000",fuchsia:"#FF00FF",magenta:"#FF00FF",deeppink:"#FF1493",orangered:"#FF4500",tomato:"#FF6347",hotpink:"#FF69B4",coral:"#FF7F50",darkorange:"#FF8C00",lightsalmon:"#FFA07A",orange:"#FFA500",lightpink:"#FFB6C1",pink:"#FFC0CB",gold:"#FFD700",peachpuff:"#FFDAB9",navajowhite:"#FFDEAD",moccasin:"#FFE4B5",bisque:"#FFE4C4",mistyrose:"#FFE4E1",blanchedalmond:"#FFEBCD",papayawhip:"#FFEFD5",lavenderblush:"#FFF0F5",seashell:"#FFF5EE",cornsilk:"#FFF8DC",lemonchiffon:"#FFFACD",floralwhite:"#FFFAF0",snow:"#FFFAFA",yellow:"#FFFF00",lightyellow:"#FFFFE0",ivory:"#FFFFF0",white:"#FFFFFF"};if("string"==typeof t)return e[t]}},{key:"setColor",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if("none"!==t){var i=void 0,o=this._isColorString(t);if(void 0!==o&&(t=o),!0===c.isString(t)){if(!0===c.isValidRGB(t)){var n=t.substr(4).substr(0,t.length-5).split(",");i={r:n[0],g:n[1],b:n[2],a:1}}else if(!0===c.isValidRGBA(t)){var r=t.substr(5).substr(0,t.length-6).split(",");i={r:r[0],g:r[1],b:r[2],a:r[3]}}else if(!0===c.isValidHex(t)){var a=c.hexToRGB(t);i={r:a.r,g:a.g,b:a.b,a:1}}}else if(t instanceof Object&&void 0!==t.r&&void 0!==t.g&&void 0!==t.b){var h=void 0!==t.a?t.a:"1.0";i={r:t.r,g:t.g,b:t.b,a:h}}if(void 0===i)throw new Error("Unknown color passed to the colorPicker. Supported are strings: rgb, hex, rgba. Object: rgb ({r:r,g:g,b:b,[a:a]}). Supplied: "+(0,s.default)(t));this._setColor(i,e)}}},{key:"show",value:function(){void 0!==this.closeCallback&&(this.closeCallback(),this.closeCallback=void 0),this.applied=!1,this.frame.style.display="block",this._generateHueCircle()}},{key:"_hide",value:function(){var t=this;!0===(!(arguments.length>0&&void 0!==arguments[0])||arguments[0])&&(this.previousColor=c.extend({},this.color)),!0===this.applied&&this.updateCallback(this.initialColor),this.frame.style.display="none",setTimeout(function(){void 0!==t.closeCallback&&(t.closeCallback(),t.closeCallback=void 0)},0)}},{key:"_save",value:function(){this.updateCallback(this.color),this.applied=!1,this._hide()}},{key:"_apply",value:function(){this.applied=!0,this.updateCallback(this.color),this._updatePicker(this.color)}},{key:"_loadLast",value:function(){void 0!==this.previousColor?this.setColor(this.previousColor,!1):alert("There is no last color to load...")}},{key:"_setColor",value:function(t){!0===(!(arguments.length>1&&void 0!==arguments[1])||arguments[1])&&(this.initialColor=c.extend({},t)),this.color=t;var e=c.RGBToHSV(t.r,t.g,t.b),i=2*Math.PI,o=this.r*e.s,n=this.centerCoordinates.x+o*Math.sin(i*e.h),s=this.centerCoordinates.y+o*Math.cos(i*e.h);this.colorPickerSelector.style.left=n-.5*this.colorPickerSelector.clientWidth+"px",this.colorPickerSelector.style.top=s-.5*this.colorPickerSelector.clientHeight+"px",this._updatePicker(t)}},{key:"_setOpacity",value:function(t){this.color.a=t/100,this._updatePicker(this.color)}},{key:"_setBrightness",value:function(t){var e=c.RGBToHSV(this.color.r,this.color.g,this.color.b);e.v=t/100;var i=c.HSVToRGB(e.h,e.s,e.v);i.a=this.color.a,this.color=i,this._updatePicker()}},{key:"_updatePicker",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.color,e=c.RGBToHSV(t.r,t.g,t.b),i=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1)),i.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var o=this.colorPickerCanvas.clientWidth,n=this.colorPickerCanvas.clientHeight;i.clearRect(0,0,o,n),i.putImageData(this.hueCircle,0,0),i.fillStyle="rgba(0,0,0,"+(1-e.v)+")",i.circle(this.centerCoordinates.x,this.centerCoordinates.y,this.r),i.fill(),this.brightnessRange.value=100*e.v,this.opacityRange.value=100*t.a,this.initialColorDiv.style.backgroundColor="rgba("+this.initialColor.r+","+this.initialColor.g+","+this.initialColor.b+","+this.initialColor.a+")",this.newColorDiv.style.backgroundColor="rgba("+this.color.r+","+this.color.g+","+this.color.b+","+this.color.a+")"}},{key:"_setSize",value:function(){this.colorPickerCanvas.style.width="100%",this.colorPickerCanvas.style.height="100%",this.colorPickerCanvas.width=289*this.pixelRatio,this.colorPickerCanvas.height=289*this.pixelRatio}},{key:"_create",value:function(){if(this.frame=document.createElement("div"),this.frame.className="vis-color-picker",this.colorPickerDiv=document.createElement("div"),this.colorPickerSelector=document.createElement("div"),this.colorPickerSelector.className="vis-selector",this.colorPickerDiv.appendChild(this.colorPickerSelector),this.colorPickerCanvas=document.createElement("canvas"),this.colorPickerDiv.appendChild(this.colorPickerCanvas),this.colorPickerCanvas.getContext){var t=this.colorPickerCanvas.getContext("2d") +;this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1),this.colorPickerCanvas.getContext("2d").setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}else{var e=document.createElement("DIV");e.style.color="red",e.style.fontWeight="bold",e.style.padding="10px",e.innerHTML="Error: your browser does not support HTML canvas",this.colorPickerCanvas.appendChild(e)}this.colorPickerDiv.className="vis-color",this.opacityDiv=document.createElement("div"),this.opacityDiv.className="vis-opacity",this.brightnessDiv=document.createElement("div"),this.brightnessDiv.className="vis-brightness",this.arrowDiv=document.createElement("div"),this.arrowDiv.className="vis-arrow",this.opacityRange=document.createElement("input");try{this.opacityRange.type="range",this.opacityRange.min="0",this.opacityRange.max="100"}catch(t){}this.opacityRange.value="100",this.opacityRange.className="vis-range",this.brightnessRange=document.createElement("input");try{this.brightnessRange.type="range",this.brightnessRange.min="0",this.brightnessRange.max="100"}catch(t){}this.brightnessRange.value="100",this.brightnessRange.className="vis-range",this.opacityDiv.appendChild(this.opacityRange),this.brightnessDiv.appendChild(this.brightnessRange);var i=this;this.opacityRange.onchange=function(){i._setOpacity(this.value)},this.opacityRange.oninput=function(){i._setOpacity(this.value)},this.brightnessRange.onchange=function(){i._setBrightness(this.value)},this.brightnessRange.oninput=function(){i._setBrightness(this.value)},this.brightnessLabel=document.createElement("div"),this.brightnessLabel.className="vis-label vis-brightness",this.brightnessLabel.innerHTML="brightness:",this.opacityLabel=document.createElement("div"),this.opacityLabel.className="vis-label vis-opacity",this.opacityLabel.innerHTML="opacity:",this.newColorDiv=document.createElement("div"),this.newColorDiv.className="vis-new-color",this.newColorDiv.innerHTML="new",this.initialColorDiv=document.createElement("div"),this.initialColorDiv.className="vis-initial-color",this.initialColorDiv.innerHTML="initial",this.cancelButton=document.createElement("div"),this.cancelButton.className="vis-button vis-cancel",this.cancelButton.innerHTML="cancel",this.cancelButton.onclick=this._hide.bind(this,!1),this.applyButton=document.createElement("div"),this.applyButton.className="vis-button vis-apply",this.applyButton.innerHTML="apply",this.applyButton.onclick=this._apply.bind(this),this.saveButton=document.createElement("div"),this.saveButton.className="vis-button vis-save",this.saveButton.innerHTML="save",this.saveButton.onclick=this._save.bind(this),this.loadButton=document.createElement("div"),this.loadButton.className="vis-button vis-load",this.loadButton.innerHTML="load last",this.loadButton.onclick=this._loadLast.bind(this),this.frame.appendChild(this.colorPickerDiv),this.frame.appendChild(this.arrowDiv),this.frame.appendChild(this.brightnessLabel),this.frame.appendChild(this.brightnessDiv),this.frame.appendChild(this.opacityLabel),this.frame.appendChild(this.opacityDiv),this.frame.appendChild(this.newColorDiv),this.frame.appendChild(this.initialColorDiv),this.frame.appendChild(this.cancelButton),this.frame.appendChild(this.applyButton),this.frame.appendChild(this.saveButton),this.frame.appendChild(this.loadButton)}},{key:"_bindHammer",value:function(){var t=this;this.drag={},this.pinch={},this.hammer=new l(this.colorPickerCanvas),this.hammer.get("pinch").set({enable:!0}),u.onTouch(this.hammer,function(e){t._moveSelector(e)}),this.hammer.on("tap",function(e){t._moveSelector(e)}),this.hammer.on("panstart",function(e){t._moveSelector(e)}),this.hammer.on("panmove",function(e){t._moveSelector(e)}),this.hammer.on("panend",function(e){t._moveSelector(e)})}},{key:"_generateHueCircle",value:function(){if(!1===this.generated){var t=this.colorPickerCanvas.getContext("2d");void 0===this.pixelRation&&(this.pixelRatio=(window.devicePixelRatio||1)/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)),t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0);var e=this.colorPickerCanvas.clientWidth,i=this.colorPickerCanvas.clientHeight;t.clearRect(0,0,e,i);var o=void 0,n=void 0,s=void 0,r=void 0;this.centerCoordinates={x:.5*e,y:.5*i},this.r=.49*e;var a=2*Math.PI/360,h=1/this.r,d=void 0;for(s=0;s<360;s++)for(r=0;rr?r:t,e=null==e?r:e0&&l.push(u.screenToValue(n)),!p.hidden&&this.itemsData.length>0&&l.push(p.screenToValue(n)),{event:t,what:d,pageX:t.srcEvent?t.srcEvent.pageX:t.pageX,pageY:t.srcEvent?t.srcEvent.pageY:t.pageY,x:o,y:n,time:r,value:l}},o.prototype._createConfigurator=function(){return new g(this,this.dom.container,v)},t.exports=o},function(t,e,i){e.util=i(2),e.DOMutil=i(14),e.DataSet=i(11),e.DataView=i(12),e.Queue=i(43),e.Network=i(182),e.network={Images:i(116),dotparser:i(114),gephiParser:i(115),allOptions:i(122)},e.network.convertDot=function(t){return e.network.dotparser.DOTToGraph(t)},e.network.convertGephi=function(t,i){return e.network.gephiParser.parseGephi(t,i)},e.moment=i(9),e.Hammer=i(10),e.keycharm=i(35)},function(t,e,i){function o(t,e,i){var n=this;if(!(this instanceof o))throw new SyntaxError("Constructor must be called with the new operator");this.options={},this.defaultOptions={locale:"en",locales:d,clickToUse:!1},s.extend(this.options,this.defaultOptions),this.body={container:t,nodes:{},nodeIndices:[],edges:{},edgeIndices:[],emitter:{on:this.on.bind(this),off:this.off.bind(this),emit:this.emit.bind(this),once:this.once.bind(this)},eventListeners:{onTap:function(){},onTouch:function(){},onDoubleTap:function(){},onHold:function(){},onDragStart:function(){},onDrag:function(){},onDragEnd:function(){},onMouseWheel:function(){},onPinch:function(){},onMouseMove:function(){},onRelease:function(){},onContext:function(){}},data:{nodes:null,edges:null},functions:{createNode:function(){},createEdge:function(){},getPointer:function(){}},modules:{},view:{scale:1,translation:{x:0,y:0}}},this.bindEventListeners(),this.images=new l(function(){return n.body.emitter.emit("_requestRedraw")}),this.groups=new u,this.canvas=new g(this.body),this.selectionHandler=new _(this.body,this.canvas),this.interactionHandler=new b(this.body,this.canvas,this.selectionHandler),this.view=new y(this.body,this.canvas),this.renderer=new v(this.body,this.canvas),this.physics=new f(this.body),this.layoutEngine=new w(this.body),this.clustering=new m(this.body),this.manipulation=new x(this.body,this.canvas,this.selectionHandler),this.nodesHandler=new c(this.body,this.images,this.groups,this.layoutEngine),this.edgesHandler=new p(this.body,this.images,this.groups),this.body.modules.kamadaKawai=new T(this.body,150,.05),this.body.modules.clustering=this.clustering,this.canvas._create(),this.setOptions(i),this.setData(e)}i(183);var n=i(44),s=i(2),r=i(114),a=i(115),h=i(97),d=i(184),l=i(116).default,u=i(186).default,c=i(187).default,p=i(214).default,f=i(220).default,m=i(227).default,v=i(229).default,g=i(230).default,y=i(231).default,b=i(232).default,_=i(234).default,w=i(235).default,x=i(237).default,k=i(71).default,S=i(15).default,D=i(15),M=D.printStyle,C=i(122),O=C.allOptions,E=C.configureOptions,T=i(238).default;n(o.prototype),o.prototype.setOptions=function(t){var e=this;if(void 0!==t){!0===S.validate(t,O)&&console.log("%cErrors have been found in the supplied options object.",M);var i=["locale","locales","clickToUse"];if(s.selectiveDeepExtend(i,this.options,t),t=this.layoutEngine.setOptions(t.layout,t),this.canvas.setOptions(t),this.groups.setOptions(t.groups),this.nodesHandler.setOptions(t.nodes),this.edgesHandler.setOptions(t.edges),this.physics.setOptions(t.physics),this.manipulation.setOptions(t.manipulation,t,this.options),this.interactionHandler.setOptions(t.interaction),this.renderer.setOptions(t.interaction),this.selectionHandler.setOptions(t.interaction),void 0!==t.groups&&this.body.emitter.emit("refreshNodes"),"configure"in t&&(this.configurator||(this.configurator=new k(this,this.body.container,E,this.canvas.pixelRatio)),this.configurator.setOptions(t.configure)),this.configurator&&!0===this.configurator.options.enabled){var o={nodes:{},edges:{},layout:{},interaction:{},manipulation:{},physics:{},global:{}};s.deepExtend(o.nodes,this.nodesHandler.options),s.deepExtend(o.edges,this.edgesHandler.options),s.deepExtend(o.layout,this.layoutEngine.options),s.deepExtend(o.interaction,this.selectionHandler.options),s.deepExtend(o.interaction,this.renderer.options),s.deepExtend(o.interaction,this.interactionHandler.options),s.deepExtend(o.manipulation,this.manipulation.options),s.deepExtend(o.physics,this.physics.options),s.deepExtend(o.global,this.canvas.options),s.deepExtend(o.global,this.options),this.configurator.setModuleOptions(o)}void 0!==t.clickToUse?!0===t.clickToUse?void 0===this.activator&&(this.activator=new h(this.canvas.frame),this.activator.on("change",function(){e.body.emitter.emit("activate")})):(void 0!==this.activator&&(this.activator.destroy(),delete this.activator),this.body.emitter.emit("activate")):this.body.emitter.emit("activate"),this.canvas.setSize(),this.body.emitter.emit("startSimulation")}},o.prototype._updateVisibleIndices=function(){var t=this.body.nodes,e=this.body.edges;this.body.nodeIndices=[],this.body.edgeIndices=[];for(var i in t)t.hasOwnProperty(i)&&(this.clustering._isClusteredNode(i)||!1!==t[i].options.hidden||this.body.nodeIndices.push(t[i].id));for(var o in e)if(e.hasOwnProperty(o)){var n=e[o],s=t[n.fromId],r=t[n.toId],a=void 0!==s&&void 0!==r,h=!this.clustering._isClusteredEdge(o)&&!1===n.options.hidden&&a&&!1===s.options.hidden&&!1===r.options.hidden;h&&this.body.edgeIndices.push(n.id)}},o.prototype.bindEventListeners=function(){var t=this;this.body.emitter.on("_dataChanged",function(){t.edgesHandler._updateState(),t.body.emitter.emit("_dataUpdated")}),this.body.emitter.on("_dataUpdated",function(){t.clustering._updateState(),t._updateVisibleIndices(),t._updateValueRange(t.body.nodes),t._updateValueRange(t.body.edges),t.body.emitter.emit("startSimulation"),t.body.emitter.emit("_requestRedraw")})},o.prototype.setData=function(t){if(this.body.emitter.emit("resetPhysics"),this.body.emitter.emit("_resetData"),this.selectionHandler.unselectAll(),t&&t.dot&&(t.nodes||t.edges))throw new SyntaxError('Data must contain either parameter "dot" or parameter pair "nodes" and "edges", but not both.');if(this.setOptions(t&&t.options),t&&t.dot){console.log("The dot property has been deprecated. Please use the static convertDot method to convert DOT into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertDot(dotString);");var e=r.DOTToGraph(t.dot);return void this.setData(e)}if(t&&t.gephi){console.log("The gephi property has been deprecated. Please use the static convertGephi method to convert gephi into vis.network format and use the normal data format with nodes and edges. This converter is used like this: var data = vis.network.convertGephi(gephiJson);");var i=a.parseGephi(t.gephi);return void this.setData(i)}this.nodesHandler.setData(t&&t.nodes,!0),this.edgesHandler.setData(t&&t.edges,!0),this.body.emitter.emit("_dataChanged"),this.body.emitter.emit("_dataLoaded"),this.body.emitter.emit("initPhysics")},o.prototype.destroy=function(){this.body.emitter.emit("destroy"),this.body.emitter.off(),this.off(),delete this.groups,delete this.canvas,delete this.selectionHandler,delete this.interactionHandler,delete this.view,delete this.renderer,delete this.physics,delete this.layoutEngine,delete this.clustering,delete this.manipulation,delete this.nodesHandler,delete this.edgesHandler,delete this.configurator,delete this.images;for(var t in this.body.nodes)this.body.nodes.hasOwnProperty(t)&&delete this.body.nodes[t];for(var e in this.body.edges)this.body.edges.hasOwnProperty(e)&&delete this.body.edges[e];s.recursiveDOMDelete(this.body.container)},o.prototype._updateValueRange=function(t){var e,i=void 0,o=void 0,n=0;for(e in t)if(t.hasOwnProperty(e)){var s=t[e].getValue();void 0!==s&&(i=void 0===i?s:Math.min(s,i),o=void 0===o?s:Math.max(s,o),n+=s)}if(void 0!==i&&void 0!==o)for(e in t)t.hasOwnProperty(e)&&t[e].setValueRange(i,o,n)},o.prototype.isActive=function(){return!this.activator||this.activator.active},o.prototype.setSize=function(){return this.canvas.setSize.apply(this.canvas,arguments)},o.prototype.canvasToDOM=function(){return this.canvas.canvasToDOM.apply(this.canvas,arguments)},o.prototype.DOMtoCanvas=function(){return this.canvas.DOMtoCanvas.apply(this.canvas,arguments)},o.prototype.findNode=function(){return this.clustering.findNode.apply(this.clustering,arguments)},o.prototype.isCluster=function(){return this.clustering.isCluster.apply(this.clustering,arguments)},o.prototype.openCluster=function(){return this.clustering.openCluster.apply(this.clustering,arguments)},o.prototype.cluster=function(){return this.clustering.cluster.apply(this.clustering,arguments)},o.prototype.getNodesInCluster=function(){return this.clustering.getNodesInCluster.apply(this.clustering,arguments)},o.prototype.clusterByConnection=function(){return this.clustering.clusterByConnection.apply(this.clustering,arguments)},o.prototype.clusterByHubsize=function(){return this.clustering.clusterByHubsize.apply(this.clustering,arguments)},o.prototype.clusterOutliers=function(){return this.clustering.clusterOutliers.apply(this.clustering,arguments)},o.prototype.getSeed=function(){return this.layoutEngine.getSeed.apply(this.layoutEngine,arguments)},o.prototype.enableEditMode=function(){return this.manipulation.enableEditMode.apply(this.manipulation,arguments)},o.prototype.disableEditMode=function(){return this.manipulation.disableEditMode.apply(this.manipulation,arguments)},o.prototype.addNodeMode=function(){return this.manipulation.addNodeMode.apply(this.manipulation,arguments)},o.prototype.editNode=function(){return this.manipulation.editNode.apply(this.manipulation,arguments)},o.prototype.editNodeMode=function(){return console.log("Deprecated: Please use editNode instead of editNodeMode."),this.manipulation.editNode.apply(this.manipulation,arguments)},o.prototype.addEdgeMode=function(){return this.manipulation.addEdgeMode.apply(this.manipulation,arguments)},o.prototype.editEdgeMode=function(){return this.manipulation.editEdgeMode.apply(this.manipulation,arguments)},o.prototype.deleteSelected=function(){return this.manipulation.deleteSelected.apply(this.manipulation,arguments)},o.prototype.getPositions=function(){return this.nodesHandler.getPositions.apply(this.nodesHandler,arguments)},o.prototype.storePositions=function(){return this.nodesHandler.storePositions.apply(this.nodesHandler,arguments)},o.prototype.moveNode=function(){return this.nodesHandler.moveNode.apply(this.nodesHandler,arguments)},o.prototype.getBoundingBox=function(){return this.nodesHandler.getBoundingBox.apply(this.nodesHandler,arguments)},o.prototype.getConnectedNodes=function(t){return void 0!==this.body.nodes[t]?this.nodesHandler.getConnectedNodes.apply(this.nodesHandler,arguments):this.edgesHandler.getConnectedNodes.apply(this.edgesHandler,arguments)},o.prototype.getConnectedEdges=function(){return this.nodesHandler.getConnectedEdges.apply(this.nodesHandler,arguments)},o.prototype.startSimulation=function(){return this.physics.startSimulation.apply(this.physics,arguments)},o.prototype.stopSimulation=function(){return this.physics.stopSimulation.apply(this.physics,arguments)},o.prototype.stabilize=function(){return this.physics.stabilize.apply(this.physics,arguments)},o.prototype.getSelection=function(){return this.selectionHandler.getSelection.apply(this.selectionHandler,arguments)},o.prototype.setSelection=function(){return this.selectionHandler.setSelection.apply(this.selectionHandler,arguments)},o.prototype.getSelectedNodes=function(){return this.selectionHandler.getSelectedNodes.apply(this.selectionHandler,arguments)},o.prototype.getSelectedEdges=function(){return this.selectionHandler.getSelectedEdges.apply(this.selectionHandler,arguments)},o.prototype.getNodeAt=function(){var t=this.selectionHandler.getNodeAt.apply(this.selectionHandler,arguments);return void 0!==t&&void 0!==t.id?t.id:t},o.prototype.getEdgeAt=function(){var t=this.selectionHandler.getEdgeAt.apply(this.selectionHandler,arguments);return void 0!==t&&void 0!==t.id?t.id:t},o.prototype.selectNodes=function(){return this.selectionHandler.selectNodes.apply(this.selectionHandler,arguments)},o.prototype.selectEdges=function(){return this.selectionHandler.selectEdges.apply(this.selectionHandler,arguments)},o.prototype.unselectAll=function(){this.selectionHandler.unselectAll.apply(this.selectionHandler,arguments),this.redraw()},o.prototype.redraw=function(){return this.renderer.redraw.apply(this.renderer,arguments)},o.prototype.getScale=function(){return this.view.getScale.apply(this.view,arguments)},o.prototype.getViewPosition=function(){return this.view.getViewPosition.apply(this.view,arguments)},o.prototype.fit=function(){return this.view.fit.apply(this.view,arguments)},o.prototype.moveTo=function(){return this.view.moveTo.apply(this.view,arguments)},o.prototype.focus=function(){return this.view.focus.apply(this.view,arguments)},o.prototype.releaseNode=function(){return this.view.releaseNode.apply(this.view,arguments)},o.prototype.getOptionsFromConfigurator=function(){var t={};return this.configurator&&(t=this.configurator.getOptions.apply(this.configurator)),t},t.exports=o},function(t,e,i){"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.circle=function(t,e,i){this.beginPath(),this.arc(t,e,i,0,2*Math.PI,!1),this.closePath()},CanvasRenderingContext2D.prototype.square=function(t,e,i){this.beginPath(),this.rect(t-i,e-i,2*i,2*i),this.closePath()},CanvasRenderingContext2D.prototype.triangle=function(t,e,i){this.beginPath(),i*=1.15,e+=.275*i;var o=2*i,n=o/2,s=Math.sqrt(3)/6*o,r=Math.sqrt(o*o-n*n);this.moveTo(t,e-(r-s)),this.lineTo(t+n,e+s),this.lineTo(t-n,e+s),this.lineTo(t,e-(r-s)),this.closePath()},CanvasRenderingContext2D.prototype.triangleDown=function(t,e,i){this.beginPath(),i*=1.15,e-=.275*i;var o=2*i,n=o/2,s=Math.sqrt(3)/6*o,r=Math.sqrt(o*o-n*n);this.moveTo(t,e+(r-s)),this.lineTo(t+n,e-s),this.lineTo(t-n,e-s),this.lineTo(t,e+(r-s)),this.closePath()},CanvasRenderingContext2D.prototype.star=function(t,e,i){this.beginPath(),i*=.82,e+=.1*i;for(var o=0;o<10;o++){var n=o%2==0?1.3*i:.5*i;this.lineTo(t+n*Math.sin(2*o*Math.PI/10),e-n*Math.cos(2*o*Math.PI/10))}this.closePath()},CanvasRenderingContext2D.prototype.diamond=function(t,e,i){this.beginPath(),this.lineTo(t,e+i),this.lineTo(t+i,e),this.lineTo(t,e-i),this.lineTo(t-i,e),this.closePath()},CanvasRenderingContext2D.prototype.roundRect=function(t,e,i,o,n){var s=Math.PI/180;i-2*n<0&&(n=i/2),o-2*n<0&&(n=o/2),this.beginPath(),this.moveTo(t+n,e),this.lineTo(t+i-n,e),this.arc(t+i-n,e+n,n,270*s,360*s,!1),this.lineTo(t+i,e+o-n),this.arc(t+i-n,e+o-n,n,0,90*s,!1),this.lineTo(t+n,e+o),this.arc(t+n,e+o-n,n,90*s,180*s,!1),this.lineTo(t,e+n),this.arc(t+n,e+n,n,180*s,270*s,!1),this.closePath()},CanvasRenderingContext2D.prototype.ellipse_vis=function(t,e,i,o){var n=i/2*.5522848,s=o/2*.5522848,r=t+i,a=e+o,h=t+i/2,d=e+o/2;this.beginPath(),this.moveTo(t,d),this.bezierCurveTo(t,d-s,h-n,e,h,e),this.bezierCurveTo(h+n,e,r,d-s,r,d),this.bezierCurveTo(r,d+s,h+n,a,h,a),this.bezierCurveTo(h-n,a,t,d+s,t,d),this.closePath()},CanvasRenderingContext2D.prototype.database=function(t,e,i,o){var n=i,s=o*(1/3),r=n/2*.5522848,a=s/2*.5522848,h=t+n,d=e+s,l=t+n/2,u=e+s/2,c=e+(o-s/2),p=e+o;this.beginPath(),this.moveTo(h,u),this.bezierCurveTo(h,u+a,l+r,d,l,d),this.bezierCurveTo(l-r,d,t,u+a,t,u),this.bezierCurveTo(t,u-a,l-r,e,l,e),this.bezierCurveTo(l+r,e,h,u-a,h,u),this.lineTo(h,c),this.bezierCurveTo(h,c+a,l+r,p,l,p),this.bezierCurveTo(l-r,p,t,c+a,t,c),this.lineTo(t,u)},CanvasRenderingContext2D.prototype.dashedLine=function(t,e,i,o,n){this.beginPath(),this.moveTo(t,e);for(var s=n.length,r=i-t,a=o-e,h=a/r,d=Math.sqrt(r*r+a*a),l=0,u=!0,c=0,p=n[0];d>=.1;)p=n[l++%s],p>d&&(p=d),c=Math.sqrt(p*p/(1+h*h)),c=r<0?-c:c,t+=c,e+=h*c,!0===u?this.lineTo(t,e):this.moveTo(t,e),d-=p,u=!u},CanvasRenderingContext2D.prototype.hexagon=function(t,e,i){this.beginPath();var o=2*Math.PI/6;this.moveTo(t+i,e);for(var n=1;n<6;n++)this.lineTo(t+i*Math.cos(o*n),e+i*Math.sin(o*n));this.closePath()})},function(t,e,i){e.en={edit:"Edit",del:"Delete selected",back:"Back",addNode:"Add Node",addEdge:"Add Edge",editNode:"Edit Node",editEdge:"Edit Edge",addDescription:"Click in an empty space to place a new node.",edgeDescription:"Click on a node and drag the edge to another node to connect them.",editEdgeDescription:"Click on the control points and drag them to a node to connect to it.",createEdgeError:"Cannot link edges to a cluster.",deleteClusterError:"Clusters cannot be deleted.",editClusterError:"Clusters cannot be edited."},e.en_EN=e.en,e.en_US=e.en,e.de={edit:"Editieren",del:"Lösche Auswahl",back:"Zurück",addNode:"Knoten hinzufügen",addEdge:"Kante hinzufügen",editNode:"Knoten editieren",editEdge:"Kante editieren",addDescription:"Klicke auf eine freie Stelle, um einen neuen Knoten zu plazieren.",edgeDescription:"Klicke auf einen Knoten und ziehe die Kante zu einem anderen Knoten, um diese zu verbinden.",editEdgeDescription:"Klicke auf die Verbindungspunkte und ziehe diese auf einen Knoten, um sie zu verbinden.",createEdgeError:"Es ist nicht möglich, Kanten mit Clustern zu verbinden.",deleteClusterError:"Cluster können nicht gelöscht werden.",editClusterError:"Cluster können nicht editiert werden."},e.de_DE=e.de,e.es={edit:"Editar",del:"Eliminar selección",back:"Átras",addNode:"Añadir nodo",addEdge:"Añadir arista",editNode:"Editar nodo",editEdge:"Editar arista",addDescription:"Haga clic en un lugar vacío para colocar un nuevo nodo.",edgeDescription:"Haga clic en un nodo y arrastre la arista hacia otro nodo para conectarlos.",editEdgeDescription:"Haga clic en un punto de control y arrastrelo a un nodo para conectarlo.",createEdgeError:"No se puede conectar una arista a un grupo.",deleteClusterError:"No es posible eliminar grupos.",editClusterError:"No es posible editar grupos."},e.es_ES=e.es,e.it={edit:"Modifica",del:"Cancella la selezione",back:"Indietro",addNode:"Aggiungi un nodo",addEdge:"Aggiungi un vertice",editNode:"Modifica il nodo",editEdge:"Modifica il vertice",addDescription:"Clicca per aggiungere un nuovo nodo",edgeDescription:"Clicca su un nodo e trascinalo ad un altro nodo per connetterli.",editEdgeDescription:"Clicca sui Punti di controllo e trascinali ad un nodo per connetterli.",createEdgeError:"Non si possono collegare vertici ad un cluster",deleteClusterError:"I cluster non possono essere cancellati",editClusterError:"I clusters non possono essere modificati."},e.it_IT=e.it,e.nl={edit:"Wijzigen",del:"Selectie verwijderen",back:"Terug",addNode:"Node toevoegen",addEdge:"Link toevoegen",editNode:"Node wijzigen",editEdge:"Link wijzigen",addDescription:"Klik op een leeg gebied om een nieuwe node te maken.",edgeDescription:"Klik op een node en sleep de link naar een andere node om ze te verbinden.",editEdgeDescription:"Klik op de verbindingspunten en sleep ze naar een node om daarmee te verbinden.",createEdgeError:"Kan geen link maken naar een cluster.",deleteClusterError:"Clusters kunnen niet worden verwijderd.",editClusterError:"Clusters kunnen niet worden aangepast."},e.nl_NL=e.nl,e.nl_BE=e.nl,e["pt-br"]={edit:"Editar",del:"Remover selecionado",back:"Voltar",addNode:"Adicionar nó",addEdge:"Adicionar aresta",editNode:"Editar nó",editEdge:"Editar aresta",addDescription:"Clique em um espaço em branco para adicionar um novo nó",edgeDescription:"Clique em um nó e arraste a aresta até outro nó para conectá-los",editEdgeDescription:"Clique nos pontos de controle e os arraste para um nó para conectá-los",createEdgeError:"Não foi possível linkar arestas a um cluster.",deleteClusterError:"Clusters não puderam ser removidos.",editClusterError:"Clusters não puderam ser editados."},e["pt-BR"]=e["pt-br"],e.pt_BR=e["pt-br"],e.pt_br=e["pt-br"],e.ru={edit:"Редактировать",del:"Удалить выбранное",back:"Назад",addNode:"Добавить узел",addEdge:"Добавить ребро",editNode:"Редактировать узел",editEdge:"Редактировать ребро",addDescription:"Кликните в свободное место, чтобы добавить новый узел.",edgeDescription:"Кликните на узел и протяните ребро к другому узлу, чтобы соединить их.",editEdgeDescription:"Кликните на контрольные точки и перетащите их в узел, чтобы подключиться к нему.",createEdgeError:"Невозможно соединить ребра в кластер.",deleteClusterError:"Кластеры не могут быть удалены",editClusterError:"Кластеры недоступны для редактирования."},e.ru_RU=e.ru,e.cn={edit:"编辑",del:"删除选定",back:"返回",addNode:"添加节点",addEdge:"添加连接线",editNode:"编辑节点",editEdge:"编辑连接线",addDescription:"单击空白处放置新节点。",edgeDescription:"单击某个节点并将该连接线拖动到另一个节点以连接它们。",editEdgeDescription:"单击控制节点并将它们拖到节点上连接。",createEdgeError:"无法将连接线连接到群集。",deleteClusterError:"无法删除群集。",editClusterError:"无法编辑群集。"},e.zh_CN=e.cn},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=function(){function t(){(0,s.default)(this,t),this.NUM_ITERATIONS=4,this.image=new Image,this.canvas=document.createElement("canvas")}return(0,a.default)(t,[{key:"init",value:function(){if(!this.initialized()){this.src=this.image.src;var t=this.image.width,e=this.image.height;this.width=t,this.height=e;var i=Math.floor(e/2),o=Math.floor(e/4),n=Math.floor(e/8),s=Math.floor(e/16),r=Math.floor(t/2),a=Math.floor(t/4),h=Math.floor(t/8),d=Math.floor(t/16);this.canvas.width=3*a,this.canvas.height=i,this.coordinates=[[0,0,r,i],[r,0,a,o],[r,o,h,n],[5*h,o,d,s]],this._fillMipMap()}}},{key:"initialized",value:function(){return void 0!==this.coordinates}},{key:"_fillMipMap",value:function(){var t=this.canvas.getContext("2d"),e=this.coordinates[0];t.drawImage(this.image,e[0],e[1],e[2],e[3]);for(var i=1;i2){e*=.5;for(var r=0;e>2&&r=this.NUM_ITERATIONS&&(r=this.NUM_ITERATIONS-1);var a=this.coordinates[r];t.drawImage(this.canvas,a[0],a[1],a[2],a[3],i,o,n,s)}else t.drawImage(this.image,i,o,n,s)}}]),t}();e.default=h},function(t,e,i){ +function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=i(2),d=function(){function t(){(0,s.default)(this,t),this.clear(),this.defaultIndex=0,this.groupsArray=[],this.groupIndex=0,this.defaultGroups=[{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},{border:"#FFA500",background:"#FFFF00",highlight:{border:"#FFA500",background:"#FFFFA3"},hover:{border:"#FFA500",background:"#FFFFA3"}},{border:"#FA0A10",background:"#FB7E81",highlight:{border:"#FA0A10",background:"#FFAFB1"},hover:{border:"#FA0A10",background:"#FFAFB1"}},{border:"#41A906",background:"#7BE141",highlight:{border:"#41A906",background:"#A1EC76"},hover:{border:"#41A906",background:"#A1EC76"}},{border:"#E129F0",background:"#EB7DF4",highlight:{border:"#E129F0",background:"#F0B3F5"},hover:{border:"#E129F0",background:"#F0B3F5"}},{border:"#7C29F0",background:"#AD85E4",highlight:{border:"#7C29F0",background:"#D3BDF0"},hover:{border:"#7C29F0",background:"#D3BDF0"}},{border:"#C37F00",background:"#FFA807",highlight:{border:"#C37F00",background:"#FFCA66"},hover:{border:"#C37F00",background:"#FFCA66"}},{border:"#4220FB",background:"#6E6EFD",highlight:{border:"#4220FB",background:"#9B9BFD"},hover:{border:"#4220FB",background:"#9B9BFD"}},{border:"#FD5A77",background:"#FFC0CB",highlight:{border:"#FD5A77",background:"#FFD1D9"},hover:{border:"#FD5A77",background:"#FFD1D9"}},{border:"#4AD63A",background:"#C2FABC",highlight:{border:"#4AD63A",background:"#E6FFE3"},hover:{border:"#4AD63A",background:"#E6FFE3"}},{border:"#990000",background:"#EE0000",highlight:{border:"#BB0000",background:"#FF3333"},hover:{border:"#BB0000",background:"#FF3333"}},{border:"#FF6000",background:"#FF6000",highlight:{border:"#FF6000",background:"#FF6000"},hover:{border:"#FF6000",background:"#FF6000"}},{border:"#97C2FC",background:"#2B7CE9",highlight:{border:"#D2E5FF",background:"#2B7CE9"},hover:{border:"#D2E5FF",background:"#2B7CE9"}},{border:"#399605",background:"#255C03",highlight:{border:"#399605",background:"#255C03"},hover:{border:"#399605",background:"#255C03"}},{border:"#B70054",background:"#FF007E",highlight:{border:"#B70054",background:"#FF007E"},hover:{border:"#B70054",background:"#FF007E"}},{border:"#AD85E4",background:"#7C29F0",highlight:{border:"#D3BDF0",background:"#7C29F0"},hover:{border:"#D3BDF0",background:"#7C29F0"}},{border:"#4557FA",background:"#000EA1",highlight:{border:"#6E6EFD",background:"#000EA1"},hover:{border:"#6E6EFD",background:"#000EA1"}},{border:"#FFC0CB",background:"#FD5A77",highlight:{border:"#FFD1D9",background:"#FD5A77"},hover:{border:"#FFD1D9",background:"#FD5A77"}},{border:"#C2FABC",background:"#74D66A",highlight:{border:"#E6FFE3",background:"#74D66A"},hover:{border:"#E6FFE3",background:"#74D66A"}},{border:"#EE0000",background:"#990000",highlight:{border:"#FF3333",background:"#BB0000"},hover:{border:"#FF3333",background:"#BB0000"}}],this.options={},this.defaultOptions={useDefaultGroups:!0},h.extend(this.options,this.defaultOptions)}return(0,a.default)(t,[{key:"setOptions",value:function(t){var e=["useDefaultGroups"];if(void 0!==t)for(var i in t)if(t.hasOwnProperty(i)&&-1===e.indexOf(i)){var o=t[i];this.add(i,o)}}},{key:"clear",value:function(){this.groups={},this.groupsArray=[]}},{key:"get",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this.groups[t];if(void 0===i&&e)if(!1===this.options.useDefaultGroups&&this.groupsArray.length>0){var o=this.groupIndex%this.groupsArray.length;this.groupIndex++,i={},i.color=this.groups[this.groupsArray[o]],this.groups[t]=i}else{var n=this.defaultIndex%this.defaultGroups.length;this.defaultIndex++,i={},i.color=this.defaultGroups[n],this.groups[t]=i}return i}},{key:"add",value:function(t,e){return this.groups[t]=e,this.groupsArray.push(t),e}}]),t}();e.default=d},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=i(2),d=i(11),l=i(12),u=i(47).default,c=function(){function t(e,i,o,n){var r=this;if((0,s.default)(this,t),this.body=e,this.images=i,this.groups=o,this.layoutEngine=n,this.body.functions.createNode=this.create.bind(this),this.nodesListeners={add:function(t,e){r.add(e.items)},update:function(t,e){r.update(e.items,e.data,e.oldData)},remove:function(t,e){r.remove(e.items)}},this.defaultOptions={borderWidth:1,borderWidthSelected:2,brokenImage:void 0,color:{border:"#2B7CE9",background:"#97C2FC",highlight:{border:"#2B7CE9",background:"#D2E5FF"},hover:{border:"#2B7CE9",background:"#D2E5FF"}},fixed:{x:!1,y:!1},font:{color:"#343434",size:14,face:"arial",background:"none",strokeWidth:0,strokeColor:"#ffffff",align:"center",vadjust:0,multi:!1,bold:{mod:"bold"},boldital:{mod:"bold italic"},ital:{mod:"italic"},mono:{mod:"",size:15,face:"monospace",vadjust:2}},group:void 0,hidden:!1,icon:{face:"FontAwesome",code:void 0,size:50,color:"#2B7CE9"},image:void 0,label:void 0,labelHighlightBold:!0,level:void 0,margin:{top:5,right:5,bottom:5,left:5},mass:1,physics:!0,scaling:{min:10,max:30,label:{enabled:!1,min:14,max:30,maxVisible:30,drawThreshold:5},customScalingFunction:function(t,e,i,o){if(e===t)return.5;var n=1/(e-t);return Math.max(0,(o-t)*n)}},shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:10,x:5,y:5},shape:"ellipse",shapeProperties:{borderDashes:!1,borderRadius:6,interpolation:!0,useImageSize:!1,useBorderWithImage:!1},size:25,title:void 0,value:void 0,x:void 0,y:void 0},this.defaultOptions.mass<=0)throw"Internal error: mass in defaultOptions of NodesHandler may not be zero or negative";this.options=h.bridgeObject(this.defaultOptions),this.bindEventListeners()}return(0,a.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("refreshNodes",this.refresh.bind(this)),this.body.emitter.on("refresh",this.refresh.bind(this)),this.body.emitter.on("destroy",function(){h.forEach(t.nodesListeners,function(e,i){t.body.data.nodes&&t.body.data.nodes.off(i,e)}),delete t.body.functions.createNode,delete t.nodesListeners.add,delete t.nodesListeners.update,delete t.nodesListeners.remove,delete t.nodesListeners})}},{key:"setOptions",value:function(t){if(void 0!==t){if(u.parseOptions(this.options,t),void 0!==t.shape)for(var e in this.body.nodes)this.body.nodes.hasOwnProperty(e)&&this.body.nodes[e].updateShape();if(void 0!==t.font)for(var i in this.body.nodes)this.body.nodes.hasOwnProperty(i)&&(this.body.nodes[i].updateLabelModule(),this.body.nodes[i].needsRefresh());if(void 0!==t.size)for(var o in this.body.nodes)this.body.nodes.hasOwnProperty(o)&&this.body.nodes[o].needsRefresh();void 0===t.hidden&&void 0===t.physics||this.body.emitter.emit("_dataChanged")}}},{key:"setData",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.body.data.nodes;if(t instanceof d||t instanceof l)this.body.data.nodes=t;else if(Array.isArray(t))this.body.data.nodes=new d,this.body.data.nodes.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.nodes=new d}if(i&&h.forEach(this.nodesListeners,function(t,e){i.off(e,t)}),this.body.nodes={},this.body.data.nodes){var o=this;h.forEach(this.nodesListeners,function(t,e){o.body.data.nodes.on(e,t)});var n=this.body.data.nodes.getIds();this.add(n,!0)}!1===e&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=void 0,o=[],n=0;n1&&void 0!==arguments[1]?arguments[1]:u)(t,this.body,this.images,this.groups,this.options,this.defaultOptions)}},{key:"refresh",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];h.forEach(this.body.nodes,function(i,o){var n=t.body.data.nodes.get(o);void 0!==n&&(!0===e&&i.setOptions({x:null,y:null}),i.setOptions({fixed:!1}),i.setOptions(n))})}},{key:"getPositions",value:function(t){var e={};if(void 0!==t){if(!0===Array.isArray(t)){for(var i=0;i0)for(var r=0;r0)for(var p=0;p0&&void 0!==arguments[0]&&arguments[0];this.spacing&&(this.add(" "),this.spacing=!1),this.buffer.length>0&&(e.push({text:this.buffer,mod:this.modName()}),this.buffer="")},i.add=function(t){" "===t&&(i.spacing=!0),i.spacing&&(this.buffer+=" ",this.spacing=!1)," "!=t&&(this.buffer+=t)};i.position/.test(t.substr(i.position,3))?i.mono||i.ital||!//.test(t.substr(i.position,3))?!i.mono&&//.test(t.substr(i.position,6))?(i.emitBlock(),i.mono=!0,i.modStack.unshift("mono"),i.position+=5):!i.mono&&"bold"===i.mod()&&/<\/b>/.test(t.substr(i.position,4))?(i.emitBlock(),i.bold=!1,i.modStack.shift(),i.position+=3):!i.mono&&"ital"===i.mod()&&/<\/i>/.test(t.substr(i.position,4))?(i.emitBlock(),i.ital=!1,i.modStack.shift(),i.position+=3):"mono"===i.mod()&&/<\/code>/.test(t.substr(i.position,7))?(i.emitBlock(),i.mono=!1,i.modStack.shift(),i.position+=6):i.add(o):(i.emitBlock(),i.ital=!0,i.modStack.unshift("ital"),i.position+=2):(i.emitBlock(),i.bold=!0,i.modStack.unshift("bold"),i.position+=2):/&/.test(o)?/</.test(t.substr(i.position,4))?(i.add("<"),i.position+=3):/&/.test(t.substr(i.position,5))?(i.add("&"),i.position+=4):i.add("&"):i.add(o),i.position++}return i.emitBlock(),e}},{key:"splitMarkdownBlocks",value:function(t){var e=[],i={bold:!1,ital:!1,mono:!1,beginable:!0,spacing:!1,position:0,buffer:"",modStack:[]};for(i.mod=function(){return 0===this.modStack.length?"normal":this.modStack[0]},i.modName=function(){return 0===this.modStack.length?"normal":"mono"===this.modStack[0]?"mono":i.bold&&i.ital?"boldital":i.bold?"bold":i.ital?"ital":void 0},i.emitBlock=function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.spacing&&(this.add(" "),this.spacing=!1),this.buffer.length>0&&(e.push({text:this.buffer,mod:this.modName()}),this.buffer="")},i.add=function(t){" "===t&&(i.spacing=!0),i.spacing&&(this.buffer+=" ",this.spacing=!1)," "!=t&&(this.buffer+=t)};i.positionthis.parent.fontOptions.maxWdt}},{key:"getLongestFit",value:function(t){for(var e="",i=0;i1&&void 0!==arguments[1]?arguments[1]:"normal",i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];t=t.replace(/^( +)/g,"$1\r"),t=t.replace(/([^\r][^ ]*)( +)/g,"$1\r$2\r");for(var o=t.split("\r");o.length>0;){var n=this.getLongestFit(o);if(0===n){var s=o[0],r=this.getLongestFitWord(s);this.lines.newLine(s.slice(0,r),e),o[0]=s.slice(r)}else{var a=n;" "===o[n-1]?n--:" "===o[a]&&a++;var h=o.slice(0,n).join("");n==o.length&&i?this.lines.append(h,e):this.lines.newLine(h,e),o=o.slice(a)}}}}]),t}();e.default=l},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(90),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=function(){function t(e){(0,a.default)(this,t),this.measureText=e,this.current=0,this.width=0,this.height=0,this.lines=[]}return(0,d.default)(t,[{key:"_add",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"normal";void 0===this.lines[t]&&(this.lines[t]={width:0,height:0,blocks:[]});var o=e;void 0!==e&&""!==e||(o=" ");var n=this.measureText(o,i),r=(0,s.default)({},n.values);r.text=e,r.width=n.width,r.mod=i,void 0!==e&&""!==e||(r.width=0),this.lines[t].blocks.push(r),this.lines[t].width+=r.width}},{key:"curWidth",value:function(){var t=this.lines[this.current];return void 0===t?0:t.width}},{key:"append",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e)}},{key:"newLine",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"normal";this._add(this.current,t,e),this.current++}},{key:"determineLineHeights",value:function(){for(var t=0;tt&&(t=o.width),e+=o.height}this.width=t,this.height=e}},{key:"removeEmptyBlocks",value:function(){for(var t=[],e=0;e1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var o=this.getDimensionsFromLabel(t,e,i);this.width=o.width+this.margin.right+this.margin.left,this.height=o.height+this.margin.top+this.margin.bottom,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,o,n,s){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this.initContextForDraw(t,s),t.roundRect(this.left,this.top,this.width,this.height,s.borderRadius),this.performFill(t,s),this.updateBoundingBox(e,i,t,o,n),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n)}},{key:"updateBoundingBox",value:function(t,e,i,o,n){this._updateBoundingBox(t,e,i,o,n);var s=this.options.shapeProperties.borderRadius;this._addBoundingBoxMargin(s)}},{key:"distanceToBorder",value:function(t,e){this.resize(t);var i=this.options.borderWidth;return Math.min(Math.abs(this.width/2/Math.cos(e)),Math.abs(this.height/2/Math.sin(e)))+i}}]),e}(m.default);e.default=v},function(t,e,i){i(195),t.exports=i(7).Object.getPrototypeOf},function(t,e,i){var o=i(41),n=i(85);i(87)("getPrototypeOf",function(){return function(t){return n(o(t))}})},function(t,e,i){t.exports={default:i(197),__esModule:!0}},function(t,e,i){i(198),t.exports=i(7).Object.setPrototypeOf},function(t,e,i){var o=i(17);o(o.S,"Object",{setPrototypeOf:i(199).set})},function(t,e,i){var o=i(32),n=i(27),s=function(t,e){if(n(t),!o(e)&&null!==e)throw TypeError(e+": can't set as prototype!")};t.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(t,e,o){try{o=i(80)(Function.call,i(89).f(Object.prototype,"__proto__").set,2),o(t,[]),e=!(t instanceof Array)}catch(t){e=!0}return function(t,i){return s(t,i),e?t.__proto__=i:o(t,i),t}}({},!1):void 0),check:s}},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(73),m=o(f),v=function(t){function e(t,i,o){(0,a.default)(this,e);var n=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return n._setMargins(o),n}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var o=this.getDimensionsFromLabel(t,e,i),n=Math.max(o.width+this.margin.right+this.margin.left,o.height+this.margin.top+this.margin.bottom);this.options.size=n/2,this.width=n,this.height=n,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,o,n,s){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this._drawRawCircle(t,e,i,s),this.updateBoundingBox(e,i),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,i,o,n)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size}},{key:"distanceToBorder",value:function(t,e){return this.resize(t),.5*this.width}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(73),m=o(f),v=function(t){function e(t,i,o,n,r){(0,a.default)(this,e);var h=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return h.setImages(n,r),h}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var o=2*this.options.size;return this.width=o,this.height=o,void(this.radius=.5*this.width)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,o,n,s){this.switchImages(o),this.resize(),this.left=e-this.width/2,this.top=i-this.height/2,this._drawRawCircle(t,e,i,s),t.save(),t.clip(),this._drawImageAtPosition(t,s),t.restore(),this._drawImageLabel(t,e,i,o,n),this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){this.boundingBox.top=e-this.options.size,this.boundingBox.left=t-this.options.size,this.boundingBox.right=t+this.options.size,this.boundingBox.bottom=e+this.options.size,this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset)}},{key:"distanceToBorder",value:function(t,e){return this.resize(t),.5*this.width}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(23),m=o(f),v=function(t){function e(t,i,o){(0,a.default)(this,e);var n=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return n._setMargins(o),n}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t,e,i){if(this.needsRefresh(e,i)){var o=this.getDimensionsFromLabel(t,e,i),n=o.width+this.margin.right+this.margin.left;this.width=n,this.height=n,this.radius=this.width/2}}},{key:"draw",value:function(t,e,i,o,n,s){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this.initContextForDraw(t,s),t.database(e-this.width/2,i-this.height/2,this.width,this.height),this.performFill(t,s),this.updateBoundingBox(e,i,t,o,n),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(24),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"diamond",4,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(24),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"circle",2,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this.resize(t),this.options.size}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(23),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(this.needsRefresh(e,i)){var o=this.getDimensionsFromLabel(t,e,i);this.height=2*o.height,this.width=o.width+o.height,this.radius=.5*this.width}}},{key:"draw",value:function(t,e,i,o,n,s){this.resize(t,o,n),this.left=e-.5*this.width,this.top=i-.5*this.height,this.initContextForDraw(t,s),t.ellipse_vis(this.left,this.top,this.width,this.height),this.performFill(t,s),this.updateBoundingBox(e,i,t,o,n),this.labelModule.draw(t,e,i,o,n)}},{key:"distanceToBorder",value:function(t,e){this.resize(t);var i=.5*this.width,o=.5*this.height,n=Math.sin(e)*i,s=Math.cos(e)*o;return i*o/Math.sqrt(n*n+s*s)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(23),m=o(f),v=function(t){function e(t,i,o){(0,a.default)(this,e);var n=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return n._setMargins(o),n}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.iconSize={width:Number(this.options.icon.size),height:Number(this.options.icon.size)},this.width=this.iconSize.width+this.margin.right+this.margin.left,this.height=this.iconSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,o,n,s){if(this.resize(t,o,n),this.options.icon.size=this.options.icon.size||50,this.left=e-this.width/2,this.top=i-this.height/2,this._icon(t,e,i,o,n,s),void 0!==this.options.label){this.labelModule.draw(t,this.left+this.iconSize.width/2+this.margin.left,i+this.height/2+5,o)}this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){if(this.boundingBox.top=e-.5*this.options.icon.size,this.boundingBox.left=t-.5*this.options.icon.size,this.boundingBox.right=t+.5*this.options.icon.size,this.boundingBox.bottom=e+.5*this.options.icon.size,void 0!==this.options.label&&this.labelModule.size.width>0){this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelModule.size.height+5)}}},{key:"_icon",value:function(t,e,i,o,n,s){var r=Number(this.options.icon.size);void 0!==this.options.icon.code?(t.font=(o?"bold ":"")+r+"px "+this.options.icon.face,t.fillStyle=this.options.icon.color||"black",t.textAlign="center",t.textBaseline="middle",this.enableShadow(t,s),t.fillText(this.options.icon.code,e,i),this.disableShadow(t,s)):console.error("When using the icon shape, you need to define the code in the icon options object. This can be done per node or globally.")}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(73),m=o(f),v=function(t){function e(t,i,o,n,r){(0,a.default)(this,e);var h=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return h.setImages(n,r),h}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.selected,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.hover;if(void 0===this.imageObj.src||void 0===this.imageObj.width||void 0===this.imageObj.height){var o=2*this.options.size;return this.width=o,void(this.height=o)}this.needsRefresh(e,i)&&this._resizeImage()}},{key:"draw",value:function(t,e,i,o,n,s){if(this.switchImages(o),this.resize(),this.left=e-this.width/2,this.top=i-this.height/2,!0===this.options.shapeProperties.useBorderWithImage){var r=this.options.borderWidth,a=this.options.borderWidthSelected||2*this.options.borderWidth,h=(o?a:r)/this.body.view.scale;t.lineWidth=Math.min(this.width,h),t.beginPath(),t.strokeStyle=o?this.options.color.highlight.border:n?this.options.color.hover.border:this.options.color.border,t.fillStyle=o?this.options.color.highlight.background:n?this.options.color.hover.background:this.options.color.background,t.rect(this.left-.5*t.lineWidth,this.top-.5*t.lineWidth,this.width+t.lineWidth,this.height+t.lineWidth),t.fill(),this.performStroke(t,s),t.closePath()}this._drawImageAtPosition(t,s),this._drawImageLabel(t,e,i,o,n),this.updateBoundingBox(e,i)}},{key:"updateBoundingBox",value:function(t,e){this.resize(),this._updateBoundingBox(t,e),void 0!==this.options.label&&this.labelModule.size.width>0&&(this.boundingBox.left=Math.min(this.boundingBox.left,this.labelModule.size.left),this.boundingBox.right=Math.max(this.boundingBox.right,this.labelModule.size.left+this.labelModule.size.width),this.boundingBox.bottom=Math.max(this.boundingBox.bottom,this.boundingBox.bottom+this.labelOffset))}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)} +}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(24),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"square",2,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(24),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"hexagon",4,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(24),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"star",4,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(23),m=o(f),v=function(t){function e(t,i,o){(0,a.default)(this,e);var n=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o));return n._setMargins(o),n}return(0,p.default)(e,t),(0,d.default)(e,[{key:"resize",value:function(t,e,i){this.needsRefresh(e,i)&&(this.textSize=this.labelModule.getTextSize(t,e,i),this.width=this.textSize.width+this.margin.right+this.margin.left,this.height=this.textSize.height+this.margin.top+this.margin.bottom,this.radius=.5*this.width)}},{key:"draw",value:function(t,e,i,o,n,s){this.resize(t,o,n),this.left=e-this.width/2,this.top=i-this.height/2,this.enableShadow(t,s),this.labelModule.draw(t,this.left+this.textSize.width/2+this.margin.left,this.top+this.textSize.height/2+this.margin.top,o,n),this.disableShadow(t,s),this.updateBoundingBox(e,i,t,o,n)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(24),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"triangle",3,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(24),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"draw",value:function(t,e,i,o,n,s){this._drawShape(t,"triangleDown",3,e,i,o,n,s)}},{key:"distanceToBorder",value:function(t,e){return this._distanceToBorder(t,e)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=i(2),d=i(11),l=i(12),u=i(74).default,c=function(){function t(e,i,o){var n=this;(0,s.default)(this,t),this.body=e,this.images=i,this.groups=o,this.body.functions.createEdge=this.create.bind(this),this.edgesListeners={add:function(t,e){n.add(e.items)},update:function(t,e){n.update(e.items)},remove:function(t,e){n.remove(e.items)}},this.options={},this.defaultOptions={arrows:{to:{enabled:!1,scaleFactor:1,type:"arrow"},middle:{enabled:!1,scaleFactor:1,type:"arrow"},from:{enabled:!1,scaleFactor:1,type:"arrow"}},arrowStrikethrough:!0,color:{color:"#848484",highlight:"#848484",hover:"#848484",inherit:"from",opacity:1},dashes:!1,font:{color:"#343434",size:14,face:"arial",background:"none",strokeWidth:2,strokeColor:"#ffffff",align:"horizontal",multi:!1,vadjust:0,bold:{mod:"bold"},boldital:{mod:"bold italic"},ital:{mod:"italic"},mono:{mod:"",size:15,face:"courier new",vadjust:2}},hidden:!1,hoverWidth:1.5,label:void 0,labelHighlightBold:!0,length:void 0,physics:!0,scaling:{min:1,max:15,label:{enabled:!0,min:14,max:30,maxVisible:30,drawThreshold:5},customScalingFunction:function(t,e,i,o){if(e===t)return.5;var n=1/(e-t);return Math.max(0,(o-t)*n)}},selectionWidth:1.5,selfReferenceSize:20,shadow:{enabled:!1,color:"rgba(0,0,0,0.5)",size:10,x:5,y:5},smooth:{enabled:!0,type:"dynamic",forceDirection:"none",roundness:.5},title:void 0,width:1,value:void 0},h.deepExtend(this.options,this.defaultOptions),this.bindEventListeners()}return(0,a.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("_forceDisableDynamicCurves",function(e){var i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];"dynamic"===e&&(e="continuous");var o=!1;for(var n in t.body.edges)if(t.body.edges.hasOwnProperty(n)){var s=t.body.edges[n],r=t.body.data.edges._data[n];if(void 0!==r){var a=r.smooth;void 0!==a&&!0===a.enabled&&"dynamic"===a.type&&(void 0===e?s.setOptions({smooth:!1}):s.setOptions({smooth:{type:e}}),o=!0)}}!0===i&&!0===o&&t.body.emitter.emit("_dataChanged")}),this.body.emitter.on("_dataUpdated",function(){t.reconnectEdges()}),this.body.emitter.on("refreshEdges",this.refresh.bind(this)),this.body.emitter.on("refresh",this.refresh.bind(this)),this.body.emitter.on("destroy",function(){h.forEach(t.edgesListeners,function(e,i){t.body.data.edges&&t.body.data.edges.off(i,e)}),delete t.body.functions.createEdge,delete t.edgesListeners.add,delete t.edgesListeners.update,delete t.edgesListeners.remove,delete t.edgesListeners})}},{key:"setOptions",value:function(t){if(void 0!==t){u.parseOptions(this.options,t,!0,this.defaultOptions,!0);var e=!1;if(void 0!==t.smooth)for(var i in this.body.edges)this.body.edges.hasOwnProperty(i)&&(e=this.body.edges[i].updateEdgeType()||e);if(void 0!==t.font)for(var o in this.body.edges)this.body.edges.hasOwnProperty(o)&&this.body.edges[o].updateLabelModule();void 0===t.hidden&&void 0===t.physics&&!0!==e||this.body.emitter.emit("_dataChanged")}}},{key:"setData",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],o=this.body.data.edges;if(t instanceof d||t instanceof l)this.body.data.edges=t;else if(Array.isArray(t))this.body.data.edges=new d,this.body.data.edges.add(t);else{if(t)throw new TypeError("Array or DataSet expected");this.body.data.edges=new d}if(o&&h.forEach(this.edgesListeners,function(t,e){o.off(e,t)}),this.body.edges={},this.body.data.edges){h.forEach(this.edgesListeners,function(t,i){e.body.data.edges.on(i,t)});var n=this.body.data.edges.getIds();this.add(n,!0)}this.body.emitter.emit("_adjustEdgesForHierarchicalLayout"),!1===i&&this.body.emitter.emit("_dataChanged")}},{key:"add",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.body.edges,o=this.body.data.edges,n=0;n1&&void 0!==arguments[1])||arguments[1];if(0!==t.length){var i=this.body.edges;h.forEach(t,function(t){var e=i[t];void 0!==e&&e.remove()}),e&&this.body.emitter.emit("_dataChanged")}}},{key:"refresh",value:function(){var t=this;h.forEach(this.body.edges,function(e,i){var o=t.body.data.edges._data[i];void 0!==o&&e.setOptions(o)})}},{key:"create",value:function(t){return new u(t,this.body,this.options,this.defaultOptions)}},{key:"reconnectEdges",value:function(){var t,e=this.body.nodes,i=this.body.edges;for(t in e)e.hasOwnProperty(t)&&(e[t].edges=[]);for(t in i)if(i.hasOwnProperty(t)){var o=i[t];o.from=null,o.to=null,o.connect()}}},{key:"getConnectedNodes",value:function(t){var e=[];if(void 0!==this.body.edges[t]){var i=this.body.edges[t];void 0!==i.fromId&&e.push(i.fromId),void 0!==i.toId&&e.push(i.toId)}return e}},{key:"_updateState",value:function(){this._addMissingEdges(),this._removeInvalidEdges()}},{key:"_removeInvalidEdges",value:function(){var t=this,e=[];h.forEach(this.body.edges,function(i,o){var n=t.body.nodes[i.toId],s=t.body.nodes[i.fromId];void 0!==n&&!0===n.isCluster||void 0!==s&&!0===s.isCluster||void 0!==n&&void 0!==s||e.push(o)}),this.remove(e,!1)}},{key:"_addMissingEdges",value:function(){var t=this.body.edges,e=this.body.data.edges,i=[];e.forEach(function(e,o){void 0===t[o]&&i.push(o)}),this.add(i,!0)}}]),t}();e.default=c},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(30),s=o(n),r=i(3),a=o(r),h=i(0),d=o(h),l=i(1),u=o(l),c=i(4),p=o(c),f=i(5),m=o(f),v=i(216),g=o(v),y=function(t){function e(t,i,o){return(0,d.default)(this,e),(0,p.default)(this,(e.__proto__||(0,a.default)(e)).call(this,t,i,o))}return(0,m.default)(e,t),(0,u.default)(e,[{key:"_line",value:function(t,e,i){var o=i[0],n=i[1];this._bezierCurve(t,e,o,n)}},{key:"_getViaCoordinates",value:function(){var t=this.from.x-this.to.x,e=this.from.y-this.to.y,i=void 0,o=void 0,n=void 0,s=void 0,r=this.options.smooth.roundness;return(Math.abs(t)>Math.abs(e)||!0===this.options.smooth.forceDirection||"horizontal"===this.options.smooth.forceDirection)&&"vertical"!==this.options.smooth.forceDirection?(o=this.from.y,s=this.to.y,i=this.from.x-r*t,n=this.to.x+r*t):(o=this.from.y-r*e,s=this.to.y+r*e,i=this.from.x,n=this.to.x),[{x:i,y:o},{x:n,y:s}]}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,r){var a=arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates(),h=(0,s.default)(a,2),d=h[0],l=h[1];return this._getDistanceToBezierEdge(t,e,i,o,n,r,d,l)}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),i=(0,s.default)(e,2),o=i[0],n=i[1],r=t,a=[];return a[0]=Math.pow(1-r,3),a[1]=3*r*Math.pow(1-r,2),a[2]=3*Math.pow(r,2)*(1-r),a[3]=Math.pow(r,3),{x:a[0]*this.fromPoint.x+a[1]*o.x+a[2]*n.x+a[3]*this.toPoint.x,y:a[0]*this.fromPoint.y+a[1]*o.y+a[2]*n.y+a[3]*this.toPoint.y}}}]),e}(g.default);e.default=y},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(75),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_getDistanceToBezierEdge",value:function(t,e,i,o,n,s,r,a){var h=1e9,d=void 0,l=void 0,u=void 0,c=void 0,p=void 0,f=t,m=e,v=[0,0,0,0];for(l=1;l<10;l++)u=.1*l,v[0]=Math.pow(1-u,3),v[1]=3*u*Math.pow(1-u,2),v[2]=3*Math.pow(u,2)*(1-u),v[3]=Math.pow(u,3),c=v[0]*t+v[1]*r.x+v[2]*a.x+v[3]*i,p=v[0]*e+v[1]*r.y+v[2]*a.y+v[3]*o,l>0&&(d=this._getDistanceToLine(f,m,c,p,n,s),h=d1&&void 0!==arguments[1]?arguments[1]:this.via,i=t,o=void 0,n=void 0;if(this.from===this.to){var r=this._getCircleData(this.from),a=(0,s.default)(r,3),h=a[0],d=a[1],l=a[2],u=2*Math.PI*(1-i);o=h+l*Math.sin(u),n=d+l-l*(1-Math.cos(u))}else o=Math.pow(1-i,2)*this.fromPoint.x+2*i*(1-i)*e.x+Math.pow(i,2)*this.toPoint.x,n=Math.pow(1-i,2)*this.fromPoint.y+2*i*(1-i)*e.y+Math.pow(i,2)*this.toPoint.y;return{x:o,y:n}}},{key:"_findBorderPosition",value:function(t,e){return this._findBorderPositionBezier(t,e,this.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,s){return this._getDistanceToBezierEdge(t,e,i,o,n,s,this.via)}}]),e}(g.default);e.default=y},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(75),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_line",value:function(t,e,i){this._bezierCurve(t,e,i)}},{key:"getViaNode",value:function(){return this._getViaCoordinates()}},{key:"_getViaCoordinates",value:function(){var t=void 0,e=void 0,i=this.options.smooth.roundness,o=this.options.smooth.type,n=Math.abs(this.from.x-this.to.x),s=Math.abs(this.from.y-this.to.y);if("discrete"===o||"diagonalCross"===o){var r=void 0,a=void 0;r=a=n<=s?i*s:i*n,this.from.x>this.to.x&&(r=-r),this.from.y>=this.to.y&&(a=-a),t=this.from.x+r,e=this.from.y+a,"discrete"===o&&(n<=s?t=nthis.to.x&&(_=-_),this.from.y>=this.to.y&&(w=-w),t=this.from.x+_,e=this.from.y+w,n<=s?t=this.from.x<=this.to.x?this.to.xt?this.to.x:t:e=this.from.y>=this.to.y?this.to.y>e?this.to.y:e:this.to.y2&&void 0!==arguments[2]?arguments[2]:{};return this._findBorderPositionBezier(t,e,i.via)}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,s){var r=arguments.length>6&&void 0!==arguments[6]?arguments[6]:this._getViaCoordinates();return this._getDistanceToBezierEdge(t,e,i,o,n,s,r)}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this._getViaCoordinates(),i=t;return{x:Math.pow(1-i,2)*this.fromPoint.x+2*i*(1-i)*e.x+Math.pow(i,2)*this.toPoint.x,y:Math.pow(1-i,2)*this.fromPoint.y+2*i*(1-i)*e.y+Math.pow(i,2)*this.toPoint.y}}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(118),m=o(f),v=function(t){function e(t,i,o){return(0,a.default)(this,e),(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o))}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_line",value:function(t,e){t.beginPath(),t.moveTo(this.fromPoint.x,this.fromPoint.y),t.lineTo(this.toPoint.x,this.toPoint.y),this.enableShadow(t,e),t.stroke(),this.disableShadow(t,e)}},{key:"getViaNode",value:function(){}},{key:"getPoint",value:function(t){return{x:(1-t)*this.fromPoint.x+t*this.toPoint.x,y:(1-t)*this.fromPoint.y+t*this.toPoint.y}}},{key:"_findBorderPosition",value:function(t,e){var i=this.to,o=this.from;t.id===this.from.id&&(i=this.from,o=this.to);var n=Math.atan2(i.y-o.y,i.x-o.x),s=i.x-o.x,r=i.y-o.y,a=Math.sqrt(s*s+r*r),h=t.distanceToBorder(e,n),d=(a-h)/a,l={};return l.x=(1-d)*o.x+d*i.x,l.y=(1-d)*o.y+d*i.y,l}},{key:"_getDistanceToEdge",value:function(t,e,i,o,n,s){return this._getDistanceToLine(t,e,i,o,n,s)}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(8),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(120).default,u=i(221).default,c=i(222).default,p=i(223).default,f=i(224).default,m=i(121).default,v=i(225).default,g=i(226).default,y=i(2),b=i(119).default,_=function(){function t(e){(0,a.default)(this,t),this.body=e,this.physicsBody={physicsNodeIndices:[],physicsEdgeIndices:[],forces:{},velocities:{}},this.physicsEnabled=!0,this.simulationInterval=1e3/60,this.requiresTimeout=!0,this.previousStates={},this.referenceState={},this.freezeCache={},this.renderTimer=void 0,this.adaptiveTimestep=!1,this.adaptiveTimestepEnabled=!1,this.adaptiveCounter=0,this.adaptiveInterval=3,this.stabilized=!1,this.startedStabilization=!1,this.stabilizationIterations=0,this.ready=!1,this.options={},this.defaultOptions={enabled:!0,barnesHut:{theta:.5,gravitationalConstant:-2e3,centralGravity:.3,springLength:95,springConstant:.04,damping:.09,avoidOverlap:0},forceAtlas2Based:{theta:.5,gravitationalConstant:-50,centralGravity:.01,springConstant:.08,springLength:100,damping:.4,avoidOverlap:0},repulsion:{centralGravity:.2,springLength:200,springConstant:.05,nodeDistance:100,damping:.09,avoidOverlap:0},hierarchicalRepulsion:{centralGravity:0,springLength:100,springConstant:.01,nodeDistance:120,damping:.09},maxVelocity:50,minVelocity:.75,solver:"barnesHut",stabilization:{enabled:!0,iterations:1e3,updateInterval:50,onlyDynamicEdges:!1,fit:!0},timestep:.5,adaptiveTimestep:!0},y.extend(this.options,this.defaultOptions),this.timestep=.5,this.layoutFailed=!1,this.bindEventListeners()}return(0,d.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("initPhysics",function(){t.initPhysics()}),this.body.emitter.on("_layoutFailed",function(){t.layoutFailed=!0}),this.body.emitter.on("resetPhysics",function(){t.stopSimulation(),t.ready=!1}),this.body.emitter.on("disablePhysics",function(){t.physicsEnabled=!1,t.stopSimulation()}),this.body.emitter.on("restorePhysics",function(){t.setOptions(t.options),!0===t.ready&&t.startSimulation()}),this.body.emitter.on("startSimulation",function(){!0===t.ready&&t.startSimulation()}),this.body.emitter.on("stopSimulation",function(){t.stopSimulation()}),this.body.emitter.on("destroy",function(){t.stopSimulation(!1),t.body.emitter.off()}),this.body.emitter.on("_dataChanged",function(){t.updatePhysicsData()})}},{key:"setOptions",value:function(t){void 0!==t&&(!1===t?(this.options.enabled=!1,this.physicsEnabled=!1,this.stopSimulation()):!0===t?(this.options.enabled=!0,this.physicsEnabled=!0,this.startSimulation()):(this.physicsEnabled=!0,y.selectiveNotDeepExtend(["stabilization"],this.options,t),y.mergeOptions(this.options,t,"stabilization"),void 0===t.enabled&&(this.options.enabled=!0),!1===this.options.enabled&&(this.physicsEnabled=!1,this.stopSimulation()),this.timestep=this.options.timestep)),this.init()}},{key:"init",value:function(){var t;"forceAtlas2Based"===this.options.solver?(t=this.options.forceAtlas2Based,this.nodesSolver=new v(this.body,this.physicsBody,t),this.edgesSolver=new p(this.body,this.physicsBody,t),this.gravitySolver=new g(this.body,this.physicsBody,t)):"repulsion"===this.options.solver?(t=this.options.repulsion,this.nodesSolver=new u(this.body,this.physicsBody,t),this.edgesSolver=new p(this.body,this.physicsBody,t),this.gravitySolver=new m(this.body,this.physicsBody,t)):"hierarchicalRepulsion"===this.options.solver?(t=this.options.hierarchicalRepulsion,this.nodesSolver=new c(this.body,this.physicsBody,t),this.edgesSolver=new f(this.body,this.physicsBody,t),this.gravitySolver=new m(this.body,this.physicsBody,t)):(t=this.options.barnesHut,this.nodesSolver=new l(this.body,this.physicsBody,t),this.edgesSolver=new p(this.body,this.physicsBody,t),this.gravitySolver=new m(this.body,this.physicsBody,t)),this.modelOptions=t}},{key:"initPhysics",value:function(){!0===this.physicsEnabled&&!0===this.options.enabled?!0===this.options.stabilization.enabled?this.stabilize():(this.stabilized=!1,this.ready=!0,this.body.emitter.emit("fit",{},this.layoutFailed),this.startSimulation()):(this.ready=!0,this.body.emitter.emit("fit"))}},{key:"startSimulation",value:function(){!0===this.physicsEnabled&&!0===this.options.enabled?(this.stabilized=!1,this.adaptiveTimestep=!1,this.body.emitter.emit("_resizeNodes"),void 0===this.viewFunction&&(this.viewFunction=this.simulationStep.bind(this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering"))):this.body.emitter.emit("_redraw")}},{key:"stopSimulation",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.stabilized=!0,!0===t&&this._emitStabilized(),void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.viewFunction=void 0,!0===t&&this.body.emitter.emit("_stopRendering"))}},{key:"simulationStep",value:function(){var t=Date.now();this.physicsTick(),(Date.now()-t<.4*this.simulationInterval||!0===this.runDoubleSpeed)&&!1===this.stabilized&&(this.physicsTick(),this.runDoubleSpeed=!0),!0===this.stabilized&&this.stopSimulation()}},{key:"_emitStabilized",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.stabilizationIterations;(this.stabilizationIterations>1||!0===this.startedStabilization)&&setTimeout(function(){t.body.emitter.emit("stabilized",{iterations:e}),t.startedStabilization=!1,t.stabilizationIterations=0},0)}},{key:"physicsStep",value:function(){this.gravitySolver.solve(),this.nodesSolver.solve(),this.edgesSolver.solve(),this.moveNodes()}},{key:"adjustTimeStep",value:function(){!0===this._evaluateStepQuality()?this.timestep=1.2*this.timestep:this.timestep/1.2.3))return!1;return!0}},{key:"moveNodes",value:function(){for(var t=this.physicsBody.physicsNodeIndices,e=0,i=0,o=0;oo&&(t=t>0?o:-o),t}},{key:"_performStep",value:function(t){var e=this.body.nodes[t],i=this.physicsBody.forces[t],o=this.physicsBody.velocities[t];return this.previousStates[t]={x:e.x,y:e.y,vx:o.x,vy:o.y},!1===e.options.fixed.x?(o.x=this.calculateComponentVelocity(o.x,i.x,e.options.mass),e.x+=o.x*this.timestep):(i.x=0,o.x=0),!1===e.options.fixed.y?(o.y=this.calculateComponentVelocity(o.y,i.y,e.options.mass),e.y+=o.y*this.timestep):(i.y=0,o.y=0),Math.sqrt(Math.pow(o.x,2)+Math.pow(o.y,2))}},{key:"_freezeNodes",value:function(){var t=this.body.nodes;for(var e in t)if(t.hasOwnProperty(e)&&t[e].x&&t[e].y){var i=t[e].options.fixed;this.freezeCache[e]={x:i.x,y:i.y},i.x=!0,i.y=!0}}},{key:"_restoreFrozenNodes",value:function(){var t=this.body.nodes;for(var e in t)t.hasOwnProperty(e)&&void 0!==this.freezeCache[e]&&(t[e].options.fixed.x=this.freezeCache[e].x,t[e].options.fixed.y=this.freezeCache[e].y);this.freezeCache={}}},{key:"stabilize",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.stabilization.iterations;if("number"!=typeof e&&(e=this.options.stabilization.iterations,console.log("The stabilize method needs a numeric amount of iterations. Switching to default: ",e)),0===this.physicsBody.physicsNodeIndices.length)return void(this.ready=!0);this.adaptiveTimestep=this.options.adaptiveTimestep,this.body.emitter.emit("_resizeNodes"),this.stopSimulation(),this.stabilized=!1,this.body.emitter.emit("_blockRedraw"),this.targetIterations=e,!0===this.options.stabilization.onlyDynamicEdges&&this._freezeNodes(),this.stabilizationIterations=0,setTimeout(function(){return t._stabilizationBatch()},0)}},{key:"_startStabilizing",value:function(){return!0!==this.startedStabilization&&(this.body.emitter.emit("startStabilizing"),this.startedStabilization=!0,!0)}},{key:"_stabilizationBatch",value:function(){var t=this,e=function(){return!1===t.stabilized&&t.stabilizationIterations0){var s=n.edges.length+1,r=this.options.centralGravity*s*n.options.mass;o[n.id].x=e*r,o[n.id].y=i*r}}}]),e}(m.default);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(8),s=o(n),r=i(6),a=o(r),h=i(0),d=o(h),l=i(1),u=o(l),c=i(2),p=i(76).default,f=i(228).default,m=i(74).default,v=i(47).default,g=function(){function t(e){var i=this;(0,d.default)(this,t),this.body=e,this.clusteredNodes={},this.clusteredEdges={},this.options={},this.defaultOptions={},c.extend(this.options,this.defaultOptions),this.body.emitter.on("_resetData",function(){i.clusteredNodes={},i.clusteredEdges={}})}return(0,u.default)(t,[{key:"clusterByHubsize",value:function(t,e){void 0===t?t=this._getHubSize():"object"===(void 0===t?"undefined":(0,a.default)(t))&&(e=this._checkOptions(t),t=this._getHubSize());for(var i=[],o=0;o=t&&i.push(n.id)}for(var s=0;s0&&void 0!==arguments[0]?arguments[0]:{},i=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(void 0===e.joinCondition)throw new Error("Cannot call clusterByNodeData without a joinCondition function in the options.");e=this._checkOptions(e);var o={},n={};c.forEach(this.body.nodes,function(i,s){var r=p.cloneOptions(i);!0===e.joinCondition(r)&&(o[s]=i,c.forEach(i.edges,function(e){void 0===t.clusteredEdges[e.id]&&(n[e.id]=e)}))}),this._cluster(o,n,e,i)}},{key:"clusterByEdgeCount",value:function(t,e){var i=this,o=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];e=this._checkOptions(e);for(var n=[],r={},a=void 0,h=void 0,d=void 0,l=0;l0&&(0,s.default)(m).length>0&&!0===b)if(c=function(){for(var t=0;t1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(1,t,e)}},{key:"clusterBridges",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.clusterByEdgeCount(2,t,e)}},{key:"clusterByConnection",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No nodeId supplied to clusterByConnection!");if(void 0===this.body.nodes[t])throw new Error("The nodeId given to clusterByConnection does not exist!");var o=this.body.nodes[t];e=this._checkOptions(e,o),void 0===e.clusterNodeProperties.x&&(e.clusterNodeProperties.x=o.x),void 0===e.clusterNodeProperties.y&&(e.clusterNodeProperties.y=o.y),void 0===e.clusterNodeProperties.fixed&&(e.clusterNodeProperties.fixed={},e.clusterNodeProperties.fixed.x=o.options.fixed.x,e.clusterNodeProperties.fixed.y=o.options.fixed.y);var n={},r={},a=o.id,h=p.cloneOptions(o);n[a]=o;for(var d=0;d-1&&(r[g.id]=g)}this._cluster(n,r,e,i)}},{key:"_createClusterEdges",value:function(t,e,i,o){for(var n=void 0,r=void 0,a=void 0,h=void 0,d=void 0,l=void 0,u=(0,s.default)(t),c=[],p=0;p0&&void 0!==arguments[0]?arguments[0]:{};return void 0===t.clusterEdgeProperties&&(t.clusterEdgeProperties={}),void 0===t.clusterNodeProperties&&(t.clusterNodeProperties={}),t}},{key:"_cluster",value:function(t,e,i){var o=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],n=[];for(var r in t)t.hasOwnProperty(r)&&void 0!==this.clusteredNodes[r]&&n.push(r);for(var a=0;ao?a.x:o,n=a.yr?a.y:r;return{x:.5*(i+o),y:.5*(n+r)}}},{key:"openCluster",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(void 0===t)throw new Error("No clusterNodeId supplied to openCluster.");var o=this.body.nodes[t];if(void 0===o)throw new Error("The clusterNodeId supplied to openCluster does not exist.");if(!0!==o.isCluster||void 0===o.containedNodes||void 0===o.containedEdges)throw new Error("The node:"+t+" is not a valid cluster.");var n=this.findNode(t),s=n.indexOf(t)-1;if(s>=0){var r=n[s];return this.body.nodes[r]._openChildCluster(t),delete this.body.nodes[t],void(!0===i&&this.body.emitter.emit("_dataChanged"))}var a=o.containedNodes,h=o.containedEdges;if(void 0!==e&&void 0!==e.releaseFunction&&"function"==typeof e.releaseFunction){var d={},l={x:o.x,y:o.y};for(var u in a)if(a.hasOwnProperty(u)){var p=this.body.nodes[u];d[u]={x:p.x,y:p.y}}var f=e.releaseFunction(l,d);for(var m in a)if(a.hasOwnProperty(m)){var v=this.body.nodes[m];void 0!==f[m]&&(v.x=void 0===f[m].x?o.x:f[m].x,v.y=void 0===f[m].y?o.y:f[m].y)}}else c.forEach(a,function(t){!1===t.options.fixed.x&&(t.x=o.x),!1===t.options.fixed.y&&(t.y=o.y)});for(var g in a)if(a.hasOwnProperty(g)){var y=this.body.nodes[g];y.vx=o.vx,y.vy=o.vy,y.setOptions({physics:!0}),delete this.clusteredNodes[g]}for(var b=[],_=0;_0&&n<100;){var s=e.pop();if(void 0!==s){var r=this.body.edges[s];if(void 0!==r){n++;var a=r.clusteringEdgeReplacingIds;if(void 0===a)o.push(s);else for(var h=0;ho&&(o=s.edges.length),t+=s.edges.length,e+=Math.pow(s.edges.length,2),i+=1}t/=i,e/=i;var r=e-Math.pow(t,2),a=Math.sqrt(r),h=Math.floor(t+2*a);return h>o&&(h=o),h}},{key:"_createClusteredEdge",value:function(t,e,i,o,n){var s=p.cloneOptions(i,"edge");c.deepExtend(s,o),s.from=t,s.to=e,s.id="clusterEdge:"+c.randomUUID(),void 0!==n&&c.deepExtend(s,n);var r=this.body.functions.createEdge(s);return r.clusteringEdgeReplacingIds=[i.id],r.connect(),this.body.edges[r.id]=r,r}},{key:"_clusterEdges",value:function(t,e,i,o){if(e instanceof m){var n=e,s={};s[n.id]=n,e=s}if(t instanceof v){var r=t,a={};a[r.id]=r,t=a}if(void 0===i||null===i)throw new Error("_clusterEdges: parameter clusterNode required");void 0===o&&(o=i.clusterEdgeProperties),this._createClusterEdges(t,e,i,o);for(var h in e)if(e.hasOwnProperty(h)&&void 0!==this.body.edges[h]){var d=this.body.edges[h];this._backupEdgeOptions(d),d.setOptions({physics:!1})}for(var l in t)t.hasOwnProperty(l)&&(this.clusteredNodes[l]={clusterId:i.id,node:this.body.nodes[l]},this.body.nodes[l].setOptions({physics:!1}))}},{key:"_getClusterNodeForNode",value:function(t){if(void 0!==t){var e=this.clusteredNodes[t];if(void 0!==e){var i=e.clusterId;if(void 0!==i)return this.body.nodes[i]}}}},{key:"_filter",value:function(t,e){var i=[];return c.forEach(t,function(t){e(t)&&i.push(t)}),i}},{key:"_updateState",value:function(){var t=this,e=void 0,i=[],o=[],n=function(e){c.forEach(t.body.nodes,function(t){!0===t.isCluster&&e(t)})};for(e in this.clusteredNodes)if(this.clusteredNodes.hasOwnProperty(e)){var r=this.body.nodes[e];void 0===r&&i.push(e)}n(function(t){for(var e=0;e0}e.endPointsValid()&&n||o.push(i)}),n(function(e){c.forEach(o,function(i){delete e.containedEdges[i],c.forEach(e.edges,function(n,s){if(n.id===i)return void(e.edges[s]=null);n.clusteringEdgeReplacingIds=t._filter(n.clusteringEdgeReplacingIds,function(t){return-1===o.indexOf(t)})}),e.edges=t._filter(e.edges,function(t){return null!==t})})}),c.forEach(o,function(e){delete t.clusteredEdges[e]}),c.forEach(o,function(e){delete t.body.edges[e]});var h=(0,s.default)(this.body.edges);c.forEach(h,function(e){var i=t.body.edges[e],o=t._isClusteredNode(i.fromId)||t._isClusteredNode(i.toId);if(o!==t._isClusteredEdge(i.id)){if(!o)throw new Error("remove edge from clustering not implemented!");var n=t._getClusterNodeForNode(i.fromId);void 0!==n&&t._clusterEdges(t.body.nodes[i.fromId],i,n);var s=t._getClusterNodeForNode(i.toId);void 0!==s&&t._clusterEdges(t.body.nodes[i.toId],i,s)}});for(var d=!1,l=!0;l;)!function(){var e=[];n(function(t){var i=(0,s.default)(t.containedNodes).length,o=!0===t.options.allowSingleNodeCluster;(o&&i<1||!o&&i<2)&&e.push(t.id)});for(var i=0;i0,d=d||l}();d&&this._updateState()}},{key:"_isClusteredNode",value:function(t){return void 0!==this.clusteredNodes[t]}},{key:"_isClusteredEdge",value:function(t){return void 0!==this.clusteredEdges[t]}}]),t}();e.default=g},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(3),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(4),u=o(l),c=i(5),p=o(c),f=i(2),m=i(47).default,v=function(t){function e(t,i,o,n,r,h){(0,a.default)(this,e);var d=(0,u.default)(this,(e.__proto__||(0,s.default)(e)).call(this,t,i,o,n,r,h));return d.isCluster=!0,d.containedNodes={},d.containedEdges={},d}return(0,p.default)(e,t),(0,d.default)(e,[{key:"_openChildCluster",value:function(t){var e=this,i=this.body.nodes[t];if(void 0===this.containedNodes[t])throw new Error("node with id: "+t+" not in current cluster");if(!i.isCluster)throw new Error("node with id: "+t+" is not a cluster");delete this.containedNodes[t],f.forEach(i.edges,function(t){delete e.containedEdges[t.id]}),f.forEach(i.containedNodes,function(t,i){e.containedNodes[i]=t}),i.containedNodes={},f.forEach(i.containedEdges,function(t,i){e.containedEdges[i]=t}),i.containedEdges={},f.forEach(i.edges,function(t){f.forEach(e.edges,function(i){var o=i.clusteringEdgeReplacingIds.indexOf(t.id);-1!==o&&(f.forEach(t.clusteringEdgeReplacingIds,function(t){i.clusteringEdgeReplacingIds.push(t),e.body.edges[t].edgeReplacedById=i.id}),i.clusteringEdgeReplacingIds.splice(o,1))})}),i.edges=[]}}]),e}(m);e.default=v},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}function n(){var t;void 0!==window&&(t=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame),window.requestAnimationFrame=void 0===t?function(t){t()}:t}Object.defineProperty(e,"__esModule",{value:!0});var s=i(0),r=o(s),a=i(1),h=o(a),d=i(2),l=function(){function t(e,i){(0,r.default)(this,t),n(),this.body=e,this.canvas=i,this.redrawRequested=!1,this.renderTimer=void 0,this.requiresTimeout=!0,this.renderingActive=!1,this.renderRequests=0,this.allowRedraw=!0,this.dragging=!1,this.options={},this.defaultOptions={hideEdgesOnDrag:!1,hideNodesOnDrag:!1},d.extend(this.options,this.defaultOptions),this._determineBrowserMethod(),this.bindEventListeners()}return(0,h.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("dragStart",function(){t.dragging=!0}),this.body.emitter.on("dragEnd",function(){t.dragging=!1}),this.body.emitter.on("_resizeNodes",function(){t._resizeNodes()}),this.body.emitter.on("_redraw",function(){!1===t.renderingActive&&t._redraw()}),this.body.emitter.on("_blockRedraw",function(){t.allowRedraw=!1}),this.body.emitter.on("_allowRedraw",function(){t.allowRedraw=!0,t.redrawRequested=!1}),this.body.emitter.on("_requestRedraw",this._requestRedraw.bind(this)),this.body.emitter.on("_startRendering",function(){t.renderRequests+=1,t.renderingActive=!0,t._startRendering()}),this.body.emitter.on("_stopRendering",function(){t.renderRequests-=1,t.renderingActive=t.renderRequests>0,t.renderTimer=void 0}),this.body.emitter.on("destroy",function(){t.renderRequests=0,t.allowRedraw=!1,t.renderingActive=!1,!0===t.requiresTimeout?clearTimeout(t.renderTimer):window.cancelAnimationFrame(t.renderTimer),t.body.emitter.off()})}},{key:"setOptions",value:function(t){if(void 0!==t){var e=["hideEdgesOnDrag","hideNodesOnDrag"];d.selectiveDeepExtend(e,this.options,t)}}},{key:"_requestNextFrame",value:function(t,e){if("undefined"!=typeof window){var i=void 0,o=window;return!0===this.requiresTimeout?i=o.setTimeout(t,e):o.requestAnimationFrame&&(i=o.requestAnimationFrame(t)),i}}},{key:"_startRendering",value:function(){!0===this.renderingActive&&void 0===this.renderTimer&&(this.renderTimer=this._requestNextFrame(this._renderStep.bind(this),this.simulationInterval))}},{key:"_renderStep",value:function(){!0===this.renderingActive&&(this.renderTimer=void 0,!0===this.requiresTimeout&&this._startRendering(),this._redraw(),!1===this.requiresTimeout&&this._startRendering())}},{key:"redraw",value:function(){this.body.emitter.emit("setSize"),this._redraw()}},{key:"_requestRedraw",value:function(){var t=this;!0!==this.redrawRequested&&!1===this.renderingActive&&!0===this.allowRedraw&&(this.redrawRequested=!0,this._requestNextFrame(function(){t._redraw(!1)},0))}},{key:"_redraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(!0===this.allowRedraw){this.body.emitter.emit("initRedraw"),this.redrawRequested=!1,0!==this.canvas.frame.canvas.width&&0!==this.canvas.frame.canvas.height||this.canvas.setSize(),this.canvas.setTransform();var e=this.canvas.getContext(),i=this.canvas.frame.canvas.clientWidth,o=this.canvas.frame.canvas.clientHeight;if(e.clearRect(0,0,i,o),0===this.canvas.frame.clientWidth)return;e.save(),e.translate(this.body.view.translation.x,this.body.view.translation.y),e.scale(this.body.view.scale,this.body.view.scale),e.beginPath(),this.body.emitter.emit("beforeDrawing",e),e.closePath(),!1===t&&(!1===this.dragging||!0===this.dragging&&!1===this.options.hideEdgesOnDrag)&&this._drawEdges(e),(!1===this.dragging||!0===this.dragging&&!1===this.options.hideNodesOnDrag)&&this._drawNodes(e,t),e.beginPath(),this.body.emitter.emit("afterDrawing",e),e.closePath(),e.restore(),!0===t&&e.clearRect(0,0,i,o)}}},{key:"_resizeNodes",value:function(){this.canvas.setTransform();var t=this.canvas.getContext();t.save(),t.translate(this.body.view.translation.x,this.body.view.translation.y),t.scale(this.body.view.scale,this.body.view.scale);var e=this.body.nodes,i=void 0;for(var o in e)e.hasOwnProperty(o)&&(i=e[o],i.resize(t),i.updateBoundingBox(t,i.selected));t.restore()}},{key:"_drawNodes",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=this.body.nodes,o=this.body.nodeIndices,n=void 0,s=[],r=this.canvas.DOMtoCanvas({x:-20,y:-20}),a=this.canvas.DOMtoCanvas({x:this.canvas.frame.canvas.clientWidth+20,y:this.canvas.frame.canvas.clientHeight+20}),h={top:r.y,left:r.x,bottom:a.y,right:a.x},d=0;d0&&void 0!==arguments[0]?arguments[0]:this.pixelRatio;!0===this.initialized&&(this.cameraState.previousWidth=this.frame.canvas.width/t,this.cameraState.previousHeight=this.frame.canvas.height/t,this.cameraState.scale=this.body.view.scale,this.cameraState.position=this.DOMtoCanvas({x:.5*this.frame.canvas.width/t,y:.5*this.frame.canvas.height/t}))}},{key:"_setCameraState",value:function(){if(void 0!==this.cameraState.scale&&0!==this.frame.canvas.clientWidth&&0!==this.frame.canvas.clientHeight&&0!==this.pixelRatio&&this.cameraState.previousWidth>0){var t=this.frame.canvas.width/this.pixelRatio/this.cameraState.previousWidth,e=this.frame.canvas.height/this.pixelRatio/this.cameraState.previousHeight,i=this.cameraState.scale;1!=t&&1!=e?i=.5*this.cameraState.scale*(t+e):1!=t?i=this.cameraState.scale*t:1!=e&&(i=this.cameraState.scale*e),this.body.view.scale=i;var o=this.DOMtoCanvas({x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight}),n={x:o.x-this.cameraState.position.x,y:o.y-this.cameraState.position.y};this.body.view.translation.x+=n.x*this.body.view.scale,this.body.view.translation.y+=n.y*this.body.view.scale}}},{key:"_prepareValue",value:function(t){if("number"==typeof t)return t+"px";if("string"==typeof t){if(-1!==t.indexOf("%")||-1!==t.indexOf("px"))return t;if(-1===t.indexOf("%"))return t+"px"}throw new Error("Could not use the value supplied for width or height:"+t)}},{key:"_create",value:function(){for(;this.body.container.hasChildNodes();)this.body.container.removeChild(this.body.container.firstChild);if(this.frame=document.createElement("div"),this.frame.className="vis-network",this.frame.style.position="relative",this.frame.style.overflow="hidden",this.frame.tabIndex=900,this.frame.canvas=document.createElement("canvas"),this.frame.canvas.style.position="relative",this.frame.appendChild(this.frame.canvas),this.frame.canvas.getContext)this._setPixelRatio(),this.setTransform();else{var t=document.createElement("DIV");t.style.color="red",t.style.fontWeight="bold",t.style.padding="10px",t.innerHTML="Error: your browser does not support HTML canvas",this.frame.canvas.appendChild(t)}this.body.container.appendChild(this.frame),this.body.view.scale=1,this.body.view.translation={x:.5*this.frame.canvas.clientWidth,y:.5*this.frame.canvas.clientHeight},this._bindHammer()}},{key:"_bindHammer",value:function(){var t=this;void 0!==this.hammer&&this.hammer.destroy(),this.drag={},this.pinch={},this.hammer=new h(this.frame.canvas),this.hammer.get("pinch").set({enable:!0}),this.hammer.get("pan").set({threshold:5,direction:h.DIRECTION_ALL}),d.onTouch(this.hammer,function(e){t.body.eventListeners.onTouch(e)}),this.hammer.on("tap",function(e){t.body.eventListeners.onTap(e)}),this.hammer.on("doubletap",function(e){t.body.eventListeners.onDoubleTap(e)}),this.hammer.on("press",function(e){t.body.eventListeners.onHold(e)}),this.hammer.on("panstart",function(e){t.body.eventListeners.onDragStart(e)}),this.hammer.on("panmove",function(e){t.body.eventListeners.onDrag(e)}),this.hammer.on("panend",function(e){t.body.eventListeners.onDragEnd(e)}),this.hammer.on("pinch",function(e){t.body.eventListeners.onPinch(e)}),this.frame.canvas.addEventListener("mousewheel",function(e){t.body.eventListeners.onMouseWheel(e)}),this.frame.canvas.addEventListener("DOMMouseScroll",function(e){t.body.eventListeners.onMouseWheel(e)}),this.frame.canvas.addEventListener("mousemove",function(e){t.body.eventListeners.onMouseMove(e)}),this.frame.canvas.addEventListener("contextmenu",function(e){t.body.eventListeners.onContext(e)}),this.hammerFrame=new h(this.frame),d.onRelease(this.hammerFrame,function(e){t.body.eventListeners.onRelease(e)})}},{key:"setSize",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.width,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.height;t=this._prepareValue(t),e=this._prepareValue(e);var i=!1,o=this.frame.canvas.width,n=this.frame.canvas.height,s=this.pixelRatio;if(this._setPixelRatio(),t!=this.options.width||e!=this.options.height||this.frame.style.width!=t||this.frame.style.height!=e)this._getCameraState(s),this.frame.style.width=t,this.frame.style.height=e,this.frame.canvas.style.width="100%",this.frame.canvas.style.height="100%",this.frame.canvas.width=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),this.frame.canvas.height=Math.round(this.frame.canvas.clientHeight*this.pixelRatio),this.options.width=t,this.options.height=e,this.canvasViewCenter={x:.5*this.frame.clientWidth,y:.5*this.frame.clientHeight},i=!0;else{var r=Math.round(this.frame.canvas.clientWidth*this.pixelRatio),a=Math.round(this.frame.canvas.clientHeight*this.pixelRatio) +;this.frame.canvas.width===r&&this.frame.canvas.height===a||this._getCameraState(s),this.frame.canvas.width!==r&&(this.frame.canvas.width=r,i=!0),this.frame.canvas.height!==a&&(this.frame.canvas.height=a,i=!0)}return!0===i&&(this.body.emitter.emit("resize",{width:Math.round(this.frame.canvas.width/this.pixelRatio),height:Math.round(this.frame.canvas.height/this.pixelRatio),oldWidth:Math.round(o/this.pixelRatio),oldHeight:Math.round(n/this.pixelRatio)}),this._setCameraState()),this.initialized=!0,i}},{key:"getContext",value:function(){return this.frame.canvas.getContext("2d")}},{key:"_determinePixelRatio",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");var e=1;return"undefined"!=typeof window&&(e=window.devicePixelRatio||1),e/(t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1)}},{key:"_setPixelRatio",value:function(){this.pixelRatio=this._determinePixelRatio()}},{key:"setTransform",value:function(){var t=this.getContext();if(void 0===t)throw new Error("Could not get canvax context");t.setTransform(this.pixelRatio,0,0,this.pixelRatio,0,0)}},{key:"_XconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.x)/this.body.view.scale}},{key:"_XconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.x}},{key:"_YconvertDOMtoCanvas",value:function(t){return(t-this.body.view.translation.y)/this.body.view.scale}},{key:"_YconvertCanvasToDOM",value:function(t){return t*this.body.view.scale+this.body.view.translation.y}},{key:"canvasToDOM",value:function(t){return{x:this._XconvertCanvasToDOM(t.x),y:this._YconvertCanvasToDOM(t.y)}}},{key:"DOMtoCanvas",value:function(t){return{x:this._XconvertDOMtoCanvas(t.x),y:this._YconvertDOMtoCanvas(t.y)}}}]),t}();e.default=u},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=i(2),d=i(76).default,l=function(){function t(e,i){var o=this;(0,s.default)(this,t),this.body=e,this.canvas=i,this.animationSpeed=1/this.renderRefreshRate,this.animationEasingFunction="easeInOutQuint",this.easingTime=0,this.sourceScale=0,this.targetScale=0,this.sourceTranslation=0,this.targetTranslation=0,this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0,this.touchTime=0,this.viewFunction=void 0,this.body.emitter.on("fit",this.fit.bind(this)),this.body.emitter.on("animationFinished",function(){o.body.emitter.emit("_stopRendering")}),this.body.emitter.on("unlockNode",this.releaseNode.bind(this))}return(0,a.default)(t,[{key:"setOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.options=t}},{key:"fit",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{nodes:[]},e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=void 0,o=void 0;if(void 0!==t.nodes&&0!==t.nodes.length||(t.nodes=this.body.nodeIndices),!0===e){var n=0;for(var s in this.body.nodes)if(this.body.nodes.hasOwnProperty(s)){var r=this.body.nodes[s];!0===r.predefinedPosition&&(n+=1)}if(n>.5*this.body.nodeIndices.length)return void this.fit(t,!1);i=d.getRange(this.body.nodes,t.nodes);o=12.662/(this.body.nodeIndices.length+7.4147)+.0964822;o*=Math.min(this.canvas.frame.canvas.clientWidth/600,this.canvas.frame.canvas.clientHeight/600)}else{this.body.emitter.emit("_resizeNodes"),i=d.getRange(this.body.nodes,t.nodes);var a=1.1*Math.abs(i.maxX-i.minX),h=1.1*Math.abs(i.maxY-i.minY),l=this.canvas.frame.canvas.clientWidth/a,u=this.canvas.frame.canvas.clientHeight/h;o=l<=u?l:u}o>1?o=1:0===o&&(o=1);var c=d.findCenter(i),p={position:c,scale:o,animation:t.animation};this.moveTo(p)}},{key:"focus",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(void 0!==this.body.nodes[t]){var i={x:this.body.nodes[t].x,y:this.body.nodes[t].y};e.position=i,e.lockedOnNode=t,this.moveTo(e)}else console.log("Node: "+t+" cannot be found.")}},{key:"moveTo",value:function(t){if(void 0===t)return void(t={});void 0===t.offset&&(t.offset={x:0,y:0}),void 0===t.offset.x&&(t.offset.x=0),void 0===t.offset.y&&(t.offset.y=0),void 0===t.scale&&(t.scale=this.body.view.scale),void 0===t.position&&(t.position=this.getViewPosition()),void 0===t.animation&&(t.animation={duration:0}),!1===t.animation&&(t.animation={duration:0}),!0===t.animation&&(t.animation={}),void 0===t.animation.duration&&(t.animation.duration=1e3),void 0===t.animation.easingFunction&&(t.animation.easingFunction="easeInOutQuad"),this.animateView(t)}},{key:"animateView",value:function(t){if(void 0!==t){this.animationEasingFunction=t.animation.easingFunction,this.releaseNode(),!0===t.locked&&(this.lockedOnNodeId=t.lockedOnNode,this.lockedOnNodeOffset=t.offset),0!=this.easingTime&&this._transitionRedraw(!0),this.sourceScale=this.body.view.scale,this.sourceTranslation=this.body.view.translation,this.targetScale=t.scale,this.body.view.scale=this.targetScale;var e=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),i={x:e.x-t.position.x,y:e.y-t.position.y};this.targetTranslation={x:this.sourceTranslation.x+i.x*this.targetScale+t.offset.x,y:this.sourceTranslation.y+i.y*this.targetScale+t.offset.y},0===t.animation.duration?void 0!=this.lockedOnNodeId?(this.viewFunction=this._lockedRedraw.bind(this),this.body.emitter.on("initRedraw",this.viewFunction)):(this.body.view.scale=this.targetScale,this.body.view.translation=this.targetTranslation,this.body.emitter.emit("_requestRedraw")):(this.animationSpeed=1/(60*t.animation.duration*.001)||1/60,this.animationEasingFunction=t.animation.easingFunction,this.viewFunction=this._transitionRedraw.bind(this),this.body.emitter.on("initRedraw",this.viewFunction),this.body.emitter.emit("_startRendering"))}}},{key:"_lockedRedraw",value:function(){var t={x:this.body.nodes[this.lockedOnNodeId].x,y:this.body.nodes[this.lockedOnNodeId].y},e=this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight}),i={x:e.x-t.x,y:e.y-t.y},o=this.body.view.translation,n={x:o.x+i.x*this.body.view.scale+this.lockedOnNodeOffset.x,y:o.y+i.y*this.body.view.scale+this.lockedOnNodeOffset.y};this.body.view.translation=n}},{key:"releaseNode",value:function(){void 0!==this.lockedOnNodeId&&void 0!==this.viewFunction&&(this.body.emitter.off("initRedraw",this.viewFunction),this.lockedOnNodeId=void 0,this.lockedOnNodeOffset=void 0)}},{key:"_transitionRedraw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this.easingTime+=this.animationSpeed,this.easingTime=!0===t?1:this.easingTime;var e=h.easingFunctions[this.animationEasingFunction](this.easingTime);this.body.view.scale=this.sourceScale+(this.targetScale-this.sourceScale)*e,this.body.view.translation={x:this.sourceTranslation.x+(this.targetTranslation.x-this.sourceTranslation.x)*e,y:this.sourceTranslation.y+(this.targetTranslation.y-this.sourceTranslation.y)*e},this.easingTime>=1&&(this.body.emitter.off("initRedraw",this.viewFunction),this.easingTime=0,void 0!=this.lockedOnNodeId&&(this.viewFunction=this._lockedRedraw.bind(this),this.body.emitter.on("initRedraw",this.viewFunction)),this.body.emitter.emit("animationFinished"))}},{key:"getScale",value:function(){return this.body.view.scale}},{key:"getViewPosition",value:function(){return this.canvas.DOMtoCanvas({x:.5*this.canvas.frame.canvas.clientWidth,y:.5*this.canvas.frame.canvas.clientHeight})}}]),t}();e.default=l},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=i(2),d=i(233).default,l=i(104).default,u=function(){function t(e,i,o){(0,s.default)(this,t),this.body=e,this.canvas=i,this.selectionHandler=o,this.navigationHandler=new d(e,i),this.body.eventListeners.onTap=this.onTap.bind(this),this.body.eventListeners.onTouch=this.onTouch.bind(this),this.body.eventListeners.onDoubleTap=this.onDoubleTap.bind(this),this.body.eventListeners.onHold=this.onHold.bind(this),this.body.eventListeners.onDragStart=this.onDragStart.bind(this),this.body.eventListeners.onDrag=this.onDrag.bind(this),this.body.eventListeners.onDragEnd=this.onDragEnd.bind(this),this.body.eventListeners.onMouseWheel=this.onMouseWheel.bind(this),this.body.eventListeners.onPinch=this.onPinch.bind(this),this.body.eventListeners.onMouseMove=this.onMouseMove.bind(this),this.body.eventListeners.onRelease=this.onRelease.bind(this),this.body.eventListeners.onContext=this.onContext.bind(this),this.touchTime=0,this.drag={},this.pinch={},this.popup=void 0,this.popupObj=void 0,this.popupTimer=void 0,this.body.functions.getPointer=this.getPointer.bind(this),this.options={},this.defaultOptions={dragNodes:!0,dragView:!0,hover:!1,keyboard:{enabled:!1,speed:{x:10,y:10,zoom:.02},bindToWindow:!0},navigationButtons:!1,tooltipDelay:300,zoomView:!0},h.extend(this.options,this.defaultOptions),this.bindEventListeners()}return(0,a.default)(t,[{key:"bindEventListeners",value:function(){var t=this;this.body.emitter.on("destroy",function(){clearTimeout(t.popupTimer),delete t.body.functions.getPointer})}},{key:"setOptions",value:function(t){if(void 0!==t){var e=["hideEdgesOnDrag","hideNodesOnDrag","keyboard","multiselect","selectable","selectConnectedEdges"];h.selectiveNotDeepExtend(e,this.options,t),h.mergeOptions(this.options,t,"keyboard"),t.tooltip&&(h.extend(this.options.tooltip,t.tooltip),t.tooltip.color&&(this.options.tooltip.color=h.parseColor(t.tooltip.color)))}this.navigationHandler.setOptions(this.options)}},{key:"getPointer",value:function(t){return{x:t.x-h.getAbsoluteLeft(this.canvas.frame.canvas),y:t.y-h.getAbsoluteTop(this.canvas.frame.canvas)}}},{key:"onTouch",value:function(t){(new Date).valueOf()-this.touchTime>50&&(this.drag.pointer=this.getPointer(t.center),this.drag.pinched=!1,this.pinch.scale=this.body.view.scale,this.touchTime=(new Date).valueOf())}},{key:"onTap",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect&&(t.changedPointers[0].ctrlKey||t.changedPointers[0].metaKey);this.checkSelectionChanges(e,t,i),this.selectionHandler._generateClickEvent("click",t,e)}},{key:"onDoubleTap",value:function(t){var e=this.getPointer(t.center);this.selectionHandler._generateClickEvent("doubleClick",t,e)}},{key:"onHold",value:function(t){var e=this.getPointer(t.center),i=this.selectionHandler.options.multiselect;this.checkSelectionChanges(e,t,i),this.selectionHandler._generateClickEvent("click",t,e),this.selectionHandler._generateClickEvent("hold",t,e)}},{key:"onRelease",value:function(t){if((new Date).valueOf()-this.touchTime>10){var e=this.getPointer(t.center);this.selectionHandler._generateClickEvent("release",t,e),this.touchTime=(new Date).valueOf()}}},{key:"onContext",value:function(t){var e=this.getPointer({x:t.clientX,y:t.clientY});this.selectionHandler._generateClickEvent("oncontext",t,e)}},{key:"checkSelectionChanges",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=this.selectionHandler.getSelection(),n=!1;n=!0===i?this.selectionHandler.selectAdditionalOnPoint(t):this.selectionHandler.selectOnPoint(t);var s=this.selectionHandler.getSelection(),r=this._determineDifference(o,s),a=this._determineDifference(s,o);r.edges.length>0&&(this.selectionHandler._generateClickEvent("deselectEdge",e,t,o),n=!0),r.nodes.length>0&&(this.selectionHandler._generateClickEvent("deselectNode",e,t,o),n=!0),a.nodes.length>0&&(this.selectionHandler._generateClickEvent("selectNode",e,t),n=!0),a.edges.length>0&&(this.selectionHandler._generateClickEvent("selectEdge",e,t),n=!0),!0===n&&this.selectionHandler._generateClickEvent("select",e,t)}},{key:"_determineDifference",value:function(t,e){var i=function(t,e){for(var i=[],o=0;o10&&(t=10);var o=void 0;void 0!==this.drag&&!0===this.drag.dragging&&(o=this.canvas.DOMtoCanvas(this.drag.pointer));var n=this.body.view.translation,s=t/i,r=(1-s)*e.x+n.x*s,a=(1-s)*e.y+n.y*s;if(this.body.view.scale=t,this.body.view.translation={x:r,y:a},void 0!=o){var h=this.canvas.canvasToDOM(o);this.drag.pointer.x=h.x,this.drag.pointer.y=h.y}this.body.emitter.emit("_requestRedraw"),i0&&(this.popupObj=h[u[u.length-1]],s=!0)}if(void 0===this.popupObj&&!1===s){for(var p=this.body.edgeIndices,f=this.body.edges,m=void 0,v=[],g=0;g0&&(this.popupObj=f[v[v.length-1]],r="edge")}void 0!==this.popupObj?this.popupObj.id!==n&&(void 0===this.popup&&(this.popup=new l(this.canvas.frame)),this.popup.popupTargetType=r,this.popup.popupTargetId=this.popupObj.id,this.popup.setPosition(t.x+3,t.y-5),this.popup.setText(this.popupObj.getTitle()),this.popup.show(),this.body.emitter.emit("showPopup",this.popupObj.id)):void 0!==this.popup&&(this.popup.hide(),this.body.emitter.emit("hidePopup"))}},{key:"_checkHidePopup",value:function(t){var e=this.selectionHandler._pointerToPositionObject(t),i=!1;if("node"===this.popup.popupTargetType){if(void 0!==this.body.nodes[this.popup.popupTargetId]&&!0===(i=this.body.nodes[this.popup.popupTargetId].isOverlappingWith(e))){var o=this.selectionHandler.getNodeAt(t);i=void 0!==o&&o.id===this.popup.popupTargetId}}else void 0===this.selectionHandler.getNodeAt(t)&&void 0!==this.body.edges[this.popup.popupTargetId]&&(i=this.body.edges[this.popup.popupTargetId].isOverlappingWith(e));!1===i&&(this.popupObj=void 0,this.popup.hide(),this.body.emitter.emit("hidePopup"))}}]),t}();e.default=u},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=i(10),d=i(37),l=i(35),u=function(){function t(e,i){var o=this;(0,s.default)(this,t),this.body=e,this.canvas=i,this.iconsCreated=!1,this.navigationHammers=[],this.boundFunctions={},this.touchTime=0,this.activated=!1,this.body.emitter.on("activate",function(){o.activated=!0,o.configureKeyboardBindings()}),this.body.emitter.on("deactivate",function(){o.activated=!1,o.configureKeyboardBindings()}),this.body.emitter.on("destroy",function(){void 0!==o.keycharm&&o.keycharm.destroy()}),this.options={}}return(0,a.default)(t,[{key:"setOptions",value:function(t){void 0!==t&&(this.options=t,this.create())}},{key:"create",value:function(){!0===this.options.navigationButtons?!1===this.iconsCreated&&this.loadNavigationElements():!0===this.iconsCreated&&this.cleanNavigation(),this.configureKeyboardBindings()}},{key:"cleanNavigation",value:function(){if(0!=this.navigationHammers.length){for(var t=0;t700&&(this.body.emitter.emit("fit",{duration:700}),this.touchTime=(new Date).valueOf())}},{key:"_stopMovement",value:function(){for(var t in this.boundFunctions)this.boundFunctions.hasOwnProperty(t)&&(this.body.emitter.off("initRedraw",this.boundFunctions[t]),this.body.emitter.emit("_stopRendering"));this.boundFunctions={}}},{key:"_moveUp",value:function(){this.body.view.translation.y+=this.options.keyboard.speed.y}},{key:"_moveDown",value:function(){this.body.view.translation.y-=this.options.keyboard.speed.y}},{key:"_moveLeft",value:function(){this.body.view.translation.x+=this.options.keyboard.speed.x}},{key:"_moveRight",value:function(){this.body.view.translation.x-=this.options.keyboard.speed.x}},{key:"_zoomIn",value:function(){var t=this.body.view.scale,e=this.body.view.scale*(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,o=e/t,n=(1-o)*this.canvas.canvasViewCenter.x+i.x*o,s=(1-o)*this.canvas.canvasViewCenter.y+i.y*o;this.body.view.scale=e,this.body.view.translation={x:n,y:s},this.body.emitter.emit("zoom",{direction:"+",scale:this.body.view.scale,pointer:null})}},{key:"_zoomOut",value:function(){var t=this.body.view.scale,e=this.body.view.scale/(1+this.options.keyboard.speed.zoom),i=this.body.view.translation,o=e/t,n=(1-o)*this.canvas.canvasViewCenter.x+i.x*o,s=(1-o)*this.canvas.canvasViewCenter.y+i.y*o;this.body.view.scale=e,this.body.view.translation={x:n,y:s},this.body.emitter.emit("zoom",{direction:"-",scale:this.body.view.scale,pointer:null})}},{key:"configureKeyboardBindings",value:function(){var t=this;void 0!==this.keycharm&&this.keycharm.destroy(),!0===this.options.keyboard.enabled&&(!0===this.options.keyboard.bindToWindow?this.keycharm=l({container:window,preventDefault:!0}):this.keycharm=l({container:this.canvas.frame,preventDefault:!0}),this.keycharm.reset(),!0===this.activated&&(this.keycharm.bind("up",function(){t.bindToRedraw("_moveUp")},"keydown"),this.keycharm.bind("down",function(){t.bindToRedraw("_moveDown")},"keydown"),this.keycharm.bind("left",function(){t.bindToRedraw("_moveLeft")},"keydown"),this.keycharm.bind("right",function(){t.bindToRedraw("_moveRight")},"keydown"),this.keycharm.bind("=",function(){t.bindToRedraw("_zoomIn")},"keydown"),this.keycharm.bind("num+",function(){t.bindToRedraw("_zoomIn")},"keydown"),this.keycharm.bind("num-",function(){t.bindToRedraw("_zoomOut")},"keydown"),this.keycharm.bind("-",function(){t.bindToRedraw("_zoomOut")},"keydown"),this.keycharm.bind("[",function(){t.bindToRedraw("_zoomOut")},"keydown"),this.keycharm.bind("]",function(){t.bindToRedraw("_zoomIn")},"keydown"),this.keycharm.bind("pageup",function(){t.bindToRedraw("_zoomIn")},"keydown"),this.keycharm.bind("pagedown",function(){t.bindToRedraw("_zoomOut")},"keydown"),this.keycharm.bind("up",function(){t.unbindFromRedraw("_moveUp")},"keyup"),this.keycharm.bind("down",function(){t.unbindFromRedraw("_moveDown")},"keyup"),this.keycharm.bind("left",function(){t.unbindFromRedraw("_moveLeft")},"keyup"),this.keycharm.bind("right",function(){t.unbindFromRedraw("_moveRight")},"keyup"),this.keycharm.bind("=",function(){t.unbindFromRedraw("_zoomIn")},"keyup"),this.keycharm.bind("num+",function(){t.unbindFromRedraw("_zoomIn")},"keyup"),this.keycharm.bind("num-",function(){t.unbindFromRedraw("_zoomOut")},"keyup"),this.keycharm.bind("-",function(){t.unbindFromRedraw("_zoomOut")},"keyup"),this.keycharm.bind("[",function(){t.unbindFromRedraw("_zoomOut")},"keyup"),this.keycharm.bind("]",function(){t.unbindFromRedraw("_zoomIn")},"keyup"),this.keycharm.bind("pageup",function(){t.unbindFromRedraw("_zoomIn")},"keyup"),this.keycharm.bind("pagedown",function(){t.unbindFromRedraw("_zoomOut")},"keyup")))}}]),t}();e.default=u},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(0),s=o(n),r=i(1),a=o(r),h=i(47).default,d=i(74).default,l=i(2),u=function(){function t(e,i){var o=this;(0,s.default)(this,t),this.body=e,this.canvas=i,this.selectionObj={nodes:[],edges:[]},this.hoverObj={nodes:{},edges:{}},this.options={},this.defaultOptions={multiselect:!1,selectable:!0,selectConnectedEdges:!0,hoverConnectedEdges:!0},l.extend(this.options,this.defaultOptions),this.body.emitter.on("_dataChanged",function(){o.updateSelection()})}return(0,a.default)(t,[{key:"setOptions",value:function(t){if(void 0!==t){var e=["multiselect","hoverConnectedEdges","selectable","selectConnectedEdges"];l.selectiveDeepExtend(e,this.options,t)}}},{key:"selectOnPoint",value:function(t){var e=!1;if(!0===this.options.selectable){var i=this.getNodeAt(t)||this.getEdgeAt(t);this.unselectAll(),void 0!==i&&(e=this.selectObject(i)),this.body.emitter.emit("_requestRedraw")}return e}},{key:"selectAdditionalOnPoint",value:function(t){var e=!1;if(!0===this.options.selectable){var i=this.getNodeAt(t)||this.getEdgeAt(t);void 0!==i&&(e=!0,!0===i.isSelected()?this.deselectObject(i):this.selectObject(i),this.body.emitter.emit("_requestRedraw"))}return e}},{key:"_initBaseEvent",value:function(t,e){var i={};return i.pointer={DOM:{x:e.x,y:e.y},canvas:this.canvas.DOMtoCanvas(e)},i.event=t,i}},{key:"_generateClickEvent",value:function(t,e,i,o){var n=arguments.length>4&&void 0!==arguments[4]&&arguments[4],s=this._initBaseEvent(e,i);if(!0===n)s.nodes=[],s.edges=[];else{var r=this.getSelection();s.nodes=r.nodes,s.edges=r.edges}void 0!==o&&(s.previousSelection=o),"click"==t&&(s.items=this.getClickedItems(i)),this.body.emitter.emit(t,s)}},{key:"selectObject",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.selectConnectedEdges;return void 0!==t&&(t instanceof h&&!0===e&&this._selectConnectedEdges(t),t.select(),this._addToSelection(t),!0)}},{key:"deselectObject",value:function(t){!0===t.isSelected()&&(t.selected=!1,this._removeFromSelection(t))}},{key:"_getAllNodesOverlappingWith",value:function(t){for(var e=[],i=this.body.nodes,o=0;o1&&void 0!==arguments[1])||arguments[1],i=this._pointerToPositionObject(t),o=this._getAllNodesOverlappingWith(i);return o.length>0?!0===e?this.body.nodes[o[o.length-1]]:o[o.length-1]:void 0}},{key:"_getEdgesOverlappingWith",value:function(t,e){for(var i=this.body.edges,o=0;o1&&void 0!==arguments[1])||arguments[1],i=this.canvas.DOMtoCanvas(t),o=10,n=null,s=this.body.edges,r=0;r1)return!0;return!1}},{key:"_selectConnectedEdges",value:function(t){for(var e=0;e1&&void 0!==arguments[1]?arguments[1]:{},i=void 0,o=void 0 +;if(!t||!t.nodes&&!t.edges)throw"Selection must be an object with nodes and/or edges properties";if((e.unselectAll||void 0===e.unselectAll)&&this.unselectAll(),t.nodes)for(i=0;i1&&void 0!==arguments[1])||arguments[1];if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({nodes:t},{highlightEdges:e})}},{key:"selectEdges",value:function(t){if(!t||void 0===t.length)throw"Selection must be an array with ids";this.setSelection({edges:t})}},{key:"updateSelection",value:function(){for(var t in this.selectionObj.nodes)this.selectionObj.nodes.hasOwnProperty(t)&&(this.body.nodes.hasOwnProperty(t)||delete this.selectionObj.nodes[t]);for(var e in this.selectionObj.edges)this.selectionObj.edges.hasOwnProperty(e)&&(this.body.edges.hasOwnProperty(e)||delete this.selectionObj.edges[e])}},{key:"getClickedItems",value:function(t){for(var e=this.canvas.DOMtoCanvas(t),i=[],o=this.body.nodeIndices,n=this.body.nodes,s=o.length-1;s>=0;s--){var r=n[o[s]],a=r.getItemsOnPoint(e);i.push.apply(i,a)}for(var h=this.body.edgeIndices,d=this.body.edges,l=h.length-1;l>=0;l--){var u=d[h[l]],c=u.getItemsOnPoint(e);i.push.apply(i,c)}return i}}]),t}();e.default=u},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(30),s=o(n),r=i(6),a=o(r),h=i(8),d=o(h),l=i(0),u=o(l),c=i(1),p=o(c),f=i(2),m=i(76).default,v=i(236),g=v.HorizontalStrategy,y=v.VerticalStrategy,b=function(){function t(){(0,u.default)(this,t),this.childrenReference={},this.parentReference={},this.trees={},this.distributionOrdering={},this.levels={},this.distributionIndex={},this.isTree=!1,this.treeIndex=-1}return(0,p.default)(t,[{key:"addRelation",value:function(t,e){void 0===this.childrenReference[t]&&(this.childrenReference[t]=[]),this.childrenReference[t].push(e),void 0===this.parentReference[e]&&(this.parentReference[e]=[]),this.parentReference[e].push(t)}},{key:"checkIfTree",value:function(){for(var t in this.parentReference)if(this.parentReference[t].length>1)return void(this.isTree=!1);this.isTree=!0}},{key:"numTrees",value:function(){return this.treeIndex+1}},{key:"setTreeIndex",value:function(t,e){void 0!==e&&void 0===this.trees[t.id]&&(this.trees[t.id]=e,this.treeIndex=Math.max(e,this.treeIndex))}},{key:"ensureLevel",value:function(t){void 0===this.levels[t]&&(this.levels[t]=0)}},{key:"getMaxLevel",value:function(t){var e=this,i={};return function t(o){if(void 0!==i[o])return i[o];var n=e.levels[o];if(e.childrenReference[o]){var s=e.childrenReference[o];if(s.length>0)for(var r=0;r0&&(i.levelSeparation*=-1):i.levelSeparation<0&&(i.levelSeparation*=-1),this.setDirectionStrategy(),this.body.emitter.emit("_resetHierarchicalLayout"),this.adaptAllOptionsForHierarchicalLayout(e);if(!0===o)return this.body.emitter.emit("refresh"),f.deepExtend(e,this.optionsBackup)}return e}},{key:"adaptAllOptionsForHierarchicalLayout",value:function(t){if(!0===this.options.hierarchical.enabled){var e=this.optionsBackup.physics;void 0===t.physics||!0===t.physics?(t.physics={enabled:void 0===e.enabled||e.enabled,solver:"hierarchicalRepulsion"},e.enabled=void 0===e.enabled||e.enabled,e.solver=e.solver||"barnesHut"):"object"===(0,a.default)(t.physics)?(e.enabled=void 0===t.physics.enabled||t.physics.enabled,e.solver=t.physics.solver||"barnesHut",t.physics.solver="hierarchicalRepulsion"):!1!==t.physics&&(e.solver="barnesHut",t.physics={solver:"hierarchicalRepulsion"});var i=this.direction.curveType();if(void 0===t.edges)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges={smooth:!1};else if(void 0===t.edges.smooth)this.optionsBackup.edges={smooth:{enabled:!0,type:"dynamic"}},t.edges.smooth=!1;else if("boolean"==typeof t.edges.smooth)this.optionsBackup.edges={smooth:t.edges.smooth},t.edges.smooth={enabled:t.edges.smooth,type:i};else{var o=t.edges.smooth;void 0!==o.type&&"dynamic"!==o.type&&(i=o.type),this.optionsBackup.edges={smooth:void 0===o.enabled||o.enabled,type:void 0===o.type?"dynamic":o.type,roundness:void 0===o.roundness?.5:o.roundness,forceDirection:void 0!==o.forceDirection&&o.forceDirection},t.edges.smooth={enabled:void 0===o.enabled||o.enabled,type:i,roundness:void 0===o.roundness?.5:o.roundness,forceDirection:void 0!==o.forceDirection&&o.forceDirection}}this.body.emitter.emit("_forceDisableDynamicCurves",i)}return t}},{key:"seededRandom",value:function(){var t=1e4*Math.sin(this.randomSeed++);return t-Math.floor(t)}},{key:"positionInitially",value:function(t){if(!0!==this.options.hierarchical.enabled){this.randomSeed=this.initialRandomSeed;for(var e=t.length+50,i=0;i150){for(var s=t.length;t.length>150&&o<=10;){o+=1;var r=t.length;o%3==0?this.body.modules.clustering.clusterBridges(n):this.body.modules.clustering.clusterOutliers(n);if(r==t.length&&o%3!=0)return this._declusterAll(),this.body.emitter.emit("_layoutFailed"),void console.info("This network could not be positioned by this version of the improved layout algorithm. Please disable improvedLayout for better performance.")}this.body.modules.kamadaKawai.setOptions({springLength:Math.max(150,2*s)})}o>10&&console.info("The clustering didn't succeed within the amount of interations allowed, progressing with partial result."),this.body.modules.kamadaKawai.solve(t,this.body.edgeIndices,!0),this._shiftToCenter();for(var a=0;a0){var t=void 0,e=void 0,i=!1,o=!1;this.lastNodeOnLevel={},this.hierarchical=new b;for(e in this.body.nodes)this.body.nodes.hasOwnProperty(e)&&(t=this.body.nodes[e],void 0!==t.options.level?(i=!0,this.hierarchical.levels[e]=t.options.level):o=!0);if(!0===o&&!0===i)throw new Error("To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.");if(!0===o){var n=this.options.hierarchical.sortMethod;"hubsize"===n?this._determineLevelsByHubsize():"directed"===n?this._determineLevelsDirected():"custom"===n&&this._determineLevelsCustomCallback()}for(var s in this.body.nodes)this.body.nodes.hasOwnProperty(s)&&this.hierarchical.ensureLevel(s);var r=this._getDistribution();this._generateMap(),this._placeNodesByHierarchy(r),this._condenseHierarchy(),this._shiftToCenter()}}},{key:"_condenseHierarchy",value:function(){var t=this,e=!1,i={},o=function(e,i){var o=t.hierarchical.trees;for(var n in o)o.hasOwnProperty(n)&&o[n]===e&&t.direction.shift(n,i)},n=function(){for(var e=[],i=0;i0)for(var s=0;s1&&void 0!==arguments[1]?arguments[1]:1e9,o=1e9,n=1e9,r=1e9,a=-1e9;for(var h in e)if(e.hasOwnProperty(h)){var d=t.body.nodes[h],l=t.hierarchical.levels[d.id],u=t.direction.getPosition(d),c=t._getSpaceAroundNode(d,e),p=(0,s.default)(c,2),f=p[0],m=p[1];o=Math.min(f,o),n=Math.min(m,n),l<=i&&(r=Math.min(u,r),a=Math.max(u,a))}return[r,a,o,n]},h=function(e,i){var o=t.hierarchical.getMaxLevel(e.id),n=t.hierarchical.getMaxLevel(i.id);return Math.min(o,n)},d=function(e,i,o){for(var n=t.hierarchical,s=0;s1)for(var h=0;h2&&void 0!==arguments[2]&&arguments[2],s=t.direction.getPosition(i),d=t.direction.getPosition(o),l=Math.abs(d-s),u=t.options.hierarchical.nodeSpacing;if(l>u){var c={},p={};r(i,c),r(o,p);var f=h(i,o),m=a(c,f),v=a(p,f),g=m[1],y=v[0],b=v[2];if(Math.abs(g-y)>u){var _=g-y+u;_<-b+u&&(_=-b+u),_<0&&(t._shiftBlock(o.id,_),e=!0,!0===n&&t._centerParent(o))}}},u=function(o,n){for(var h=n.id,d=n.edges,l=t.hierarchical.levels[n.id],u=t.options.hierarchical.levelSeparation*t.options.hierarchical.levelSeparation,c={},p=[],f=0;f0?p=Math.min(c,u-t.options.hierarchical.nodeSpacing):c<0&&(p=-Math.min(-c,l-t.options.hierarchical.nodeSpacing)),0!=p&&(t._shiftBlock(n.id,p),e=!0)}(_),_=b(o,d),function(i){var o=t.direction.getPosition(n),r=t._getSpaceAroundNode(n),a=(0,s.default)(r,2),h=a[0],d=a[1],l=i-o,u=o;l>0?u=Math.min(o+(d-t.options.hierarchical.nodeSpacing),i):l<0&&(u=Math.max(o-(h-t.options.hierarchical.nodeSpacing),i)),u!==o&&(t.direction.setPosition(n,u),e=!0)}(_)};!0===this.options.hierarchical.blockShifting&&(function(i){var o=t.hierarchical.getLevels();o=o.reverse();for(var n=0;n0&&Math.abs(p)0&&(a=this.direction.getPosition(i[n-1])+r),this.direction.setPosition(s,a,e),this._validatePositionAndContinue(s,e,a),o++}}}}},{key:"_placeBranchNodes",value:function(t,e){var i=this.hierarchical.childrenReference[t];if(void 0!==i){for(var o=[],n=0;ne&&void 0===this.positionedNodes[r.id]))return;var h=this.options.hierarchical.nodeSpacing,d=void 0;d=0===s?this.direction.getPosition(this.body.nodes[t]):this.direction.getPosition(o[s-1])+h,this.direction.setPosition(r,d,a),this._validatePositionAndContinue(r,a,d)}var l=this._getCenterPosition(o);this.direction.setPosition(this.body.nodes[t],l,e)}}},{key:"_validatePositionAndContinue",value:function(t,e,i){if(this.hierarchical.isTree){if(void 0!==this.lastNodeOnLevel[e]){var o=this.direction.getPosition(this.body.nodes[this.lastNodeOnLevel[e]]);if(i-ot.hierarchical.levels[e.id]&&t.hierarchical.addRelation(e.id,i.id)};this._crawlNetwork(e),this.hierarchical.checkIfTree()}},{key:"_crawlNetwork",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){},i=arguments[1],o={},n=function i(n,s){if(void 0===o[n.id]){t.hierarchical.setTreeIndex(n,s),o[n.id]=!0;for(var r=void 0,a=t._getActiveEdges(n),h=0;h2&&void 0!==arguments[2]?arguments[2]:void 0;this.fake_use(t,e,i),this.abstract()}},{key:"getTreeSize",value:function(t){return this.fake_use(t),this.abstract()}},{key:"sort",value:function(t){this.fake_use(t),this.abstract()}},{key:"fix",value:function(t,e){this.fake_use(t,e),this.abstract()}},{key:"shift",value:function(t,e){this.fake_use(t,e),this.abstract()}}]),t}(),m=function(t){function e(t){(0,u.default)(this,e);var i=(0,a.default)(this,(e.__proto__||(0,s.default)(e)).call(this));return i.layout=t,i}return(0,d.default)(e,t),(0,p.default)(e,[{key:"curveType",value:function(){return"horizontal"}},{key:"getPosition",value:function(t){return t.x}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.x=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_x,max:e.max_x}}},{key:"sort",value:function(t){t.sort(function(t,e){return void 0===t.x||void 0===e.x?0:t.x-e.x})}},{key:"fix",value:function(t,e){t.y=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.y=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].x+=e}}]),e}(f),v=function(t){function e(t){(0,u.default)(this,e);var i=(0,a.default)(this,(e.__proto__||(0,s.default)(e)).call(this));return i.layout=t,i}return(0,d.default)(e,t),(0,p.default)(e,[{key:"curveType",value:function(){return"vertical"}},{key:"getPosition",value:function(t){return t.y}},{key:"setPosition",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0;void 0!==i&&this.layout.hierarchical.addToOrdering(t,i),t.y=e}},{key:"getTreeSize",value:function(t){var e=this.layout.hierarchical.getTreeSize(this.layout.body.nodes,t);return{min:e.min_y,max:e.max_y}}},{key:"sort",value:function(t){t.sort(function(t,e){return void 0===t.y||void 0===e.y?0:t.y-e.y})}},{key:"fix",value:function(t,e){t.x=this.layout.options.hierarchical.levelSeparation*e,t.options.fixed.x=!0}},{key:"shift",value:function(t,e){this.layout.body.nodes[t].y+=e}}]),e}(f);e.HorizontalStrategy=v,e.VerticalStrategy=m},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(8),s=o(n),r=i(19),a=o(r),h=i(6),d=o(h),l=i(0),u=o(l),c=i(1),p=o(c),f=i(2),m=i(10),v=i(37),g=function(){function t(e,i,o){var n=this;(0,u.default)(this,t),this.body=e,this.canvas=i,this.selectionHandler=o,this.editMode=!1,this.manipulationDiv=void 0,this.editModeDiv=void 0,this.closeDiv=void 0,this.manipulationHammers=[],this.temporaryUIFunctions={},this.temporaryEventFunctions=[],this.touchTime=0,this.temporaryIds={nodes:[],edges:[]},this.guiEnabled=!1,this.inMode=!1,this.selectedControlNode=void 0,this.options={},this.defaultOptions={enabled:!1,initiallyActive:!1,addNode:!0,addEdge:!0,editNode:void 0,editEdge:!0,deleteNode:!0,deleteEdge:!0,controlNodeStyle:{shape:"dot",size:6,color:{background:"#ff0000",border:"#3c3c3c",highlight:{background:"#07f968",border:"#3c3c3c"}},borderWidth:2,borderWidthSelected:2}},f.extend(this.options,this.defaultOptions),this.body.emitter.on("destroy",function(){n._clean()}),this.body.emitter.on("_dataChanged",this._restore.bind(this)),this.body.emitter.on("_resetData",this._restore.bind(this))}return(0,p.default)(t,[{key:"_restore",value:function(){!1!==this.inMode&&(!0===this.options.initiallyActive?this.enableEditMode():this.disableEditMode())}},{key:"setOptions",value:function(t,e,i){void 0!==e&&(void 0!==e.locale?this.options.locale=e.locale:this.options.locale=i.locale,void 0!==e.locales?this.options.locales=e.locales:this.options.locales=i.locales),void 0!==t&&("boolean"==typeof t?this.options.enabled=t:(this.options.enabled=!0,f.deepExtend(this.options,t)),!0===this.options.initiallyActive&&(this.editMode=!0),this._setup())}},{key:"toggleEditMode",value:function(){!0===this.editMode?this.disableEditMode():this.enableEditMode()}},{key:"enableEditMode",value:function(){this.editMode=!0,this._clean(),!0===this.guiEnabled&&(this.manipulationDiv.style.display="block",this.closeDiv.style.display="block",this.editModeDiv.style.display="none",this.showManipulatorToolbar())}},{key:"disableEditMode",value:function(){this.editMode=!1,this._clean(),!0===this.guiEnabled&&(this.manipulationDiv.style.display="none",this.closeDiv.style.display="none",this.editModeDiv.style.display="block",this._createEditButton())}},{key:"showManipulatorToolbar",value:function(){if(this._clean(),this.manipulationDOM={},!0===this.guiEnabled){this.editMode=!0,this.manipulationDiv.style.display="block",this.closeDiv.style.display="block";var t=this.selectionHandler._getSelectedNodeCount(),e=this.selectionHandler._getSelectedEdgeCount(),i=t+e,o=this.options.locales[this.options.locale],n=!1;!1!==this.options.addNode&&(this._createAddNodeButton(o),n=!0),!1!==this.options.addEdge&&(!0===n?this._createSeperator(1):n=!0,this._createAddEdgeButton(o)),1===t&&"function"==typeof this.options.editNode?(!0===n?this._createSeperator(2):n=!0,this._createEditNodeButton(o)):1===e&&0===t&&!1!==this.options.editEdge&&(!0===n?this._createSeperator(3):n=!0,this._createEditEdgeButton(o)),0!==i&&(t>0&&!1!==this.options.deleteNode?(!0===n&&this._createSeperator(4),this._createDeleteButton(o)):0===t&&!1!==this.options.deleteEdge&&(!0===n&&this._createSeperator(4),this._createDeleteButton(o))),this._bindHammerToDiv(this.closeDiv,this.toggleEditMode.bind(this)),this._temporaryBindEvent("select",this.showManipulatorToolbar.bind(this))}this.body.emitter.emit("_redraw")}},{key:"addNodeMode",value:function(){if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addNode",!0===this.guiEnabled){var t=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(t),this._createSeperator(),this._createDescription(t.addDescription||this.options.locales.en.addDescription),this._bindHammerToDiv(this.closeDiv,this.toggleEditMode.bind(this))}this._temporaryBindEvent("click",this._performAddNode.bind(this))}},{key:"editNode",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean();var e=this.selectionHandler._getSelectedNode();if(void 0!==e){if(this.inMode="editNode","function"!=typeof this.options.editNode)throw new Error("No function has been configured to handle the editing of nodes.");if(!0!==e.isCluster){var i=f.deepExtend({},e.options,!1);if(i.x=e.x,i.y=e.y,2!==this.options.editNode.length)throw new Error("The function for edit does not support two arguments (data, callback)");this.options.editNode(i,function(e){null!==e&&void 0!==e&&"editNode"===t.inMode&&t.body.data.nodes.getDataSet().update(e),t.showManipulatorToolbar()})}else alert(this.options.locales[this.options.locale].editClusterError||this.options.locales.en.editClusterError)}else this.showManipulatorToolbar()}},{key:"addEdgeMode",value:function(){if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="addEdge",!0===this.guiEnabled){var t=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(t),this._createSeperator(),this._createDescription(t.edgeDescription||this.options.locales.en.edgeDescription),this._bindHammerToDiv(this.closeDiv,this.toggleEditMode.bind(this))}this._temporaryBindUI("onTouch",this._handleConnect.bind(this)),this._temporaryBindUI("onDragEnd",this._finishConnect.bind(this)),this._temporaryBindUI("onDrag",this._dragControlNode.bind(this)),this._temporaryBindUI("onRelease",this._finishConnect.bind(this)),this._temporaryBindUI("onDragStart",this._dragStartEdge.bind(this)),this._temporaryBindUI("onHold",function(){})}},{key:"editEdgeMode",value:function(){if(!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="editEdge","object"===(0,d.default)(this.options.editEdge)&&"function"==typeof this.options.editEdge.editWithoutDrag&&(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdges()[0],void 0!==this.edgeBeingEditedId)){var t=this.body.edges[this.edgeBeingEditedId];return void this._performEditEdge(t.from,t.to)}if(!0===this.guiEnabled){var e=this.options.locales[this.options.locale];this.manipulationDOM={},this._createBackButton(e),this._createSeperator(),this._createDescription(e.editEdgeDescription||this.options.locales.en.editEdgeDescription),this._bindHammerToDiv(this.closeDiv,this.toggleEditMode.bind(this))}if(this.edgeBeingEditedId=this.selectionHandler.getSelectedEdges()[0],void 0!==this.edgeBeingEditedId){var i=this.body.edges[this.edgeBeingEditedId],o=this._getNewTargetNode(i.from.x,i.from.y),n=this._getNewTargetNode(i.to.x,i.to.y);this.temporaryIds.nodes.push(o.id),this.temporaryIds.nodes.push(n.id),this.body.nodes[o.id]=o,this.body.nodeIndices.push(o.id),this.body.nodes[n.id]=n,this.body.nodeIndices.push(n.id),this._temporaryBindUI("onTouch",this._controlNodeTouch.bind(this)),this._temporaryBindUI("onTap",function(){}),this._temporaryBindUI("onHold",function(){}),this._temporaryBindUI("onDragStart",this._controlNodeDragStart.bind(this)),this._temporaryBindUI("onDrag",this._controlNodeDrag.bind(this)),this._temporaryBindUI("onDragEnd",this._controlNodeDragEnd.bind(this)),this._temporaryBindUI("onMouseMove",function(){}),this._temporaryBindEvent("beforeDrawing",function(t){var e=i.edgeType.findBorderPositions(t);!1===o.selected&&(o.x=e.from.x,o.y=e.from.y),!1===n.selected&&(n.x=e.to.x,n.y=e.to.y)}),this.body.emitter.emit("_redraw")}else this.showManipulatorToolbar()}},{key:"deleteSelected",value:function(){var t=this;!0!==this.editMode&&this.enableEditMode(),this._clean(),this.inMode="delete";var e=this.selectionHandler.getSelectedNodes(),i=this.selectionHandler.getSelectedEdges(),o=void 0;if(e.length>0){for(var n=0;n0&&"function"==typeof this.options.deleteEdge&&(o=this.options.deleteEdge);if("function"==typeof o){var s={nodes:e,edges:i};if(2!==o.length)throw new Error("The function for delete does not support two arguments (data, callback)");o(s,function(e){null!==e&&void 0!==e&&"delete"===t.inMode?(t.body.data.edges.getDataSet().remove(e.edges),t.body.data.nodes.getDataSet().remove(e.nodes),t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar()):(t.body.emitter.emit("startSimulation"),t.showManipulatorToolbar())})}else this.body.data.edges.getDataSet().remove(i),this.body.data.nodes.getDataSet().remove(e),this.body.emitter.emit("startSimulation"),this.showManipulatorToolbar()}},{key:"_setup",value:function(){!0===this.options.enabled?(this.guiEnabled=!0,this._createWrappers(),!1===this.editMode?this._createEditButton():this.showManipulatorToolbar()):(this._removeManipulationDOM(),this.guiEnabled=!1)}},{key:"_createWrappers",value:function(){void 0===this.manipulationDiv&&(this.manipulationDiv=document.createElement("div"),this.manipulationDiv.className="vis-manipulation",!0===this.editMode?this.manipulationDiv.style.display="block":this.manipulationDiv.style.display="none",this.canvas.frame.appendChild(this.manipulationDiv)),void 0===this.editModeDiv&&(this.editModeDiv=document.createElement("div"),this.editModeDiv.className="vis-edit-mode",!0===this.editMode?this.editModeDiv.style.display="none":this.editModeDiv.style.display="block",this.canvas.frame.appendChild(this.editModeDiv)),void 0===this.closeDiv&&(this.closeDiv=document.createElement("div"),this.closeDiv.className="vis-close",this.closeDiv.style.display=this.manipulationDiv.style.display,this.canvas.frame.appendChild(this.closeDiv))}},{key:"_getNewTargetNode",value:function(t,e){var i=f.deepExtend({},this.options.controlNodeStyle);i.id="targetNode"+f.randomUUID(),i.hidden=!1,i.physics=!1,i.x=t,i.y=e;var o=this.body.functions.createNode(i);return o.shape.boundingBox={left:t,right:t,top:e,bottom:e},o}},{key:"_createEditButton",value:function(){this._clean(),this.manipulationDOM={},f.recursiveDOMDelete(this.editModeDiv);var t=this.options.locales[this.options.locale],e=this._createButton("editMode","vis-button vis-edit vis-edit-mode",t.edit||this.options.locales.en.edit);this.editModeDiv.appendChild(e),this._bindHammerToDiv(e,this.toggleEditMode.bind(this))}},{key:"_clean",value:function(){this.inMode=!1,!0===this.guiEnabled&&(f.recursiveDOMDelete(this.editModeDiv),f.recursiveDOMDelete(this.manipulationDiv),this._cleanManipulatorHammers()),this._cleanupTemporaryNodesAndEdges(),this._unbindTemporaryUIs(),this._unbindTemporaryEvents(),this.body.emitter.emit("restorePhysics")}},{key:"_cleanManipulatorHammers",value:function(){if(0!=this.manipulationHammers.length){for(var t=0;t0&&void 0!==arguments[0]?arguments[0]:1;this.manipulationDOM["seperatorLineDiv"+t]=document.createElement("div"),this.manipulationDOM["seperatorLineDiv"+t].className="vis-separator-line",this.manipulationDiv.appendChild(this.manipulationDOM["seperatorLineDiv"+t])}},{key:"_createAddNodeButton",value:function(t){var e=this._createButton("addNode","vis-button vis-add",t.addNode||this.options.locales.en.addNode);this.manipulationDiv.appendChild(e),this._bindHammerToDiv(e,this.addNodeMode.bind(this))}},{key:"_createAddEdgeButton",value:function(t){var e=this._createButton("addEdge","vis-button vis-connect",t.addEdge||this.options.locales.en.addEdge);this.manipulationDiv.appendChild(e),this._bindHammerToDiv(e,this.addEdgeMode.bind(this))}},{key:"_createEditNodeButton",value:function(t){var e=this._createButton("editNode","vis-button vis-edit",t.editNode||this.options.locales.en.editNode);this.manipulationDiv.appendChild(e),this._bindHammerToDiv(e,this.editNode.bind(this))}},{key:"_createEditEdgeButton",value:function(t){var e=this._createButton("editEdge","vis-button vis-edit",t.editEdge||this.options.locales.en.editEdge);this.manipulationDiv.appendChild(e),this._bindHammerToDiv(e,this.editEdgeMode.bind(this))}},{key:"_createDeleteButton",value:function(t){var e;e=this.options.rtl?"vis-button vis-delete-rtl":"vis-button vis-delete";var i=this._createButton("delete",e,t.del||this.options.locales.en.del);this.manipulationDiv.appendChild(i),this._bindHammerToDiv(i,this.deleteSelected.bind(this))}},{key:"_createBackButton",value:function(t){var e=this._createButton("back","vis-button vis-back",t.back||this.options.locales.en.back);this.manipulationDiv.appendChild(e),this._bindHammerToDiv(e,this.showManipulatorToolbar.bind(this))}},{key:"_createButton",value:function(t,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"vis-label";return this.manipulationDOM[t+"Div"]=document.createElement("div"),this.manipulationDOM[t+"Div"].className=e,this.manipulationDOM[t+"Label"]=document.createElement("div"),this.manipulationDOM[t+"Label"].className=o,this.manipulationDOM[t+"Label"].innerHTML=i,this.manipulationDOM[t+"Div"].appendChild(this.manipulationDOM[t+"Label"]),this.manipulationDOM[t+"Div"]}},{key:"_createDescription",value:function(t){this.manipulationDiv.appendChild(this._createButton("description","vis-button vis-none",t))}},{key:"_temporaryBindEvent",value:function(t,e){this.temporaryEventFunctions.push({event:t,boundFunction:e}),this.body.emitter.on(t,e)}},{key:"_temporaryBindUI",value:function(t,e){if(void 0===this.body.eventListeners[t])throw new Error("This UI function does not exist. Typo? You tried: "+t+" possible are: "+(0,a.default)((0,s.default)(this.body.eventListeners)));this.temporaryUIFunctions[t]=this.body.eventListeners[t],this.body.eventListeners[t]=e}},{key:"_unbindTemporaryUIs",value:function(){for(var t in this.temporaryUIFunctions)this.temporaryUIFunctions.hasOwnProperty(t)&&(this.body.eventListeners[t]=this.temporaryUIFunctions[t],delete this.temporaryUIFunctions[t]);this.temporaryUIFunctions={}}},{key:"_unbindTemporaryEvents",value:function(){for(var t=0;t=0;r--)if(n[r]!==this.selectedControlNode.id){s=this.body.nodes[n[r]];break}if(void 0!==s&&void 0!==this.selectedControlNode)if(!0===s.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var a=this.body.nodes[this.temporaryIds.nodes[0]];this.selectedControlNode.id===a.id?this._performEditEdge(s.id,o.to.id):this._performEditEdge(o.from.id,s.id)}else o.updateEdgeType(),this.body.emitter.emit("restorePhysics");this.body.emitter.emit("_redraw")}}},{key:"_handleConnect",value:function(t){if((new Date).valueOf()-this.touchTime>100){this.lastTouch=this.body.functions.getPointer(t.center),this.lastTouch.translation=f.extend({},this.body.view.translation);var e=this.lastTouch,i=this.selectionHandler.getNodeAt(e);if(void 0!==i)if(!0===i.isCluster)alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError);else{var o=this._getNewTargetNode(i.x,i.y);this.body.nodes[o.id]=o,this.body.nodeIndices.push(o.id);var n=this.body.functions.createEdge({id:"connectionEdge"+f.randomUUID(),from:i.id,to:o.id,physics:!1,smooth:{enabled:!0,type:"continuous",roundness:.5}});this.body.edges[n.id]=n,this.body.edgeIndices.push(n.id),this.temporaryIds.nodes.push(o.id),this.temporaryIds.edges.push(n.id)}this.touchTime=(new Date).valueOf()}}},{key:"_dragControlNode",value:function(t){var e=this.body.functions.getPointer(t.center);if(void 0!==this.temporaryIds.nodes[0]){var i=this.body.nodes[this.temporaryIds.nodes[0]];i.x=this.canvas._XconvertDOMtoCanvas(e.x),i.y=this.canvas._YconvertDOMtoCanvas(e.y),this.body.emitter.emit("_redraw")}else{var o=e.x-this.lastTouch.x,n=e.y-this.lastTouch.y;this.body.view.translation={x:this.lastTouch.translation.x+o,y:this.lastTouch.translation.y+n}}}},{key:"_finishConnect",value:function(t){var e=this.body.functions.getPointer(t.center),i=this.selectionHandler._pointerToPositionObject(e),o=void 0;void 0!==this.temporaryIds.edges[0]&&(o=this.body.edges[this.temporaryIds.edges[0]].fromId);for(var n=this.selectionHandler._getAllNodesOverlappingWith(i),s=void 0,r=n.length-1;r>=0;r--)if(-1===this.temporaryIds.nodes.indexOf(n[r])){s=this.body.nodes[n[r]];break}this._cleanupTemporaryNodesAndEdges(),void 0!==s&&(!0===s.isCluster?alert(this.options.locales[this.options.locale].createEdgeError||this.options.locales.en.createEdgeError):void 0!==this.body.nodes[o]&&void 0!==this.body.nodes[s.id]&&this._performAddEdge(o,s.id)),this.body.emitter.emit("_redraw")}},{key:"_dragStartEdge",value:function(t){var e=this.lastTouch;this.selectionHandler._generateClickEvent("dragStart",t,e,void 0,!0)}},{key:"_performAddNode",value:function(t){var e=this,i={id:f.randomUUID(),x:t.pointer.canvas.x,y:t.pointer.canvas.y,label:"new"};if("function"==typeof this.options.addNode){if(2!==this.options.addNode.length)throw this.showManipulatorToolbar(),new Error("The function for add does not support two arguments (data,callback)");this.options.addNode(i,function(t){null!==t&&void 0!==t&&"addNode"===e.inMode&&(e.body.data.nodes.getDataSet().add(t),e.showManipulatorToolbar())})}else this.body.data.nodes.getDataSet().add(i),this.showManipulatorToolbar()}},{key:"_performAddEdge",value:function(t,e){var i=this,o={from:t,to:e};if("function"==typeof this.options.addEdge){if(2!==this.options.addEdge.length)throw new Error("The function for connect does not support two arguments (data,callback)");this.options.addEdge(o,function(t){null!==t&&void 0!==t&&"addEdge"===i.inMode&&(i.body.data.edges.getDataSet().add(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())})}else this.body.data.edges.getDataSet().add(o),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}},{key:"_performEditEdge",value:function(t,e){var i=this,o={id:this.edgeBeingEditedId,from:t,to:e,label:this.body.data.edges._data[this.edgeBeingEditedId].label},n=this.options.editEdge;if("object"===(void 0===n?"undefined":(0,d.default)(n))&&(n=n.editWithoutDrag),"function"==typeof n){if(2!==n.length)throw new Error("The function for edit does not support two arguments (data, callback)");n(o,function(t){null===t||void 0===t||"editEdge"!==i.inMode?(i.body.edges[o.id].updateEdgeType(),i.body.emitter.emit("_redraw"),i.showManipulatorToolbar()):(i.body.data.edges.getDataSet().update(t),i.selectionHandler.unselectAll(),i.showManipulatorToolbar())})}else this.body.data.edges.getDataSet().update(o),this.selectionHandler.unselectAll(),this.showManipulatorToolbar()}}]),t}();e.default=g},function(t,e,i){function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=i(30),s=o(n),r=i(0),a=o(r),h=i(1),d=o(h),l=i(239),u=o(l),c=function(){function t(e,i,o){(0,a.default)(this,t),this.body=e,this.springLength=i,this.springConstant=o,this.distanceSolver=new u.default}return(0,d.default)(t,[{key:"setOptions",value:function(t){t&&(t.springLength&&(this.springLength=t.springLength),t.springConstant&&(this.springConstant=t.springConstant))}},{key:"solve",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=this.distanceSolver.getDistances(this.body,t,e);this._createL_matrix(o),this._createK_matrix(o),this._createE_matrix();for(var n=0,r=Math.max(1e3,Math.min(10*this.body.nodeIndices.length,6e3)),a=1e9,h=0,d=0,l=0,u=0,c=0;a>.01&&n1&&c<5;){c+=1,this._moveNode(h,d,l);var m=this._getEnergy(h),v=(0,s.default)(m,3);u=v[0],d=v[1],l=v[2]}}}},{key:"_getHighestEnergyNode",value:function(t){for(var e=this.body.nodeIndices,i=this.body.nodes,o=0,n=e[0],r=0,a=0,h=0;h Date: Fri, 18 Jan 2019 21:19:41 -0500 Subject: [PATCH 063/162] Added missing / --- scripts/nginx/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/nginx/install b/scripts/nginx/install index 74783899c..7a911f742 100755 --- a/scripts/nginx/install +++ b/scripts/nginx/install @@ -28,7 +28,7 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th # CJDNS peers mkdir "$BASE_DIR/tmp" git clone https://github.com/hamishcoleman/cjdns_tool.git "$BASE_DIR/tmp/cjdns_tool" - sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib/" "/var/www/html/cgi-bin" + sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib/" "/var/www/html/cgi-bin/" rm -rf "$BASE_DIR/tmp" sudo cp "$BASE_DIR/peers-cjdns" "/var/www/html/cgi-bin/peers-cjdns" From 44f490b10a74e0b38c558fea916f1382eda44c9e Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 24 Jan 2019 17:45:24 -0500 Subject: [PATCH 064/162] IPFS version bump (#261) * IPFS Bump Resolve issue #256 * Enabled gossipsub * Fixed version --- scripts/ipfs/install | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/ipfs/install b/scripts/ipfs/install index 2e01ad520..037296d50 100755 --- a/scripts/ipfs/install +++ b/scripts/ipfs/install @@ -4,7 +4,7 @@ true set -e -GO_IPFS_VERSION=v0.4.17 +GO_IPFS_VERSION=v0.4.18 # Hyperborea connected peer used to bootstrap hyperborea only ipfs nodes IPFS_PEER="/ip6/fc6e:691e:dfaa:b992:a10a:7b49:5a1a:5e09/tcp/4001/ipfs/QmU6NeD2Uu34WKest1NZGvGmScLhN1zVo66K35GeE6Jft2" @@ -22,6 +22,9 @@ rm -rf "$BASE_DIR/tmp" # Initialize IPFS ipfs init || true +# Enable gossipsub routing +ipfs config Pubsub.Router gossipsub + # Configure HTTP to IPFS gateway sudo cp "$BASE_DIR/ipfs-http-gateway.conf" /etc/nginx/site-path-enabled/ipfs-http-gateway.conf sudo systemctl restart nginx.service From 5d80ac879e797a25df5b8d8efe6fd42ed831528a Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 24 Jan 2019 23:06:42 -0500 Subject: [PATCH 065/162] Cjdns tunnel fix (#227) * Update cjdns service script to run cjdns-setup * Service reload daemon * Update cjdns-setup * Delete 50-cjdns.rules --- scripts/cjdns-iptunnel/50-cjdns.rules | 5 ----- scripts/cjdns-iptunnel/cjdns-setup | 6 ++++-- scripts/cjdns-iptunnel/install | 14 +++++++++++--- 3 files changed, 15 insertions(+), 10 deletions(-) delete mode 100644 scripts/cjdns-iptunnel/50-cjdns.rules diff --git a/scripts/cjdns-iptunnel/50-cjdns.rules b/scripts/cjdns-iptunnel/50-cjdns.rules deleted file mode 100644 index a0743db98..000000000 --- a/scripts/cjdns-iptunnel/50-cjdns.rules +++ /dev/null @@ -1,5 +0,0 @@ -#SUBSYSTEM!="net", GOTO="cjdns_end" -KERNEL!="tun0", GOTO="cjdns_end" -ACTION!="add", GOTO="cjdns_end" -PROGRAM="/usr/local/sbin/cjdns-setup %k" -LABEL="cjdns_end" diff --git a/scripts/cjdns-iptunnel/cjdns-setup b/scripts/cjdns-iptunnel/cjdns-setup index f91cd0574..efaf66838 100755 --- a/scripts/cjdns-iptunnel/cjdns-setup +++ b/scripts/cjdns-iptunnel/cjdns-setup @@ -1,6 +1,8 @@ #!/usr/bin/env bash -set -e +# The service should have started by now and tun interface should be up +# But if not we can uncomment this sleep line +# sleep 8 SUBNET4="10.1.0." SUBNET6="fe80::" @@ -51,4 +53,4 @@ elif [ -e /etc/cjdns.iptunnel.client ]; then # Add default ipv6 router over tun0 ip -6 route add default dev tun0 -fi \ No newline at end of file +fi diff --git a/scripts/cjdns-iptunnel/install b/scripts/cjdns-iptunnel/install index cb7231664..a0a5d45a5 100755 --- a/scripts/cjdns-iptunnel/install +++ b/scripts/cjdns-iptunnel/install @@ -4,6 +4,14 @@ set -e BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# Install scripts that run after cjdns tun0 is configured -sudo cp "$BASE_DIR/50-cjdns.rules" /etc/udev/rules.d/50-cjdns.rules -sudo cp "$BASE_DIR/cjdns-setup" /usr/local/sbin/cjdns-setup +# Update service to start script on cjdns start +if [ -f /lib/systemd/system/cjdns.service ]; then + sudo sed -i /ExecStartPost/d /lib/systemd/system/cjdns.service + sudo sed -i s#Restart=always#Restart=always\\nExecStartPost=/usr/local/sbin/cjdns-setup# /lib/systemd/system/cjdns.service +fi +if [ -f /etc/systemd/system/cjdns.service ]; then + sudo sed -i /ExecStartPost/d /etc/systemd/system/cjdns.service + sudo sed -i s#Restart=always#Restart=always\\nExecStartPost=/usr/local/sbin/cjdns-setup# /etc/systemd/system/cjdns.service +fi + +sudo systemctl daemon-reload From 8872818900b463639ebedca1267077ed7d8652bd Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 25 Jan 2019 00:12:03 -0500 Subject: [PATCH 066/162] Added missing line to CJDNS Tuunle --- scripts/cjdns-iptunnel/install | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/cjdns-iptunnel/install b/scripts/cjdns-iptunnel/install index a0a5d45a5..eae152ed7 100755 --- a/scripts/cjdns-iptunnel/install +++ b/scripts/cjdns-iptunnel/install @@ -3,6 +3,7 @@ set -e BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +sudo cp "$BASE_DIR/cjdns-setup" "/usr/local/sbin/cjdns-setup" # Update service to start script on cjdns start if [ -f /lib/systemd/system/cjdns.service ]; then From d56591c534da9d2d942e1a4bc72f8544125303df Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 25 Jan 2019 00:22:38 -0500 Subject: [PATCH 067/162] allow nginx access to socket --- scripts/nginx/install | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/nginx/install b/scripts/nginx/install index 7a911f742..64fecb7b9 100755 --- a/scripts/nginx/install +++ b/scripts/nginx/install @@ -34,10 +34,12 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th # Yggdrasil peers sudo cp "$BASE_DIR/peers-yggdrasil" "/var/www/html/cgi-bin/peers-yggdrasil" - sudo chmod +x "/var/www/html/cgi-bin/peers-cjdns" sudo chmod +x "/var/www/html/cgi-bin/peers-yggdrasil" - + + # Allow nginx access to yggdrasil socket + usermod -a -G yggdrasil www-data + BASE_DIR="$LAST_BASE" fi From 8ce2f98a8b2e7960c01c3cacad7e5f79186797c9 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 25 Jan 2019 18:51:44 -0500 Subject: [PATCH 068/162] Yggdrasil permisions moved to yggdrasil module --- scripts/nginx/install | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/scripts/nginx/install b/scripts/nginx/install index 64fecb7b9..5c2ba37e6 100755 --- a/scripts/nginx/install +++ b/scripts/nginx/install @@ -28,7 +28,7 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th # CJDNS peers mkdir "$BASE_DIR/tmp" git clone https://github.com/hamishcoleman/cjdns_tool.git "$BASE_DIR/tmp/cjdns_tool" - sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib/" "/var/www/html/cgi-bin/" + sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib" "/var/www/html/cgi-bin/" rm -rf "$BASE_DIR/tmp" sudo cp "$BASE_DIR/peers-cjdns" "/var/www/html/cgi-bin/peers-cjdns" @@ -36,10 +36,7 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th sudo cp "$BASE_DIR/peers-yggdrasil" "/var/www/html/cgi-bin/peers-yggdrasil" sudo chmod +x "/var/www/html/cgi-bin/peers-cjdns" sudo chmod +x "/var/www/html/cgi-bin/peers-yggdrasil" - - # Allow nginx access to yggdrasil socket - usermod -a -G yggdrasil www-data - + BASE_DIR="$LAST_BASE" fi From e9cba17f11e7a5d505f58a62546be3aa14171587 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 25 Jan 2019 18:52:58 -0500 Subject: [PATCH 069/162] yggdrasil permisions --- scripts/yggdrasil/install | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index a9e89830a..a5c831ec8 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -29,3 +29,8 @@ sudo sed -i "s/IfName: auto/IfName: ygg0/" /etc/yggdrasil.conf YGGDRASIL_PORT=$(sudo cat /etc/yggdrasil.conf | grep \ Listen: | awk '{print $2}' | tr -d \") YGGDRASIL_PORT=$(printf "%q" "$YGGDRASIL_PORT") # Escape for sed sudo sed -i "s/$YGGDRASIL_PORT/\[::\]:12345/" /etc/yggdrasil.conf + +sudo systemctl start yggdrasil + +# Allow nginx access to yggdrasil socket when installed +sudo usermod -a -G yggdrasil www-data || true From 9e1360fa495a2f6a901bc761986546b35639dda7 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 26 Jan 2019 09:06:41 -0500 Subject: [PATCH 070/162] Added a missing sudo --- scripts/status | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/status b/scripts/status index 141ba3732..346ab716d 100755 --- a/scripts/status +++ b/scripts/status @@ -126,6 +126,6 @@ if [ "$(which yggdrasil)" ]; then echo -e $YGGIP echo -e '---------------------------------------' echo -e 'YGGDRASIL PEERS' - yggdrasilctl getPeers | grep -v "$YGGIP" | awk '{print $1}' | grep -v "bytes_recvd" + sudo yggdrasilctl getPeers | grep -v "$YGGIP" | awk '{print $1}' | grep -v "bytes_recvd" echo -e '---------------------------------------' fi From 646d2d2a04527dd36902fe9896ddb7f7eeea5c23 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 26 Jan 2019 11:07:30 -0500 Subject: [PATCH 071/162] Corrected errors in function names --- scripts/nginx/map.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/nginx/map.js b/scripts/nginx/map.js index 799226c5e..1d6526e5a 100644 --- a/scripts/nginx/map.js +++ b/scripts/nginx/map.js @@ -43,7 +43,7 @@ function CJDNSMap(ajax) { UpdateNode(parts[5],public2IPv6(parts[5]),parts[4], Nodes.peers[a].recvKbps + "kpbs / " + Nodes.peers[a].sendKbps + " kbps","cjdns",NodeExist); } DeleteNodes("cjdns",NodeExist); - setTimeout("loadXMLDoc()",1000); + setTimeout("LoadXMLDoc_cjdns()",1000); } lastrx=[]; @@ -65,7 +65,7 @@ function YggdrasilMap(ajax) { } } DeleteNodes("yggdrasil",NodeExist); - setTimeout("loadXMLDoc_y()",1000); + setTimeout("LoadXMLDoc_ygg()",1000); } // Update Map From 8ce3856d08c5274989823d2a69fbc5b4fa84328e Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 31 Jan 2019 13:14:37 -0500 Subject: [PATCH 072/162] Yggdrasil patches (#268) * Enabled yggdrasil service on install * Add yggdrasil peer and nocopy support * Added yggdrasil support to ipfs swarm code * remove cjdns from filename * remove cjdns from file name * remove cjdns from file name * Corrected variable defination --- scripts/ipfs/install | 21 +++++++++++----- .../{ipfs-swarm-cjdns.sh => ipfs-swarm.sh} | 24 ++++++++++++++----- scripts/ipfs/ipfs.service | 2 +- scripts/yggdrasil/install | 4 ++-- 4 files changed, 36 insertions(+), 15 deletions(-) rename scripts/ipfs/{ipfs-swarm-cjdns.sh => ipfs-swarm.sh} (69%) diff --git a/scripts/ipfs/install b/scripts/ipfs/install index 037296d50..b0ab9204c 100755 --- a/scripts/ipfs/install +++ b/scripts/ipfs/install @@ -7,7 +7,11 @@ set -e GO_IPFS_VERSION=v0.4.18 # Hyperborea connected peer used to bootstrap hyperborea only ipfs nodes -IPFS_PEER="/ip6/fc6e:691e:dfaa:b992:a10a:7b49:5a1a:5e09/tcp/4001/ipfs/QmU6NeD2Uu34WKest1NZGvGmScLhN1zVo66K35GeE6Jft2" +IPFS_PEER_1="/ip6/fc6e:691e:dfaa:b992:a10a:7b49:5a1a:5e09/tcp/4001/ipfs/QmU6NeD2Uu34WKest1NZGvGmScLhN1zVo66K35GeE6Jft2" +# Yggdrasil connected peer used to bootstrap hyperborea only ipfs nodes +IPFS_PEER_2="/ip6/301:4541:2f84:1188:216:3eff:fed5:a2df/tcp/4001/ipfs/QmWZpTdfETtpjJphVE1YbxMkUcL84idkg44Cq1XWSBNm7P" +IPFS_PEER_3="/ip6/200:98bf:d6df:e49a:f525:40bf:18d:ac45/tcp/4001/ipfs/QmU6NeD2Uu34WKest1NZGvGmScLhN1zVo66K35GeE6Jft2" + BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -25,6 +29,9 @@ ipfs init || true # Enable gossipsub routing ipfs config Pubsub.Router gossipsub +# Enable Filestore for --nocopy capability +ipfs config --bool Experimental.FilestoreEnabled true + # Configure HTTP to IPFS gateway sudo cp "$BASE_DIR/ipfs-http-gateway.conf" /etc/nginx/site-path-enabled/ipfs-http-gateway.conf sudo systemctl restart nginx.service @@ -33,15 +40,17 @@ sudo systemctl restart nginx.service source "$BASE_DIR/../shared/nodeinfo/install" sudo cp "$BASE_DIR/nodeinfo-ipfs" /opt/tomesh/nodeinfo.d/ipfs -# add cjdns bootstrap address -ipfs bootstrap add "$IPFS_PEER" +# Add bootstrap addresses +ipfs bootstrap add "$IPFS_PEER_1" +ipfs bootstrap add "$IPFS_PEER_2" +ipfs bootstrap add "$IPFS_PEER_3" # Download dependencies sudo apt-get install -y jq -# Move file -sudo cp "$BASE_DIR/ipfs-swarm-cjdns.sh" /usr/local/bin/ -sudo chmod +x /usr/local/bin/ipfs-swarm-cjdns.sh +# Copy file +sudo cp "$BASE_DIR/ipfs-swarm.sh" /usr/local/bin/ +sudo chmod +x /usr/local/bin/ipfs-swarm.sh # Configure systemd to start ipfs.service on system boot sudo cp "$BASE_DIR/ipfs.service" /etc/systemd/system/ipfs.service diff --git a/scripts/ipfs/ipfs-swarm-cjdns.sh b/scripts/ipfs/ipfs-swarm.sh similarity index 69% rename from scripts/ipfs/ipfs-swarm-cjdns.sh rename to scripts/ipfs/ipfs-swarm.sh index f66f67f1f..a4e20f5c3 100644 --- a/scripts/ipfs/ipfs-swarm-cjdns.sh +++ b/scripts/ipfs/ipfs-swarm.sh @@ -11,20 +11,25 @@ if [[ ${attempts} -eq 0 ]]; then exit 1 fi -while read -r cjdns_peer; do - cjdns_addr=$(sudo /opt/cjdns/publictoip6 "$cjdns_peer") - +function addPeer { + addr=$1 # See if they have IPFS enabled - res=$(curl http://["${cjdns_addr}"]/nodeinfo.json -s) + res=$(curl http://["${addr}"]/nodeinfo.json -s) if [ ! -x "${res}" ]; then id=$(echo "${res}" | jq -r -M '.services.ipfs.ID') # Value is found if [[ ! ${id} == "null" ]] && [[ ! "${id}" == "" ]]; then # Connect to neighbouring ipfs - ipfs swarm connect "/ip6/${cjdns_addr}/tcp/4001/ipfs/${id}" - echo "Connecting to ${cjdns_addr}" + ipfs swarm connect "/ip6/${addr}/tcp/4001/ipfs/${id}" + echo "Connecting to ${addr}" fi fi +} + +# Add cjdns direct peers +while read -r cjdns_peer; do + cjdns_addr=$(sudo /opt/cjdns/publictoip6 "$cjdns_peer") + addPeer "${cjdns_addr}" # Add all that node's peers to the bottom of the list to check further hop peers # XXX: The below command hasn't been working -- so for now only 1-hop peers are checked @@ -32,5 +37,12 @@ while read -r cjdns_peer; do done <<< "$(sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{ print $6".k" }' | xargs)" +# Add yggdrasil direct peers +if [ "$(which yggdrasil)" ]; then + while read -r ygg_peer; do + addPeer "${ygg_peer}" + done <<< "$(sudo yggdrasilctl getPeers | grep -v "(self)" | awk '{print $1}' | grep -v bytes_recvd | xargs)" +fi + # Update peers data since ipfs just started sudo /usr/local/bin/nodeinfo-update.sh diff --git a/scripts/ipfs/ipfs.service b/scripts/ipfs/ipfs.service index ed5b9a4ec..26cabf74a 100644 --- a/scripts/ipfs/ipfs.service +++ b/scripts/ipfs/ipfs.service @@ -7,7 +7,7 @@ After=network.target Type=simple Environment=IPFS_PATH=__USER_HOME__/.ipfs ExecStart=/usr/local/bin/ipfs daemon --enable-namesys-pubsub --migrate=true -ExecStartPost=/usr/local/bin/ipfs-swarm-cjdns.sh +ExecStartPost=/usr/local/bin/ipfs-swarm.sh ExecStop=/bin/kill -s QUIT $MAINPID Restart=on-failure RestartSec=10s diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index a5c831ec8..ac5546a73 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -9,7 +9,6 @@ YGGDRASIL_HOST=419-115685026 BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Download and install yggdrasil routing engine - ARM_VERSION=armhf if uname -m | grep -q aarch64; then ARM_VERSION=arm64 @@ -30,7 +29,8 @@ YGGDRASIL_PORT=$(sudo cat /etc/yggdrasil.conf | grep \ Listen: | awk '{print $2 YGGDRASIL_PORT=$(printf "%q" "$YGGDRASIL_PORT") # Escape for sed sudo sed -i "s/$YGGDRASIL_PORT/\[::\]:12345/" /etc/yggdrasil.conf -sudo systemctl start yggdrasil +sudo systemctl enable yggdrasil.service +sudo systemctl start yggdrasil.service # Allow nginx access to yggdrasil socket when installed sudo usermod -a -G yggdrasil www-data || true From 42f6cd9523331bd357cc7e9947ef651ff400234e Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 31 Jan 2019 14:06:09 -0500 Subject: [PATCH 073/162] Update install --- scripts/nginx/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/nginx/install b/scripts/nginx/install index 5c2ba37e6..6551c9b55 100755 --- a/scripts/nginx/install +++ b/scripts/nginx/install @@ -28,7 +28,7 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th # CJDNS peers mkdir "$BASE_DIR/tmp" git clone https://github.com/hamishcoleman/cjdns_tool.git "$BASE_DIR/tmp/cjdns_tool" - sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib" "/var/www/html/cgi-bin/" + sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib/" "/var/www/html/cgi-bin/" rm -rf "$BASE_DIR/tmp" sudo cp "$BASE_DIR/peers-cjdns" "/var/www/html/cgi-bin/peers-cjdns" From 3fa2daebdb8de6604d44caf63da050733692a027 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 31 Jan 2019 15:47:35 -0500 Subject: [PATCH 074/162] Add hostname to yggdrasil config (#271) --- scripts/yggdrasil/install | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index ac5546a73..bf9b8b8f0 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -29,6 +29,13 @@ YGGDRASIL_PORT=$(sudo cat /etc/yggdrasil.conf | grep \ Listen: | awk '{print $2 YGGDRASIL_PORT=$(printf "%q" "$YGGDRASIL_PORT") # Escape for sed sudo sed -i "s/$YGGDRASIL_PORT/\[::\]:12345/" /etc/yggdrasil.conf + +# Set node name +if [ -z "${NEWHOSTNAME}" ]; then + NEWHOSTNAME=$(cat /etc/hostname) +fi +sudo sed -i "\$i\ \ NodeInfo:\n {\n name: ${NEWHOSTNAME}\n }\n" /etc/yggdrasil.conf + sudo systemctl enable yggdrasil.service sudo systemctl start yggdrasil.service From c5c80524a3f26d2e016436f0e82821aa672325d1 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 31 Jan 2019 15:48:58 -0500 Subject: [PATCH 075/162] Added check for cjdns tunnel interface (#274) * Added check for cjdns tunnel interface * Replaced ifconfig with ipaddr More support across Debian/ubuntu --- scripts/status | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/status b/scripts/status index 346ab716d..a20d8dd37 100755 --- a/scripts/status +++ b/scripts/status @@ -106,7 +106,7 @@ if [ "$(which yrd)" ]; then fi fi -if [ "$(which cjdroute)" ]; then +if [ "$(which cjdroute)" ] && [ "$(ip addr | grep tun0)" ] ; then echo -e '---------------------------------------' echo -e 'CJDNS NODE' sudo grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g' From 219b5db6d890f1aa5bd6451eaac0b05a1ffae2e2 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 31 Jan 2019 15:49:33 -0500 Subject: [PATCH 076/162] Remove lock file before starting (#275) --- scripts/prometheus-server/prometheus-server.service | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/prometheus-server/prometheus-server.service b/scripts/prometheus-server/prometheus-server.service index 8276367ea..b64ba4c33 100644 --- a/scripts/prometheus-server/prometheus-server.service +++ b/scripts/prometheus-server/prometheus-server.service @@ -6,6 +6,7 @@ After=network.target [Service] WorkingDirectory=/opt/prometheus Type=simple +ExecStartPre=/bin/rm -rf /opt/prometheus/data/lock || true ExecStart=/opt/prometheus/prometheus ExecStop=/bin/kill -s QUIT $MAINPID Restart=on-failure From 892762158ab401e7ccf5dc7a20da4760db9854e7 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 31 Jan 2019 15:50:27 -0500 Subject: [PATCH 077/162] SSB neighbour ping (#276) * Added yggdrasil and cjdns to manua peering for SSB * Shellcheck fixes * Update ssb-broadcast-service.sh * Update ssb-broadcast-service.sh --- scripts/ssb/ssb-broadcast-service.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/scripts/ssb/ssb-broadcast-service.sh b/scripts/ssb/ssb-broadcast-service.sh index b23b32d18..c8908826b 100755 --- a/scripts/ssb/ssb-broadcast-service.sh +++ b/scripts/ssb/ssb-broadcast-service.sh @@ -10,5 +10,28 @@ while true; do fi done fi + + # Manual cjdns peer unicast + if [ "$(which cjdns)" ]; then + mycjdnsip=$(grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g') + # shellcheck disable=SC2102,SC2046 + read -ar peers <<< $(sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{print $6".k"}' | xargs) + for peer in "${peers[@]}"; do + ip=$(sudo /opt/cjdns/publictoip6 "$peer") + # shellcheck disable=SC2102 + echo -n "net:$mycjdnsip:8008~shs:$id" | sudo socat -T 1 - UDP6-DATAGRAM:[$ip]:8008 + done + fi + + # Add yggdrasil direct peers + if [ "$(which yggdrasil)" ]; then + myyggip=$(yggdrasilctl getself | grep address | awk '{print $3}') + read -ar peers <<< "$(sudo yggdrasilctl getPeers | grep -v "(self)" | awk '{print $1}' | grep -v bytes_recvd | xargs)" + for peer in "${peers[@]}"; do + # shellcheck disable=SC2102 + echo -n "net:$myyggip:8008~shs:$id" | sudo socat -T 1 - UDP6-DATAGRAM:[$peer]:8008 + done + fi + sleep 5 done From 32963a454258e6b4dbe75635cdb50c432f4ca2b4 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 8 Feb 2019 13:45:25 -0500 Subject: [PATCH 078/162] Profile Creation (#217) * Added askSelection function and created framework for groups * Corrected some syntax issues * Cleanup syntax * Corrected overwritten text * More whitespace cleanup * Corrected default letter from z to Z * Ignore variable check (incorrectly identifies) * Sync To Develop (#264) * Corrected IPERF3 port number * Initial install script * Update rules.v6 * Fix incorrect match of / during find * Fixed incorrect match of / in find * Opened port 8008 for ssb peering * Fixed ipv6 rules Removed duplication of rules Removed redundant CJDNS target * Updated meshpoint script to scan all interfaces Old mesh point scanned only phy0 and phy1, Update scans all interfaces, checks if they are wireless, determines the phy id, then checks for meshpoint. This way any phyx can be mesh point not just 0 and 1 * clearified meshpoint meaning in comment * Added missing accept keyword * Seperated and sorted ipv6 ports * Sorted ipv4 ports in firewall * Updated grammer in meshpoint comment * Added prometheus and grafana ports * Update FAQ.md * Deleted to avoid conflict * Patchfoo Module (#200) * Added patchfoo module * Added patchfoo to readme * added nginx to install * /patchfoo fix * Updated ssb-web-pi nginx script * Update and rename ssb-web-broadcast.service to ssb-web-pi-broadcast.service * Rename ssb-web-broadcast-service.sh to ssb-web-pi-broadcast-service.sh * Restored ssb-web-broadcast-service.sh * Cjdns iptunnel ipv6 (#223) * Added server side ipv6 addressing * Update cjdns-setup * correct ipv6 address definition * Added routing for ipv6 and ipv4 in client mode * Corrected paths and sudo * Updated status to include Yggdrasil and Cjdns * Removed unnecessary sudo (#226) Fixes #225 * Expire Password on Raspberry PI (#224) * Force password change after first reboot * Added check if password was already changed Fixes #198 * Update .travis.yml * Update install * Add HLS Player for IPFS Live Stream Repo (#228) Add HLS player from ipfs-live-stream Updated readme about player * Roll back change * Corrected incorrect binary path * Remove has password changed * Node welcome page (#230) * Create home page with list of service * Update process-stream.sh * Prevent ipns caching * Added multicast address for yagdrissil * Updated peer lookup * Update interface name * added ygg0 to nat * removed uneeded cjdns group * Lock port to specific value * Add yggdrasil to ports * Remove whitespace and version bump * shellcheck changes * Uninstall script for yaggdrasil * added WITH_YGGDRASIL variable * Added WITH_YGGDRASIL * remove of yggdrasil * correct path * Corrected spelling mistake * Corrected capitalization * Update install * Update status * Better way of finding the ipaddress for yggdrasil * Update status * Pi stream for SDR (#253) dded contrib file to compile and install SDR driver. Added image placeholder for audio only streams Added commented line to change from Pi Camera to SDR * Better regex * [Contrib] Captive Portal like lock for internet bound connection on an offline node (#229) * Make nginx install by default (#252) * Made changes according to issue's list * removed extra installs * Updated Yggdrasil Version * Node status screen (#249) * Added map code for index * Support Files * added cgi-bin config file * Install Map update * Create peers * missing " * Added yggdrasil map and reusable code * Split cjdns code into separate file Code cleanup * Whitespace cleanup * Whitespace cleanup * corrected lib path and +x peers-yggdrasil * move common css to head * Added node removal * Merge nginx move from upstream * Renamed Peers to peers-cjdns Corrected spelling * Renamed function to InitMap Fixed Syntax * Fixed formatting of LoadXMLDoc_x * Corrected peers to peers-cjdns * Added missing / * Added missing / * IPFS version bump (#261) * IPFS Bump Resolve issue #256 * Enabled gossipsub * Fixed version * Cjdns tunnel fix (#227) * Update cjdns service script to run cjdns-setup * Service reload daemon * Update cjdns-setup * Delete 50-cjdns.rules * Added profiles * Removed unused variable * Corrected missing file --- scripts/cjdns-iptunnel/install | 3 +- scripts/install2 | 203 ++++++++++++++++++++++++++++++--- scripts/nginx/install | 10 +- 3 files changed, 197 insertions(+), 19 deletions(-) diff --git a/scripts/cjdns-iptunnel/install b/scripts/cjdns-iptunnel/install index eae152ed7..370278642 100755 --- a/scripts/cjdns-iptunnel/install +++ b/scripts/cjdns-iptunnel/install @@ -10,7 +10,8 @@ if [ -f /lib/systemd/system/cjdns.service ]; then sudo sed -i /ExecStartPost/d /lib/systemd/system/cjdns.service sudo sed -i s#Restart=always#Restart=always\\nExecStartPost=/usr/local/sbin/cjdns-setup# /lib/systemd/system/cjdns.service fi -if [ -f /etc/systemd/system/cjdns.service ]; then + +if [ -f /etc/systemd/system/cjdns.service ]; then sudo sed -i /ExecStartPost/d /etc/systemd/system/cjdns.service sudo sed -i s#Restart=always#Restart=always\\nExecStartPost=/usr/local/sbin/cjdns-setup# /etc/systemd/system/cjdns.service fi diff --git a/scripts/install2 b/scripts/install2 index c8f3a70ab..339c07193 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -1,5 +1,6 @@ #!/usr/bin/env bash - +# shellcheck disable=SC2034 +true set -e TAG_CJDNS=d2e55d58548d83940482fe1bbbe1fd36f7f1b4ef @@ -28,20 +29,21 @@ function askModule { eval "res=\$$1" if [ "$(checkModule 'WITH_DIALOG')" ]; then - - # Do not stop exec on non 0 return values - set +e - # shellcheck disable=SC2086 - dialog $dialogGlobalParams $dialogParam --title "$2" --yesno "Install $2?" 6 55 - response=$? - # Return to previous setting - set -e - - case $response in - 0) res="true";; - 1) res="false";; - 255) exit;; - esac + if [ -z "$res" ] || [ "$res" != "true" ] && [ "$res" != "false" ]; then + # Do not stop exec on non 0 return values + set +e + # shellcheck disable=SC2086 + dialog $dialogGlobalParams $dialogParam --title "$2" --yesno "Install $2?" 6 55 + response=$? + # Return to previous setting + set -e + + case $response in + 0) res="true";; + 1) res="false";; + 255) exit;; + esac + fi else if [ -z "$res" ] || [ "$res" != "true" ] && [ "$res" != "false" ]; then read -p "Install $2 $askPrompt? " -n 1 -r @@ -72,6 +74,71 @@ function checkModule { fi } +# Ask user to choose from a selection of items +# list is \n delimited. Each line formated as +# "x text" +# x - single capital character that will be returned +# text - description of item +# +# askSelection +# +# Result is stored in $dialogREPLY +dialogREPLY="" +function askSelection { + selection=$1 + dialogREPLY="" + default="$3" + if [ "$(checkModule 'WITH_DIALOG')" ]; then + selection=$(echo -e "$selection" | while read -r selected; do + selectedItem="${selected:0:1}" + selectedText="${selected:2}" + if [[ "${selected:0:1}" == "$default" ]]; then + echo "$selectedItem \"$selectedText\" on" + else + echo "$selectedItem \"$selectedText\" off" + fi + done) + echo "$selection" > /tmp/selectionList + + # shellcheck disable=SC2086 + dialog $dialogGlobalParams --radiolist "$2" 10 55 8 --file /tmp/selectionList 2> /tmp/res + rm -f selectionList + response=$(cat /tmp/res) + rm -f /tmp/res + + # Return if canceled + if [[ "$response" == "" ]]; then + exit 1 + fi + + # Set response variable + dialogREPLY="$response" + else + isValid="" + while [[ "$isValid" == "" ]]; do + echo "$2" + echo ------------------- + echo -e "$1" + echo ------------------- + read -p "Selection: " -n 1 -r + echo "" + if [[ "$REPLY" == "" ]] && [[ "$default" != "" ]]; then + REPLY="$default" + isValid=1 + else + REPLY=$(echo "$REPLY" | awk '{print toupper($0)}') + + isValid=$(echo -e "$selection" | while read -r selected; do + if [[ "${selected:0:1}" == "$REPLY" ]]; then + echo 1 + fi + done) + fi + done + dialogREPLY="$REPLY" + fi +} + # Get board information and set flags accordingly BOARD_FAMILY="Unknown" BOARD_NAME="Generic" @@ -204,6 +271,112 @@ if [ "$(checkModule 'WITH_DIALOG')" ]; then sudo apt-get install dialog -y fi + +askSelection "A Basic node\nB Basic IPSF Node\nC Monitor Node\nD SSB Node\nE Camera Node\nZ Custom" "Select install type" Z + +case "$dialogREPLY" in + "A") + echo "Basic node" + WITH_YGGDRASIL=true + WITH_MESH_POINT="" + WITH_WIFI_AP="" + WITH_FIREWALL=true + WITH_CJDNS_IPTUNNEL=true + WITH_IPFS=false + WITH_PROMETHEUS_NODE_EXPORTER=true + WITH_EXTRA_TOOLS=true + WITH_WATCHDOG=true + WITH_YRD=true + WITH_PROMETHEUS_SERVER=false + WITH_GRAFANA=false + WITH_SSB=false + WITH_SSB_WEB=false + WITH_IPFS_PI_STREAM=false + ;; + "B") + echo "Basic IPFS node" + WITH_YGGDRASIL=true + WITH_MESH_POINT="" + WITH_WIFI_AP="" + WITH_FIREWALL=true + WITH_CJDNS_IPTUNNEL=true + WITH_IPFS=true + WITH_PROMETHEUS_NODE_EXPORTER=true + WITH_EXTRA_TOOLS=true + WITH_WATCHDOG=true + WITH_YRD=true + + WITH_PROMETHEUS_SERVER=false + WITH_GRAFANA=false + WITH_SSB=false + WITH_SSB_WEB=false + WITH_IPFS_PI_STREAM=false + ;; + "C") + echo "Monitor Node" + WITH_YGGDRASIL=true + WITH_MESH_POINT="" + WITH_WIFI_AP="" + WITH_FIREWALL=true + WITH_CJDNS_IPTUNNEL=true + WITH_IPFS=false + WITH_PROMETHEUS_NODE_EXPORTER=true + WITH_EXTRA_TOOLS=true + WITH_WATCHDOG=true + WITH_YRD=true + + WITH_PROMETHEUS_SERVER=true + WITH_GRAFANA=true + WITH_SSB=false + WITH_SSB_WEB=false + WITH_IPFS_PI_STREAM=false + ;; + "D") + echo "SSB Node" + WITH_YGGDRASIL=true + WITH_MESH_POINT="" + WITH_WIFI_AP="" + WITH_FIREWALL=true + WITH_CJDNS_IPTUNNEL=true + WITH_IPFS=false + WITH_PROMETHEUS_NODE_EXPORTER=true + WITH_EXTRA_TOOLS=true + WITH_WATCHDOG=true + WITH_YRD=true + + WITH_PROMETHEUS_SERVER=false + WITH_GRAFANA=false + WITH_SSB=true + WITH_SSB_PATCHFOO=true + WITH_IPFS_PI_STREAM=false + ;; + "E") + echo "IPFS Camera Node" + WITH_YGGDRASIL=true + WITH_MESH_POINT="" + WITH_WIFI_AP="" + WITH_FIREWALL=true + WITH_CJDNS_IPTUNNEL=true + WITH_IPFS=true + WITH_PROMETHEUS_NODE_EXPORTER=true + WITH_EXTRA_TOOLS=true + WITH_WATCHDOG=true + WITH_YRD=true + + WITH_PROMETHEUS_SERVER=false + WITH_GRAFANA=false + WITH_SSB=false + WITH_SSB_PATCHFOO=false + WITH_IPFS_PI_STREAM=true + ;; + "Z") + ;; + *) + echo "Error unknown response $dialogREPLY" + exit + ;; +esac + # Prompt and set missing flags # Prompt for name of the mesh network diff --git a/scripts/nginx/install b/scripts/nginx/install index 6551c9b55..d44aaf436 100755 --- a/scripts/nginx/install +++ b/scripts/nginx/install @@ -34,9 +34,13 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th # Yggdrasil peers sudo cp "$BASE_DIR/peers-yggdrasil" "/var/www/html/cgi-bin/peers-yggdrasil" + sudo chmod +x "/var/www/html/cgi-bin/peers-cjdns" sudo chmod +x "/var/www/html/cgi-bin/peers-yggdrasil" - + + # Allow nginx access to yggdrasil socket + usermod -a -G yggdrasil www-data + BASE_DIR="$LAST_BASE" - -fi + +fi \ No newline at end of file From 8ee6e8faa934dfb6abb29533ba12b107f712063d Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 8 Feb 2019 20:18:43 -0500 Subject: [PATCH 079/162] 20hmz band (#273) * remove default 40hmz * 20hmz downgrade --- scripts/mesh-adhoc/mesh-adhoc | 6 +++--- scripts/mesh-point/mesh-point | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/mesh-adhoc/mesh-adhoc b/scripts/mesh-adhoc/mesh-adhoc index 1e34ee6ca..be5dc158a 100755 --- a/scripts/mesh-adhoc/mesh-adhoc +++ b/scripts/mesh-adhoc/mesh-adhoc @@ -20,9 +20,9 @@ sudo ifconfig $mesh_dev up # Optionally assign IPv4 address to the mesh_dev interface # sudo ifconfig $mesh_dev 192.168.X.Y -# Join the mesh network with radio in HT40+ htmode to enable 802.11n rates -##TODO## Check for HT40+ first -sudo iw dev $mesh_dev ibss join MESH_NAME 2412 HT40+ +# Join the mesh network +# To join radio in HT40+ htmode (enable 802.11n rates) add HT40+ to end of this line +sudo iw dev $mesh_dev ibss join MESH_NAME 2412 # Restart cjdns sudo killall cjdroute diff --git a/scripts/mesh-point/mesh-point b/scripts/mesh-point/mesh-point index 95c7b81fc..2612c3063 100755 --- a/scripts/mesh-point/mesh-point +++ b/scripts/mesh-point/mesh-point @@ -50,8 +50,9 @@ sudo ifconfig $mesh_dev up # Optionally assign IPv4 address to the mesh_dev interface # sudo ifconfig $mesh_dev 192.168.X.Y -# Join the mesh network with radio in HT40+ htmode to enable 802.11n rates -sudo iw dev $mesh_dev mesh join MESH_NAME freq 2412 HT40+ +# Join the mesh network +# To join radio in HT40+ htmode (enable 802.11n rates) add HT40+ to end of this line +sudo iw dev $mesh_dev mesh join MESH_NAME freq 2412 # Disable forwarding since we rely on cjdns to do routing and only uses Mesh Point as a point-to-point link sudo iw dev $mesh_dev set mesh_param mesh_fwding=0 From e4c0b67a1ef0e821dc49e5dd2d0d27b576167b27 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 10 Feb 2019 10:48:35 -0500 Subject: [PATCH 080/162] Move yggdrasil group add to yggdrasil from nginx --- scripts/nginx/install | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/nginx/install b/scripts/nginx/install index d44aaf436..371cbce35 100755 --- a/scripts/nginx/install +++ b/scripts/nginx/install @@ -38,9 +38,6 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th sudo chmod +x "/var/www/html/cgi-bin/peers-cjdns" sudo chmod +x "/var/www/html/cgi-bin/peers-yggdrasil" - # Allow nginx access to yggdrasil socket - usermod -a -G yggdrasil www-data - BASE_DIR="$LAST_BASE" -fi \ No newline at end of file +fi From de813a367313e4e7cb042e25d3b8afa96d8dadf6 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 20:50:09 -0500 Subject: [PATCH 081/162] force confinue if path exists --- scripts/prometheus-node-exporter/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/prometheus-node-exporter/install b/scripts/prometheus-node-exporter/install index cb84fb797..f61b620fe 100755 --- a/scripts/prometheus-node-exporter/install +++ b/scripts/prometheus-node-exporter/install @@ -22,7 +22,7 @@ if [[ ! -f "/usr/local/bin/node_exporter" ]]; then rm -rf "$BASE_DIR/tmp" fi -sudo mkdir /var/lib/node_exporter/ +sudo mkdir /var/lib/node_exporter/ || true sudo mkdir /opt/tomesh/ || true sudo cp "$BASE_DIR/nodestats-tomesh.py" "/opt/tomesh/nodestats-tomesh.py" From 7a59b30c36b60993cfd69b7374a964a2be11c2a5 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 21:18:01 -0500 Subject: [PATCH 082/162] IPFS no pin fix (#287) --- scripts/ipfs-pi-stream/process-stream.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/ipfs-pi-stream/process-stream.sh b/scripts/ipfs-pi-stream/process-stream.sh index 3a8c3ae25..8650cb6dd 100755 --- a/scripts/ipfs-pi-stream/process-stream.sh +++ b/scripts/ipfs-pi-stream/process-stream.sh @@ -1,7 +1,7 @@ #!/bin/bash -HLS_TIME=15 -M3U8_SIZE=10 +HLS_TIME=40 +M3U8_SIZE=3 IPFS_GATEWAY="https://ipfs.io" # Load settings @@ -17,7 +17,7 @@ function startFFmpeg() { # Stream Raspberry Pi Camera ffmpeg -f video4linux2 -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 -vcodec copy -hls_time "${HLS_TIME}" "${what}.m3u8" > ~/ffmpeg.log 2>&1 - + # Stream FM Station from a SDR module (see contrib/pi-stream to install drivers) # Frequency ends in M IE 99.9M # rtl_fm -f 99.9M -M fm -s 170k -A std -l0 -E deemp -r 44.1k | ffmpeg -r 15 -loop 1 -i ../audio.jpg -f s16le -ac 1 -i pipe:0 -c:v libx264 -tune stillimage -preset ultrafast -hls_time "${HLS_TIME}" "${what}.m3u8" > ~/ffmpeg 2>&1 @@ -44,14 +44,14 @@ startFFmpeg & while true; do #TODO# Fix this one # shellcheck disable=SC2086,SC2012 - nextfile=$(ls -tr ${what}*.ts 2>/dev/null | tail -n 1) + nextfile=$(ls -tr ${what}*.ts 2>/dev/null | head -n 1) if ! [ -z "${nextfile}" ]; then # Check if the next file on the list is still being written to by ffmpeg if lsof "${nextfile}" | grep -1 ffmpeg; then # Wait for file to finish writing # If not finished in 45 seconds something is wrong, timeout - inotifywait -e close_write "${nextfile}" -t 45 + inotifywait -e close_write "${nextfile}" -t ${HLS_TIME} fi # Grab the timecode from the m3u8 file so we can add it to the log @@ -80,12 +80,12 @@ while true; do time=$(date "+%F-%H-%M-%S") # Add ts file to IPFS - ret=$(ipfs add "${nextfile}" 2>/dev/null > ~/tmp.txt; echo $?) + ret=$(ipfs add --pin=false "${nextfile}" 2>/dev/null > ~/tmp.txt; echo $?) attempts=5 until [[ ${ret} -eq 0 || ${attempts} -eq 0 ]]; do # Wait and retry - sleep 1 - ret=$(ipfs add "${nextfile}" 2>/dev/null > ~/tmp.txt; echo $?) + sleep 0.5 + ret=$(ipfs add --pin=false "${nextfile}" 2>/dev/null > ~/tmp.txt; echo $?) attempts=$((attempts-1)) done if [[ ${ret} -eq 0 ]]; then From 437024f9151860ab2eb3e4239b8158df13e4166f Mon Sep 17 00:00:00 2001 From: makeworld <25111343+makeworld-the-better-one@users.noreply.github.com> Date: Mon, 11 Feb 2019 21:24:42 -0500 Subject: [PATCH 083/162] Yggdrasil subnetting (#269) * Setup yggdrasil subnetting * Used ::1/64 subnet address when needed * Firewall update - Yggdrasil Client (#266) * Incorrect protocol module combination * Reject all packets for yggdrasil clients * Added group for ygg client for easy management * Added sample line * Used tmp file for sed, reverted status yggdrasil change * Added module docs, moved FAQ, and removed firewall comment * Added windows and mac IP instructions * Initial modules example [ygg] (#270) * Initial modules example * Update MODULES.md * Update MODULES.md * Spelling and grammar fixes Also changed a few things that I think are clearer. * Fixes fc00::/8 * Update rules.v6 [ygg] (#272) * Update rules.v6 * yggdrasil uses TCP not UDP * Remove comment * Made req. changes, added docs, add firewall commenting * Fixed some md spacing * Disables NATing for clients running Yggdrasil or CJDNS already * Update nat.sh * Remove errant anti-NAT rules * cp to mv --- README.md | 38 ++-------- FAQ.md => docs/FAQ.md | 0 docs/MODULES.md | 150 ++++++++++++++++++++++++++++++++++++++ scripts/firewall/rules.v4 | 2 +- scripts/firewall/rules.v6 | 49 ++++++++++--- scripts/hostapd/install | 27 +++++-- scripts/hostapd/nat.sh | 1 - 7 files changed, 215 insertions(+), 52 deletions(-) rename FAQ.md => docs/FAQ.md (100%) create mode 100644 docs/MODULES.md diff --git a/README.md b/README.md index 314278028..f0337c515 100644 --- a/README.md +++ b/README.md @@ -39,44 +39,16 @@ Many board that run [Armbian](https://www.armbian.com/) such as many models of O ``` $ wget https://raw.githubusercontent.com/tomeshnet/prototype-cjdns-pi/master/scripts/install && chmod +x install && ./install ``` - - The installation script can also install many optional features such as distributed applications and network analysis tools that are useful but non-essential to run a node. You can use flags to selectively enable them, or use the following command to install all optional features: - ``` - $ wget https://raw.githubusercontent.com/tomeshnet/prototype-cjdns-pi/master/scripts/install && chmod +x install && WITH_MESH_POINT=true WITH_AD_HOC=false WITH_WIFI_AP=true WITH_FIREWALL=true WITH_CJDNS_IPTUNNEL=true WITH_IPFS=true WITH_SSB=true WITH_SSB_WEB_PI=false WITH_PROMETHEUS_NODE_EXPORTER=true WITH_PROMETHEUS_SERVER=true WITH_GRAFANA=true WITH_H_DNS=true WITH_H_NTP=true WITH_EXTRA_TOOLS=true WITH_YRD=true ./install - ``` +## Modules -## Optional Features - -| Feature Flag | HTTP Service Port | Description | -| :------------------------------ | :--------------------------------------------- | :---------- | -| `WITH_MESH_POINT` | None | Set to `true` if you have a suitable USB WiFi adapter and want to configure it as a 802.11s Mesh Point interface. | -| `WITH_AD_HOC` | None | Set to `true` if you have a suitable USB WiFi adapter and want to configure it as a IBSS Ad-hoc interface. | -| `WITH_WIFI_AP` | None | Set to `true` if you have a Raspberry Pi 3 and want to configure the on-board WiFi as an Access Point. The default configuration routes all traffic to the Ethernet port `eth0`. | -| `WITH_FIREWALL` | None | Set to `true` if you want to enable a basic firewall on your node.| -| `WITH_CJDNS_IPTUNNEL` | None | Set to `true` if you want to use the cjdns iptunnel feature to set up an Internet gateway for your node. To configure as a server (exit Internet traffic for other nodes), create **/etc/cjdns.iptunnel.server** containing a newline-separated list of cjdns public keys of allowed clients. To configure as a client (use an exit server to access the Internet), create **/etc/cjdns.iptunnel.client** containing a newline-separated list of cjdns public keys of the gateway servers. You can only configure as one or the other, not both. | -| `WITH_IPFS` | **80**: HTTP-to-IPFS gateway at `/ipfs/HASH` | Set to `true` if you want to install [IPFS](https://ipfs.io). | -| `WITH_IPFS_PI_STREAM` | None | Set to `true` if you want to install Pi stream service to live stream your camera over IPFS. Requires a Raspberry Pi with camera module. Player interface at `/video-player` *Warning: By default the camera will start broadcasting after first reboot.* | -| `WITH_SSB` | | Set to `true` if you want to install [Scuttlebot (SSB)](https://github.com/ssbc/scuttlebot) a secure scuttlebutt daemon. | -| `WITH_SSB_PATCHFOO` | **80**: SSB web interface at `/patchfoo` | Set to `true` if you want to install [Patchfoo](https://github.com/ssbc/patchfoo), allows you to interact with the scuttlebot backend with a web interface. | -| `WITH_SSB_WEB_PI` | **80**: SSB web interface at `/ssb-web-pi` | Set to `true` if you want to install [SSB Web Pi](https://github.com/darkdrgn2k/ssb-web-pi), interact with scuttlebot api via a web interface. **EXPERIMENTAL** | -| `WITH_PROMETHEUS_NODE_EXPORTER` | **9100**: Node Exporter UI | Set to `true` if you want to install [Prometheus Node Exporter](https://github.com/prometheus/node_exporter) to report network metrics. | -| `WITH_PROMETHEUS_SERVER` | **9090**: Prometheus Server UI | Set to `true` if you want to install [Prometheus Server](https://github.com/prometheus/prometheus) to collect network metrics. *Requires Prometheus Node Exporter.* | -| `WITH_GRAFANA` | **3000**: Grafana UI (login: admin/admin) | Set to `true` if you want to install [Grafana](https://grafana.com) to display network metrics. *Requires Prometheus Server.* | -| `WITH_H_DNS` | None | Set to `true` if you want to use Hyperboria-compatible DNS servers: `fc4d:c8e5:9efe:9ac2:8e72:fcf7:6ce8:39dc`, `fc6e:691e:dfaa:b992:a10a:7b49:5a1a:5e09`, and `fc16:b44c:2bf9:467:8098:51c6:5849:7b4f` | -| `WITH_H_NTP` | None | Set to `true` if you want to use a Hyperboria-compatible NTP server: `fc4d:c8e5:9efe:9ac2:8e72:fcf7:6ce8:39dc` | -| `WITH_EXTRA_TOOLS` | None | Set to `true` if you want to install non-essential tools useful for network analysis: vim socat oping bmon iperf3 | -| `WITH_WATCHDOG` | None | Set to `true` if you want to enable hardware watchdog that will reset the device when the operating system becomes unresponsive. | -| `WITH_YRD` | None | Set to `true` if you want to enable [yrd](https://github.com/kpcyrd/yrd), a helpful command-line tool for cjdns. | - - -If you are connected to the WiFi Access Point, all HTTP services are available via `http://10.0.0.1:PORT` as well as the cjdns IPv6. To connect with the cjdns address, first note your node's fc00::/8 address from `status`, then navigate to `http://[fcaa:bbbb:cccc:dddd:eeee:0000:1111:2222]:PORT` from your browser. +During the installation, you may be able to pick a profile, or choose between many modules. To learn what each module is for, look at [MODULES.md](./docs/MODULES.md). This is important for the installation. ## Check Status 1. Give the Pi about 15 seconds to reboot and SSH back into it. You should find the status of your mesh node automatically printed. You can also print this anytime by running `status`. -1. Verify that **cjdns Service** is active, and **Mesh Interface** (if applicable). The **NODE** section should display a single IPv6 address, that's the identity of your Pi in the cjdns mesh. The **PEERS** section should indicate a list of IPv6 addresses that are active peers to your node. This list will be empty, until you have another nearby node with the same set up. +2. Verify that **cjdns Service** is active, and **Mesh Interface** (if applicable). The **NODE** section should display a single IPv6 address, that's the identity of your Pi in the cjdns mesh. The **PEERS** section should indicate a list of IPv6 addresses that are active peers to your node. This list will be empty, until you have another nearby node with the same set up. ## Network Benchmark @@ -141,8 +113,8 @@ To add a new module, use **scripts/ipfs/** as an example to: ## Notes -* We keep a list of [Frequently Asked Questions](./FAQ.md). Feel free to add to this list with the issues you experienced on your boards. +* We keep a list of [Frequently Asked Questions](./docs/FAQ.md). Feel free to add to this list with the issues you experienced on your boards. * Your computer can be a node too! It will mesh with the Pi's over your router. See the [cjdns repository](https://github.com/cjdelisle/cjdns) on how to set this up. -* Original plan for this repository and early benchmark results are available in [the doc folder](https://github.com/tomeshnet/prototype-cjdns-pi/blob/master/docs/). +* Original plan for this repository and early benchmark results are available in [the doc folder](./docs). diff --git a/FAQ.md b/docs/FAQ.md similarity index 100% rename from FAQ.md rename to docs/FAQ.md diff --git a/docs/MODULES.md b/docs/MODULES.md new file mode 100644 index 000000000..ab01faf9c --- /dev/null +++ b/docs/MODULES.md @@ -0,0 +1,150 @@ +# Modules Documentation + +A short summary of each module is directly below. Documentation for specific abilities of modules, or reference commands are further below. + +## Command-line flags + +| Feature Flag | HTTP Service Port | Description | +| :------------------------------ | :--------------------------------------------- | :---------- | +| `WITH_MESH_POINT` | None | Set to `true` if you have a suitable USB WiFi adapter and want to configure it as a 802.11s Mesh Point interface. | +| `WITH_AD_HOC` | None | Set to `true` if you have a suitable USB WiFi adapter and want to configure it as a IBSS Ad-hoc interface. | +| `WITH_WIFI_AP` | None | Set to `true` if you have a Raspberry Pi 3 and want to configure the on-board WiFi as an Access Point. The default configuration routes all traffic to the Ethernet port `eth0`. | +| `WITH_FIREWALL` | None | Set to `true` if you want to enable a basic firewall on your node.| +| `WITH_CJDNS_IPTUNNEL` | None | Set to `true` if you want to use the cjdns iptunnel feature to set up an Internet gateway for your node. To configure as a server (exit Internet traffic for other nodes), create **/etc/cjdns.iptunnel.server** containing a newline-separated list of cjdns public keys of allowed clients. To configure as a client (use an exit server to access the Internet), create **/etc/cjdns.iptunnel.client** containing a newline-separated list of cjdns public keys of the gateway servers. You can only configure as one or the other, not both. | +| `WITH_IPFS` | **80**: HTTP-to-IPFS gateway at `/ipfs/HASH` | Set to `true` if you want to install [IPFS](https://ipfs.io). | +| `WITH_IPFS_PI_STREAM` | None | Set to `true` if you want to install Pi stream service to live stream your camera over IPFS. Requires a Raspberry Pi with camera module. Player interface at `/video-player` *Warning: By default the camera will start broadcasting after first reboot.* | +| `WITH_SSB` | | Set to `true` if you want to install [Scuttlebot (SSB)](https://github.com/ssbc/scuttlebot) a secure scuttlebutt daemon. | +| `WITH_SSB_PATCHFOO` | **80**: SSB web interface at `/patchfoo` | Set to `true` if you want to install [Patchfoo](https://github.com/ssbc/patchfoo), allows you to interact with the scuttlebot backend with a web interface. | +| `WITH_SSB_WEB_PI` | **80**: SSB web interface at `/ssb-web-pi` | Set to `true` if you want to install [SSB Web Pi](https://github.com/darkdrgn2k/ssb-web-pi), interact with scuttlebot api via a web interface. **EXPERIMENTAL** | +| `WITH_PROMETHEUS_NODE_EXPORTER` | **9100**: Node Exporter UI | Set to `true` if you want to install [Prometheus Node Exporter](https://github.com/prometheus/node_exporter) to report network metrics. | +| `WITH_PROMETHEUS_SERVER` | **9090**: Prometheus Server UI | Set to `true` if you want to install [Prometheus Server](https://github.com/prometheus/prometheus) to collect network metrics. *Requires Prometheus Node Exporter.* | +| `WITH_GRAFANA` | **3000**: Grafana UI (login: admin/admin) | Set to `true` if you want to install [Grafana](https://grafana.com) to display network metrics. *Requires Prometheus Server.* | +| `WITH_H_DNS` | None | Set to `true` if you want to use Hyperboria-compatible DNS servers: `fc4d:c8e5:9efe:9ac2:8e72:fcf7:6ce8:39dc`, `fc6e:691e:dfaa:b992:a10a:7b49:5a1a:5e09`, and `fc16:b44c:2bf9:467:8098:51c6:5849:7b4f` | +| `WITH_H_NTP` | None | Set to `true` if you want to use a Hyperboria-compatible NTP server: `fc4d:c8e5:9efe:9ac2:8e72:fcf7:6ce8:39dc` | +| `WITH_EXTRA_TOOLS` | None | Set to `true` if you want to install non-essential tools useful for network analysis: vim socat oping bmon iperf3 | +| `WITH_WATCHDOG` | None | Set to `true` if you want to enable hardware watchdog that will reset the device when the operating system becomes unresponsive. | +| `WITH_YRD` | None | Set to `true` if you want to enable [yrd](https://github.com/kpcyrd/yrd), a helpful command-line tool for cjdns. | +| `WITH_YGGDRASIL` | None | Set to `true` if you want to install [Yggdrasil](https://yggdrasil-network.github.io/), an alternate and possibly more efficient mesh routing software than CJDNS. | + +To install all optional modules (not recommended), run the following command: + +``` +$ wget https://raw.githubusercontent.com/tomeshnet/prototype-cjdns-pi/master/scripts/install && chmod +x install && WITH_MESH_POINT=true WITH_AD_HOC=false WITH_WIFI_AP=true WITH_FIREWALL=true WITH_CJDNS_IPTUNNEL=true WITH_IPFS=true WITH_SSB=true WITH_SSB_WEB_PI=true WITH_PROMETHEUS_NODE_EXPORTER=true WITH_PROMETHEUS_SERVER=true WITH_GRAFANA=true WITH_H_DNS=true WITH_H_NTP=true WITH_EXTRA_TOOLS=true WITH_WATCHDOG=true WITH_YRD=true ./install +``` + +## CJDNS +Cjdns (Caleb James DeLisle's Network Suite) is a networking protocol and reference implementation. It is founded on the ideology that networks should be easy to set up, protocols should scale smoothly, and security should be built in by default. + +CJDNS uses cryptography to self-assign IPv6 address in the fc00::/8 subnet and will automatically peer with other nodes connected via Layer2 ethernet, broadcasts or configured UDP tunnels. + +For more information please see the [CJDNS FAQ](https://github.com/cjdelisle/cjdns/blob/master/doc/faq/general.md). + +To modify the ports that are accessable from CJDNS modify the `cjdns` *table* in the IPv6 firewall config file. See the [**Firewall**](#firewall) section for more details. + +## Yggdrasil +Yggdrasil is another piece of mesh routing software similar to CJDNS, but with potentially better performance and more active development. For more info visit the [website](https://yggdrasil-network.github.io). + +### Yggdrasil subnetting + +Yggdrasil will give each node (like your Pi, for example) an IPv6 address, but it can also give each node a subnet to distribute to its clients. This means that if you connect to the WiFi of your Pi, your device can get a unique Yggdrasil address, with all the benefits it provides. These include being able to access your device directly, without being NATed or blocked. + +However, the Pi does have a firewall, so various commands need be run to allow access to clients. By default all Yggdrasil client access is blocked. See [**Firewall/IPv6/Yggdrasil Clients**](#yggdrasil-clients) to learn how to change that. + +## IPFS +IPFS stands for Interplanetary File System. It is an open-source, peer-to-peer distributed hypermedia protocol that aims to function as a ubiquitous file system for all computing devices. + +This module will install IPFS under the user where the script runs allowing you to access IPFS resouces both directly from the command line, and through the gateway available at /ipfs/ + +## Firewall + +The firewall module installes a basic firewall for your device. It will block all ports that were not meant to be open. By default there are no ports blocked from the Wireless Access Point interface (`wlan-ap`). + +### Applying changes +After making any changes to files as outlined below, run `sudo systemctl restart hostapd` to apply the changes. This will take down the Pi's WiFi for a moment, but it will come back up on it's own. SSH sessions will freeze, but should reconnect on their own as well. + +### IPv4 +Default open ports to the device are below. Since both CJDNS and Yggdrasil use IPv6, these ports are open only for LAN or WiFi usage. + +| Port | Protocol | Policy | Description | +| :---- | :------ | :----- | :------------------------ | +| 67:68 | UDP | Accept | DHCP Client/Server | +| 22 | UDP | Accept | SSH | +| 53 | TCP/UDP | Accept | DNS Server | +| 80 | TCP | Accept | HTTP | +| 443 | TCP | Accept | SSH | +| 9100 | TCP | Accept | NodeExporter | +| 9090 | TCP | Accept | Prometheus Server | +| 3000 | TCP | Accept | Grafana | +| 5201 | TCP | Accept | IPerf3 | +| 4001 | TCP | Accept | IPFS Swarm port | + +#### Change open ports + +To change the open ports you can edit the IPv4 configuration file located at `/etc/iptables/rules.v4` + +Remove or comment out (`#`) the lines of the ports that you wish to close and add new lines for additional ports you wish to open. + +Likely you will not need to edit this file as much, if you are interested in opening mesh ports look at the **IPv6** section directly below. + +These are standard `iptables` rules. The basic syntax is as follows: + +`-A INPUT -j ACCEPT -p --dport ` + +`protocol` - either `tcp` or `udp`, not required but recommended + +`port` - Port you wish to open between 1-65535 + + +### IPv6 + +Default open ports to the device over IPv6 are + +| Port | Protocol | Policy | Description | +| :---- | :------ | :----- | :------------------------ | +| 67:68 | UDP | Accept | DHCP Client/Server | +| 22 | UDP | Accept | SSH | +| 53 | TCP/UDP | Accept | DNS Server | +| 80 | TCP | Accept | HTTP | +| 443 | TCP | Accept | SSH | +| 9100 | TCP | Accept | NodeExporter | +| 5201 | TCP | Accept | IPerf3 | +| 4001 | TCP | Accept | IPFS Swarm port | + +#### Change open ports + +To change the open ports you can edit the IPv6 configuration file located at `/etc/iptables/rules.v6` + +Remove or comment out (#) the lines of the ports that you wish to close and add new lines for additional ports you wish to open. + +These are standard `ip6tables` rules. The basic syntax is as follows: + +`-A -j ACCEPT -p --dport ` + +`table` - `CJDNS` or `YGGDRASIL` for opening the port to CJDNS or YGGDRASIL, `YGGCLIENT` for opening up access to [**Yggdrasil Clients**](#yggdrasil-clients), and `INPUT` to open the port up to all of IPv6. + +`protocol` - either `tcp` or `udp`, not required but recommended + +`port` - Port you wish to open between 1-65535 + +Make sure to put your rules in the right section of the file, there are different ones depending on the table, with comments defining each section. + +#### Yggdrasil Clients +Below are some different scenarios for opening up Yggdrasil clients. You will need to put these rules in `/etc/iptables/rules.v6`, in the Yggdrasil client rules section indicated by a comment. + + - **One client, one port** + +Doing this is not recommended, as Yggdrasil clients IP addresses may change. + + - **All clients, one port** + +`-A YGGCLIENT -j ACCEPT -p --dport ` + +Specifying a protocol is not required, but recommended. + +- **All clients, all ports** + +`-A YGGCLIENT -j ACCEPT` + +If you use this rule, there is no point in having any other Yggdrasil client rules in the file. + +You can specify a protocol, but that would limit the ports that are open. \ No newline at end of file diff --git a/scripts/firewall/rules.v4 b/scripts/firewall/rules.v4 index 2d22d5457..875327239 100644 --- a/scripts/firewall/rules.v4 +++ b/scripts/firewall/rules.v4 @@ -14,7 +14,7 @@ -A INPUT -p tcp -m tcp --dport 3000 -j ACCEPT -A INPUT -p tcp -m tcp --dport 4001 -j ACCEPT -A INPUT -p tcp -m tcp --dport 5201 -j ACCEPT --A INPUT -p tcp -m udp --dport 8008 -j ACCEPT +-A INPUT -p udp -m udp --dport 8008 -j ACCEPT -A INPUT -p tcp -m tcp --dport 9090 -j ACCEPT -A INPUT -p tcp -m tcp --dport 9100 -j ACCEPT -A INPUT -i wlan+ -j ACCEPT diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index e86005e16..7fe6021e3 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -2,18 +2,49 @@ :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] +:CJDNS - [0:0] +:YGGDRASIL - [0:0] +:YGGCLIENT - [0:0] -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT --A INPUT -j ACCEPT -p tcp --dport 22 --A INPUT -j ACCEPT -p tcp --dport 80 --A INPUT -j ACCEPT -p tcp --dport 443 --A INPUT -j ACCEPT -p tcp --dport 3000 --A INPUT -j ACCEPT -p tcp --dport 5201 --A INPUT -j ACCEPT -p tcp --dport 4001 --A INPUT -j ACCEPT -p tcp --dport 9090 --A INPUT -j ACCEPT -p tcp --dport 9100 --A INPUT -j ACCEPT -p udp --dport 12345 + +# Raw INPUT rules needed for Yggdrasil - DO NOT EDIT +-A INPUT -j ACCEPT -p tcp --dport 12345 -A INPUT -j ACCEPT -p udp --dport 9001 -d ff02::114 + +# Any new raw INPUT rules go here + + +# DO NOT EDIT - Redirect to named tables +-A INPUT -i tun0 -d fc00::/8 -j CJDNS +-A INPUT -i ygg0 -d 200::/8 -j YGGDRASIL -A INPUT -j REJECT --reject-with icmp6-port-unreachable +-A FORWARD -i ygg0 -d 300::/8 -j YGGCLIENT +-A FORWARD -j REJECT --reject-with icmp6-port-unreachable + +# CJDNS rules +-A CJDNS -j ACCEPT -p tcp --dport 22 +-A CJDNS -j ACCEPT -p tcp --dport 80 +-A CJDNS -j ACCEPT -p tcp --dport 443 +-A CJDNS -j ACCEPT -p tcp --dport 3000 +-A CJDNS -j ACCEPT -p tcp --dport 5201 +-A CJDNS -j ACCEPT -p tcp --dport 4001 +-A CJDNS -j ACCEPT -p tcp --dport 9090 +-A CJDNS -j ACCEPT -p tcp --dport 9100 + +# Yggdrasil rules +-A YGGDRASIL -j ACCEPT -p tcp --dport 22 +-A YGGDRASIL -j ACCEPT -p tcp --dport 80 +-A YGGDRASIL -j ACCEPT -p tcp --dport 443 +-A YGGDRASIL -j ACCEPT -p tcp --dport 3000 +-A YGGDRASIL -j ACCEPT -p tcp --dport 5201 +-A YGGDRASIL -j ACCEPT -p tcp --dport 4001 +-A YGGDRASIL -j ACCEPT -p tcp --dport 9090 +-A YGGDRASIL -j ACCEPT -p tcp --dport 9100 + +# Yggdrasil client (YGGCLIENT) rules go here + + +# End, put nothing below this COMMIT diff --git a/scripts/hostapd/install b/scripts/hostapd/install index 1659b1fc5..b3e72f603 100755 --- a/scripts/hostapd/install +++ b/scripts/hostapd/install @@ -13,10 +13,10 @@ H_DNS_SERVER_2="fc16:b44c:2bf9:467:8098:51c6:5849:7b4f" I_DNS_SERVER_0="1.1.1.1" I_DNS_SERVER_1="1.0.0.1" -# Create radvd.conf before installing radvd, installation fails without it -if ! [ -f /etc/radvd.conf ]; then - sudo cp "$BASE_DIR/radvd.conf" /etc/radvd.conf -fi +# Yggdrasil subnetting +YGG_SUBNET=$(sudo yggdrasilctl getSelf | grep "IPv6 subnet" | awk '{print $3}') +# End subnet with ::, so either 1/64 or /64 can be added to end later as needed +YGG_SUBNET=${YGG_SUBNET:0:-3} # Install packages to run IEEE 802.11 Access Point sudo apt-get install hostapd radvd dnsmasq iptables -y @@ -37,7 +37,13 @@ echo " netmask 255.255.255.0" | sudo tee --append /etc/network/interfaces > / echo " network 10.0.0.0" | sudo tee --append /etc/network/interfaces > /dev/null echo " broadcast 10.0.0.255" | sudo tee --append /etc/network/interfaces > /dev/null echo "iface wlan-ap inet6 static" | sudo tee --append /etc/network/interfaces > /dev/null -echo " address fdfc::2" | sudo tee --append /etc/network/interfaces > /dev/null + +if [ "$(which yggdrasil)" ]; then + echo " address ${YGG_SUBNET}1/64" | sudo tee --append /etc/network/interfaces > /dev/null +else + echo " address fdfc::2" | sudo tee --append /etc/network/interfaces > /dev/null +fi + echo " netmask 64" | sudo tee --append /etc/network/interfaces > /dev/null echo "" | sudo tee --append /etc/network/interfaces > /dev/null echo "allow-hotplug eth0" | sudo tee --append /etc/network/interfaces > /dev/null @@ -110,8 +116,13 @@ if [ -f /etc/dhcpcd.conf ]; then sudo echo "denyinterfaces wlan-ap" | sudo tee --append /etc/dhcpcd.conf > /dev/null fi -# Configure IPv6 router advertisement with radvd -sudo cp "$BASE_DIR/radvd.conf" /etc/radvd.conf +# Setup radvd +sudo cp "$BASE_DIR/radvd.conf" /tmp +if [ "$(which yggdrasil)" ]; then + # Setup Yggdrasil radvd prefix for subnetting + sed -i "s/fdfc::\/64/${YGG_SUBNET}\/64/" /tmp/radvd.conf +fi +sudo mv /tmp/radvd.conf /etc sudo systemctl daemon-reload sudo systemctl enable radvd.service sudo systemctl start radvd.service @@ -144,4 +155,4 @@ fi if ! grep -q rfkill /etc/rc.local; then sudo sed -i 's/^exit 0/rfkill unblock wifi \&\& service hostapd restart\nexit 0/' /etc/rc.local -fi \ No newline at end of file +fi diff --git a/scripts/hostapd/nat.sh b/scripts/hostapd/nat.sh index d5fbf0349..a76a2b4ac 100755 --- a/scripts/hostapd/nat.sh +++ b/scripts/hostapd/nat.sh @@ -9,4 +9,3 @@ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE # Allow all IPv6 traffic routed out tun0 and ygg0 to be masked with their respective external IP address ip6tables -t nat -A POSTROUTING -o tun0 -j MASQUERADE -ip6tables -t nat -A POSTROUTING -o ygg0 -j MASQUERADE From a42b861a8fdd7a13e45e8254e487eefc4accb28d Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 21:32:39 -0500 Subject: [PATCH 084/162] Support for mk802ii (#290) * Added cjdns compile support for MK802ii * added MK802ii --- README.md | 2 +- scripts/install2 | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f0337c515..60cf38106 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ List of tested hardware: | Rock64 | [Armbian](https://dl.armbian.com/rock64/) | 255k, 168K | 94 Mbps | 3 | 10/100/1000 | 1 USB 3.0, Gigabit Eth | | Pine64 | [Armbian](https://dl.armbian.com/pine/nightly/) | 227k, 151k | 78 Mbps | 2 | 10/100/1000 | Gigabit Eth | | EspressoBin | [Armbian](https://dl.armbian.com/espressobin/) | 186k, 128K | 73 Mbps | 2 | 10/100/1000 | 1 USB 3.0, 3x Gigabit Eth, Sata, mPCIE. Use stable and apt-get upgrade after boot | - +| MK802ii | Debian | 30k, 40k | 25Mbps | | | Android box. Single Core. Onboard wifi does Meshpoint | ## Development You can install from a specific tag or branch, such as `develop`, with: diff --git a/scripts/install2 b/scripts/install2 index 339c07193..58c4172fb 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -146,8 +146,10 @@ BOARD_REVISION="?" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 ./do" ##TODO## Possibly use /sys/firmware/devicetree/base/model +BOARD_MODEL=$(cat /sys/firmware/devicetree/base/model) BOARD_HARDWARE=$(grep Hardware /proc/cpuinfo | awk '{print $3}' | head -n 1) + # Flag to identify if board can support on-board AP. Default to false. SUPPORT_HOSTAP=false # Flag to identify if board can support on-board hardware watchdog. @@ -161,6 +163,11 @@ if [[ -z "$BOARD_HARDWARE" ]]; then BOARD_HARDWARE="$(grep "BOARD=" /etc/armbian-image-release | awk -F '=' '{print $2}' | tr -d \" | sed 's/Orange Pi //g')" fi +if [[ "$BOARD_MODEL" == "MK802ii" ]]; then + BOARD_REVISION="experimental" + CJDNS_BUILD_CMD="sudo NO_TEST=1 CFLAGS=\"-O2\" ./do" +fi + if [[ "$BOARD_HARDWARE" == 'Allwinner' || "$BOARD_HARDWARE" == 'Generic' ]]; then # Stop unattended upgrade that will block apt-get requests on some armbian boards sudo service unattended-upgrades stop || true From 6a6750a6afe88be4d86097c893427b7b32bc460d Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 21:35:36 -0500 Subject: [PATCH 085/162] Status - added sudo to support debin (#288) * added sudo to support debian non root user --- scripts/status | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/status b/scripts/status index a20d8dd37..f0b6c3b90 100755 --- a/scripts/status +++ b/scripts/status @@ -22,9 +22,9 @@ else fi if [ "$(which mesh-point)" ]; then - ints=$(iw dev | grep Interface | awk '{print $2}') + ints=$(sudo iw dev | grep Interface | awk '{print $2}') while read -r line; do - mp=$(iw dev $line info | grep "type mesh point") + mp=$(sudo iw dev $line info | grep "type mesh point") if [ "$mp" ]; then mpint=$line fi @@ -36,9 +36,9 @@ if [ "$(which mesh-point)" ]; then fi fi if [ "$(which mesh-adhoc)" ]; then - ints=$(iw dev | grep Interface | awk '{print $2}') + ints=$(sudo iw dev | grep Interface | awk '{print $2}') while read -r line; do - mp=$(iw dev $line info | grep "type IBSS") + mp=$(sudo iw dev $line info | grep "type IBSS") if [ "$mp" ]; then mpint=$line fi @@ -120,7 +120,7 @@ if [ "$(which cjdroute)" ] && [ "$(ip addr | grep tun0)" ] ; then fi if [ "$(which yggdrasil)" ]; then - YGGIP=$(ifconfig ygg0 | grep -E 'inet6 2[0-9a-fA-F]{2}:' | awk '{print $2}') + YGGIP=$(sudo ifconfig ygg0 | grep -E 'inet6 2[0-9a-fA-F]{2}:' | awk '{print $2}') echo -e '---------------------------------------' echo -e 'YGGDRASIL NODE' echo -e $YGGIP From c63d2ccc9081bf7356ee27626bbc9f3415842ac5 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 21:40:01 -0500 Subject: [PATCH 086/162] Support for Orange Pi Lite access point (#280) * add firmware install * Added rtl8189fs driver for access point * Added lite access point support --- scripts/hostapd/install | 2 +- scripts/install2 | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/hostapd/install b/scripts/hostapd/install index b3e72f603..9afc1058d 100755 --- a/scripts/hostapd/install +++ b/scripts/hostapd/install @@ -142,7 +142,7 @@ for wlan in $(find /sys/class/net -maxdepth 1 -name 'wlan*' | xargs -0 basename) driverPath=$(readlink "/sys/class/net/$wlan/device/driver") driver=$(basename "$driverPath") # mac="$(cat /sys/class/net/$wlan/address)" - if [[ "$driver" == "xradio_wlan" || "$driver" == "brcm80211" || "$driver" == "brcmfmac" ]]; then + if [[ "$driver" == "xradio_wlan" || "$driver" == "brcm80211" || "$driver" == "brcmfmac" || "$driver" == "rtl8189fs" ]]; then echo "SUBSYSTEM==\"net\", ACTION==\"add\", DRIVERS==\"$driver\", ATTR{dev_id}==\"0x0\", ATTR{type}==\"1\", KERNEL==\"wlan*\", NAME=\"wlan-ap\"" | sudo tee /etc/udev/rules.d/70-persistent-net.rules fi diff --git a/scripts/install2 b/scripts/install2 index 58c4172fb..cce0a9a56 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -182,6 +182,10 @@ if [[ "$BOARD_HARDWARE" == 'Allwinner' || "$BOARD_HARDWARE" == 'Generic' ]]; the fi SUPPORT_WATCHDOG=true fi + if [[ "$BOARD_NAME" == "Lite" ]]; then + SUPPORT_HOSTAP=true + SUPPORT_WATCHDOG=true + fi #TODO# -O2 workaround. Needs to be resolved. CJDNS_BUILD_CMD="sudo Seccomp_NO=1 CFLAGS=\"-O2 -s -static -Wall -march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -fomit-frame-pointer -marm\" ./do" CJDNS_PACKAGE="cjdns-neon-v4.deb" @@ -200,6 +204,7 @@ elif [[ "$BOARD_HARDWARE" == 'nanopineo2' || "$BOARD_HARDWARE" == 'sun50iw1p1' | if [[ "$BOARD_HARDWARE" == "orangepizeroplus2-h5" ]]; then SUPPORT_HOSTAP=true fi + else BOARD_FAMILY="Raspberry Pi" BOARD_REVISION="$(sed -rn 's/Revision\s+\:\s+([0-9a-z_\-\s\,\(\)]+)/\1/p' /proc/cpuinfo)" @@ -244,6 +249,10 @@ echo -e "\e[1;32mStarting installation on ${BOARD_FAMILY} ${BOARD_NAME} (${BOARD # Normalize OS environment +# Install firmware package for wireless drivers +# #TODO# detect armbian +sudo apt-get install -y armbian-firmware-full || true + # Enable password-less sudo on Armbian sudo sed -i 's/ALL=(ALL:ALL) ALL/ALL=(ALL:ALL) NOPASSWD:ALL/' /etc/sudoers From a75ff6e65f9180b611a43a4dbb348c5f6b6b92da Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 21:49:24 -0500 Subject: [PATCH 087/162] Move functions to seperate file (#289) * Move functions to seperate file --- scripts/functions.sh | 137 +++++++++++++++++++++++++++++++++++++++++++ scripts/install2 | 135 +----------------------------------------- 2 files changed, 139 insertions(+), 133 deletions(-) create mode 100644 scripts/functions.sh diff --git a/scripts/functions.sh b/scripts/functions.sh new file mode 100644 index 000000000..1789b30cd --- /dev/null +++ b/scripts/functions.sh @@ -0,0 +1,137 @@ +#!/bin/bash +# shellcheck disable=SC2034 +true + +dialogGlobalParams="--backtitle Installation --ascii-lines" +# Ask if module is to be enabled if not defined +# askModule [default answer] +function askModule { + # Define standard behaviour (default yes) + askPrompt="[Y/n]" + nonDefaultMatch="Nn" + defaultValue=true + nonDefaultValue=false + dialogParam="" + + # Define alternative behaviour (default no) + if [ "$3" == "n" ]; then + askPrompt="[y/N]" + nonDefaultMatch="Yy" + nonDefaultValue=true + defaultValue=false + dialogParam=" --defaultno " + fi + + # This reads variable repersented by the string + eval "res=\$$1" + + if [ "$(checkModule 'WITH_DIALOG')" ]; then + if [ -z "$res" ] || [ "$res" != "true" ] && [ "$res" != "false" ]; then + # Do not stop exec on non 0 return values + set +e + # shellcheck disable=SC2086 + dialog $dialogGlobalParams $dialogParam --title "$2" --yesno "Install $2?" 6 55 + response=$? + # Return to previous setting + set -e + + case $response in + 0) res="true";; + 1) res="false";; + 255) exit;; + esac + fi + else + if [ -z "$res" ] || [ "$res" != "true" ] && [ "$res" != "false" ]; then + read -p "Install $2 $askPrompt? " -n 1 -r + echo "" + if [[ $REPLY =~ ^[$nonDefaultMatch]$ ]]; then + res=$nonDefaultValue + else + res=$defaultValue + fi + fi + fi + if [ "$res" == "true" ]; then + echo -e "\e[1;32m$2 will be enabled\e[0m" + else + echo -e "\e[1;31m$2 will be skipped\e[0m" + fi + eval "$1=\$res" +} + +# Check to see if module is enabled +# checkModule +function checkModule { + eval "res=\$$1" + if [ ! -z "$res" ] && [ "$res" == "true" ]; then + echo "1" + else + echo "" + fi +} + +# Ask user to choose from a selection of items +# list is \n delimited. Each line formated as +# "x text" +# x - single capital character that will be returned +# text - description of item +# +# askSelection +# +# Result is stored in $dialogREPLY +dialogREPLY="" +function askSelection { + selection=$1 + dialogREPLY="" + default="$3" + if [ "$(checkModule 'WITH_DIALOG')" ]; then + selection=$(echo -e "$selection" | while read -r selected; do + selectedItem="${selected:0:1}" + selectedText="${selected:2}" + if [[ "${selected:0:1}" == "$default" ]]; then + echo "$selectedItem \"$selectedText\" on" + else + echo "$selectedItem \"$selectedText\" off" + fi + done) + echo "$selection" > /tmp/selectionList + + # shellcheck disable=SC2086 + dialog $dialogGlobalParams --radiolist "$2" 10 55 8 --file /tmp/selectionList 2> /tmp/res + rm -f selectionList + response=$(cat /tmp/res) + rm -f /tmp/res + + # Return if canceled + if [[ "$response" == "" ]]; then + exit 1 + fi + + # Set response variable + dialogREPLY="$response" + else + isValid="" + while [[ "$isValid" == "" ]]; do + echo "$2" + echo ------------------- + echo -e "$1" + echo ------------------- + read -p "Selection: " -n 1 -r + echo "" + if [[ "$REPLY" == "" ]] && [[ "$default" != "" ]]; then + REPLY="$default" + isValid=1 + else + REPLY=$(echo "$REPLY" | awk '{print toupper($0)}') + + isValid=$(echo -e "$selection" | while read -r selected; do + if [[ "${selected:0:1}" == "$REPLY" ]]; then + echo 1 + fi + done) + fi + done + dialogREPLY="$REPLY" + fi +} diff --git a/scripts/install2 b/scripts/install2 index cce0a9a56..aace1fded 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -5,139 +5,8 @@ set -e TAG_CJDNS=d2e55d58548d83940482fe1bbbe1fd36f7f1b4ef -dialogGlobalParams="--backtitle Installation --ascii-lines" -# Ask if module is to be enabled if not defined -# askModule [default answer] -function askModule { - # Define standard behaviour (default yes) - askPrompt="[Y/n]" - nonDefaultMatch="Nn" - defaultValue=true - nonDefaultValue=false - dialogParam="" - - # Define alternative behaviour (default no) - if [ "$3" == "n" ]; then - askPrompt="[y/N]" - nonDefaultMatch="Yy" - nonDefaultValue=true - defaultValue=false - dialogParam=" --defaultno " - fi - - # This reads variable repersented by the string - eval "res=\$$1" - - if [ "$(checkModule 'WITH_DIALOG')" ]; then - if [ -z "$res" ] || [ "$res" != "true" ] && [ "$res" != "false" ]; then - # Do not stop exec on non 0 return values - set +e - # shellcheck disable=SC2086 - dialog $dialogGlobalParams $dialogParam --title "$2" --yesno "Install $2?" 6 55 - response=$? - # Return to previous setting - set -e - - case $response in - 0) res="true";; - 1) res="false";; - 255) exit;; - esac - fi - else - if [ -z "$res" ] || [ "$res" != "true" ] && [ "$res" != "false" ]; then - read -p "Install $2 $askPrompt? " -n 1 -r - echo "" - if [[ $REPLY =~ ^[$nonDefaultMatch]$ ]]; then - res=$nonDefaultValue - else - res=$defaultValue - fi - fi - fi - if [ "$res" == "true" ]; then - echo -e "\e[1;32m$2 will be enabled\e[0m" - else - echo -e "\e[1;31m$2 will be skipped\e[0m" - fi - eval "$1=\$res" -} - -# Check to see if module is enabled -# checkModule -function checkModule { - eval "res=\$$1" - if [ ! -z "$res" ] && [ "$res" == "true" ]; then - echo "1" - else - echo "" - fi -} - -# Ask user to choose from a selection of items -# list is \n delimited. Each line formated as -# "x text" -# x - single capital character that will be returned -# text - description of item -# -# askSelection -# -# Result is stored in $dialogREPLY -dialogREPLY="" -function askSelection { - selection=$1 - dialogREPLY="" - default="$3" - if [ "$(checkModule 'WITH_DIALOG')" ]; then - selection=$(echo -e "$selection" | while read -r selected; do - selectedItem="${selected:0:1}" - selectedText="${selected:2}" - if [[ "${selected:0:1}" == "$default" ]]; then - echo "$selectedItem \"$selectedText\" on" - else - echo "$selectedItem \"$selectedText\" off" - fi - done) - echo "$selection" > /tmp/selectionList - - # shellcheck disable=SC2086 - dialog $dialogGlobalParams --radiolist "$2" 10 55 8 --file /tmp/selectionList 2> /tmp/res - rm -f selectionList - response=$(cat /tmp/res) - rm -f /tmp/res - - # Return if canceled - if [[ "$response" == "" ]]; then - exit 1 - fi - - # Set response variable - dialogREPLY="$response" - else - isValid="" - while [[ "$isValid" == "" ]]; do - echo "$2" - echo ------------------- - echo -e "$1" - echo ------------------- - read -p "Selection: " -n 1 -r - echo "" - if [[ "$REPLY" == "" ]] && [[ "$default" != "" ]]; then - REPLY="$default" - isValid=1 - else - REPLY=$(echo "$REPLY" | awk '{print toupper($0)}') - - isValid=$(echo -e "$selection" | while read -r selected; do - if [[ "${selected:0:1}" == "$REPLY" ]]; then - echo 1 - fi - done) - fi - done - dialogREPLY="$REPLY" - fi -} +# Common functions +source functions.sh # Get board information and set flags accordingly BOARD_FAMILY="Unknown" From 514e487e1269500e17039b73f7f1888fa99728b8 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 22:12:52 -0500 Subject: [PATCH 088/162] Added peers --- scripts/ipfs/install | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/scripts/ipfs/install b/scripts/ipfs/install index b0ab9204c..c14af6a23 100755 --- a/scripts/ipfs/install +++ b/scripts/ipfs/install @@ -7,10 +7,16 @@ set -e GO_IPFS_VERSION=v0.4.18 # Hyperborea connected peer used to bootstrap hyperborea only ipfs nodes +# DarkDrgn2k's peer IPFS_PEER_1="/ip6/fc6e:691e:dfaa:b992:a10a:7b49:5a1a:5e09/tcp/4001/ipfs/QmU6NeD2Uu34WKest1NZGvGmScLhN1zVo66K35GeE6Jft2" +# HeavyMetal's peer +IPFS_PEER_2="/ip6/ip6/fc6d:3961:6744:7d94:31ba:2bf3:30bf:ebab/tcp/4001/ipfs/QmRGk8DdMWy5P5xgUisnv7u4hV4WfgEhbxa6iGpviYGC7q" # Yggdrasil connected peer used to bootstrap hyperborea only ipfs nodes -IPFS_PEER_2="/ip6/301:4541:2f84:1188:216:3eff:fed5:a2df/tcp/4001/ipfs/QmWZpTdfETtpjJphVE1YbxMkUcL84idkg44Cq1XWSBNm7P" -IPFS_PEER_3="/ip6/200:98bf:d6df:e49a:f525:40bf:18d:ac45/tcp/4001/ipfs/QmU6NeD2Uu34WKest1NZGvGmScLhN1zVo66K35GeE6Jft2" +IPFS_PEER_3="/ip6/301:4541:2f84:1188:216:3eff:fed5:a2df/tcp/4001/ipfs/QmWZpTdfETtpjJphVE1YbxMkUcL84idkg44Cq1XWSBNm7P" +# DarkDrgn2k's peer +IPFS_PEER_4="/ip6/200:98bf:d6df:e49a:f525:40bf:18d:ac45/tcp/4001/ipfs/QmU6NeD2Uu34WKest1NZGvGmScLhN1zVo66K35GeE6Jft2" +# HeavyMetal's peer +IPFS_PEER_5="/ip6/201:3d73:dbf:da97:e008:2d29:3919:cdb1/tcp/4001/ipfs/QmRGk8DdMWy5P5xgUisnv7u4hV4WfgEhbxa6iGpviYGC7q" BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -44,6 +50,8 @@ sudo cp "$BASE_DIR/nodeinfo-ipfs" /opt/tomesh/nodeinfo.d/ipfs ipfs bootstrap add "$IPFS_PEER_1" ipfs bootstrap add "$IPFS_PEER_2" ipfs bootstrap add "$IPFS_PEER_3" +ipfs bootstrap add "$IPFS_PEER_4" +ipfs bootstrap add "$IPFS_PEER_5" # Download dependencies sudo apt-get install -y jq From be03f441d3277858b46f64fdd4ed93a77717d420 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 22:31:50 -0500 Subject: [PATCH 089/162] Corrected ip6 duplication --- scripts/ipfs/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ipfs/install b/scripts/ipfs/install index c14af6a23..8e3f066aa 100755 --- a/scripts/ipfs/install +++ b/scripts/ipfs/install @@ -10,7 +10,7 @@ GO_IPFS_VERSION=v0.4.18 # DarkDrgn2k's peer IPFS_PEER_1="/ip6/fc6e:691e:dfaa:b992:a10a:7b49:5a1a:5e09/tcp/4001/ipfs/QmU6NeD2Uu34WKest1NZGvGmScLhN1zVo66K35GeE6Jft2" # HeavyMetal's peer -IPFS_PEER_2="/ip6/ip6/fc6d:3961:6744:7d94:31ba:2bf3:30bf:ebab/tcp/4001/ipfs/QmRGk8DdMWy5P5xgUisnv7u4hV4WfgEhbxa6iGpviYGC7q" +IPFS_PEER_2="/ip6/fc6d:3961:6744:7d94:31ba:2bf3:30bf:ebab/tcp/4001/ipfs/QmRGk8DdMWy5P5xgUisnv7u4hV4WfgEhbxa6iGpviYGC7q" # Yggdrasil connected peer used to bootstrap hyperborea only ipfs nodes IPFS_PEER_3="/ip6/301:4541:2f84:1188:216:3eff:fed5:a2df/tcp/4001/ipfs/QmWZpTdfETtpjJphVE1YbxMkUcL84idkg44Cq1XWSBNm7P" # DarkDrgn2k's peer From 15e7e7efb07f610fb31ee1915f9589dad7ef03fd Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 22:45:30 -0500 Subject: [PATCH 090/162] Attempt to fix folder issue --- scripts/nginx/install | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/nginx/install b/scripts/nginx/install index 371cbce35..d14de933e 100755 --- a/scripts/nginx/install +++ b/scripts/nginx/install @@ -28,7 +28,8 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th # CJDNS peers mkdir "$BASE_DIR/tmp" git clone https://github.com/hamishcoleman/cjdns_tool.git "$BASE_DIR/tmp/cjdns_tool" - sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib/" "/var/www/html/cgi-bin/" + mkdir "/var/www/html/cgi-bin/lib/" || true + sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib/*" "/var/www/html/cgi-bin/lib/" rm -rf "$BASE_DIR/tmp" sudo cp "$BASE_DIR/peers-cjdns" "/var/www/html/cgi-bin/peers-cjdns" From 35723d927e030fc4dbf4115bcd1afd937f9b76ea Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 22:47:19 -0500 Subject: [PATCH 091/162] renamed scuttlebot to ssb-server --- scripts/ssb/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ssb/install b/scripts/ssb/install index 12b7bb1e2..3c01d1548 100755 --- a/scripts/ssb/install +++ b/scripts/ssb/install @@ -10,7 +10,7 @@ sudo apt-get install -y socat python-dev libtool python-setuptools autoconf auto # Install scuttlebot # sudo sudo is a hack to allow post-install scripts that drop one level of sudo and still be sudoed # otherwise you get permissions errors when it tries to write to root owned folders -sudo sudo npm install scuttlebot -g --unsafe-perm +sudo sudo npm install ssb-server -g --unsafe-perm # Store current user as sudo will change it currentUser=$USER From 82f0afb33f00e773627d01a659eb984b37eda4d6 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 23:20:10 -0500 Subject: [PATCH 092/162] Added update before apt-get install --- scripts/install2 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/install2 b/scripts/install2 index aace1fded..3b2e6b9b6 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -117,6 +117,7 @@ fi echo -e "\e[1;32mStarting installation on ${BOARD_FAMILY} ${BOARD_NAME} (${BOARD_REVISION})...\e[0m" # Normalize OS environment +sudo apt-get update -y # Install firmware package for wireless drivers # #TODO# detect armbian From 7048d86261b5698e01573609323f4635da0b6c52 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 23:27:32 -0500 Subject: [PATCH 093/162] Update install --- scripts/nginx/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/nginx/install b/scripts/nginx/install index d14de933e..cf35bda90 100755 --- a/scripts/nginx/install +++ b/scripts/nginx/install @@ -28,7 +28,7 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th # CJDNS peers mkdir "$BASE_DIR/tmp" git clone https://github.com/hamishcoleman/cjdns_tool.git "$BASE_DIR/tmp/cjdns_tool" - mkdir "/var/www/html/cgi-bin/lib/" || true + mkdir -p "/var/www/html/cgi-bin/lib/" || true sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib/*" "/var/www/html/cgi-bin/lib/" rm -rf "$BASE_DIR/tmp" sudo cp "$BASE_DIR/peers-cjdns" "/var/www/html/cgi-bin/peers-cjdns" From 28fb651806c7b61ef772960bab09438829a7e51b Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 11 Feb 2019 23:34:48 -0500 Subject: [PATCH 094/162] Fix for cgi-bin folder --- scripts/nginx/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/nginx/install b/scripts/nginx/install index cf35bda90..dee83b754 100755 --- a/scripts/nginx/install +++ b/scripts/nginx/install @@ -29,7 +29,7 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th mkdir "$BASE_DIR/tmp" git clone https://github.com/hamishcoleman/cjdns_tool.git "$BASE_DIR/tmp/cjdns_tool" mkdir -p "/var/www/html/cgi-bin/lib/" || true - sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib/*" "/var/www/html/cgi-bin/lib/" + sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib" "/var/www/html/cgi-bin/" rm -rf "$BASE_DIR/tmp" sudo cp "$BASE_DIR/peers-cjdns" "/var/www/html/cgi-bin/peers-cjdns" From 79eb53d74e6f8e96b8b59d025eb12921de809221 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 10:23:17 -0500 Subject: [PATCH 095/162] Corrected typo in SDR filename --- .../pi-stream/{install-srd-drivers.sh => install-sdr-drivers.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename contrib/pi-stream/{install-srd-drivers.sh => install-sdr-drivers.sh} (100%) diff --git a/contrib/pi-stream/install-srd-drivers.sh b/contrib/pi-stream/install-sdr-drivers.sh similarity index 100% rename from contrib/pi-stream/install-srd-drivers.sh rename to contrib/pi-stream/install-sdr-drivers.sh From e4c25f7ac7967906a7cd35dfbb253ffa7b6b77a6 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 10:59:12 -0500 Subject: [PATCH 096/162] Updated adhoc to 20mhz PR --- docs/FAQ.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index d7673731f..008ac2ca0 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -119,10 +119,9 @@ On board wireless we have seen so far To install * Install Ad-Hoc mesh module * Do NOT install Access Point -* After install remove `HT40+` from `/usr/bin/mesh-adhoc` If you have success using ad-hoc with on board cards please let us know your experience. So far: -3b+ seemed to have worked but 3b did not -Got 3b working by killing wpa_supplicant first (reproducable?) +- 3b+ seemed to have worked but 3b did not +- 3b working by killing wpa_supplicant first From b2df7d278a0fc950eebc4662a31d1000f4e71e79 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 13:44:31 -0500 Subject: [PATCH 097/162] Fix permissions during install of /tmp/radvd.conf --- scripts/hostapd/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/hostapd/install b/scripts/hostapd/install index 9afc1058d..446351690 100755 --- a/scripts/hostapd/install +++ b/scripts/hostapd/install @@ -117,7 +117,7 @@ if [ -f /etc/dhcpcd.conf ]; then fi # Setup radvd -sudo cp "$BASE_DIR/radvd.conf" /tmp +cp "$BASE_DIR/radvd.conf" /tmp if [ "$(which yggdrasil)" ]; then # Setup Yggdrasil radvd prefix for subnetting sed -i "s/fdfc::\/64/${YGG_SUBNET}\/64/" /tmp/radvd.conf From ed533f44d556d6db0810c37a826bfff32dd2ce75 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 13:53:08 -0500 Subject: [PATCH 098/162] Correct IPFS typo --- scripts/install2 | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/scripts/install2 b/scripts/install2 index 3b2e6b9b6..d459544f9 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -158,7 +158,7 @@ if [ "$(checkModule 'WITH_DIALOG')" ]; then fi -askSelection "A Basic node\nB Basic IPSF Node\nC Monitor Node\nD SSB Node\nE Camera Node\nZ Custom" "Select install type" Z +askSelection "A Basic node\nB IPFS Node\nC Monitor Node\nD SSB Node\nE Camera Node\nZ Custom" "Select node install type" Z case "$dialogREPLY" in "A") @@ -191,7 +191,6 @@ case "$dialogREPLY" in WITH_EXTRA_TOOLS=true WITH_WATCHDOG=true WITH_YRD=true - WITH_PROMETHEUS_SERVER=false WITH_GRAFANA=false WITH_SSB=false @@ -210,7 +209,6 @@ case "$dialogREPLY" in WITH_EXTRA_TOOLS=true WITH_WATCHDOG=true WITH_YRD=true - WITH_PROMETHEUS_SERVER=true WITH_GRAFANA=true WITH_SSB=false @@ -229,7 +227,6 @@ case "$dialogREPLY" in WITH_EXTRA_TOOLS=true WITH_WATCHDOG=true WITH_YRD=true - WITH_PROMETHEUS_SERVER=false WITH_GRAFANA=false WITH_SSB=true @@ -248,7 +245,6 @@ case "$dialogREPLY" in WITH_EXTRA_TOOLS=true WITH_WATCHDOG=true WITH_YRD=true - WITH_PROMETHEUS_SERVER=false WITH_GRAFANA=false WITH_SSB=false From 2ad9272a8cbc2f259e44633dcb45e3ae6ccf95e6 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 14:10:38 -0500 Subject: [PATCH 099/162] switch remote to purge --- scripts/nginx/uninstall | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/nginx/uninstall b/scripts/nginx/uninstall index 36a2abdea..c92c23732 100644 --- a/scripts/nginx/uninstall +++ b/scripts/nginx/uninstall @@ -4,5 +4,6 @@ sudo rm -rf /etc/nginx/sites-available/main.conf || true sudo rm -rf /etc/nginx/sites-enabled/main.conf || true sudo rm /etc/nginx/sites-enabled/default || true sudo rm -rf /etc/nginx/site-path-enabled || true -sudo apt-get remove nginx -y -sudo rm -rf /var/www/html \ No newline at end of file +sudo apt-get purge nginx -y +sudo apt-get purge nginx-* libnginx-* -y +sudo rm -rf /var/www/html From d766909ce104a8d7d8eed4cd9eb9ba1a35dc8a2e Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 14:20:24 -0500 Subject: [PATCH 100/162] Update install2 --- scripts/install2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install2 b/scripts/install2 index d459544f9..d5c8795fc 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -121,7 +121,7 @@ sudo apt-get update -y # Install firmware package for wireless drivers # #TODO# detect armbian -sudo apt-get install -y armbian-firmware-full || true +sudo apt-get install -y armbian-firmware-full 2> /dev/null || true # Enable password-less sudo on Armbian sudo sed -i 's/ALL=(ALL:ALL) ALL/ALL=(ALL:ALL) NOPASSWD:ALL/' /etc/sudoers From 3bc4d0999154755d06a3826732cde28e0e7ef869 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 14:32:50 -0500 Subject: [PATCH 101/162] Updated permissions and hopefully fixed lib --- scripts/nginx/install | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/nginx/install b/scripts/nginx/install index dee83b754..17083595d 100755 --- a/scripts/nginx/install +++ b/scripts/nginx/install @@ -27,8 +27,9 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th # CJDNS peers mkdir "$BASE_DIR/tmp" + git clone https://github.com/hamishcoleman/cjdns_tool.git "$BASE_DIR/tmp/cjdns_tool" - mkdir -p "/var/www/html/cgi-bin/lib/" || true + sudo mkdir -p "/var/www/html/cgi-bin/lib/" || true sudo cp -r "$BASE_DIR/tmp/cjdns_tool/lib" "/var/www/html/cgi-bin/" rm -rf "$BASE_DIR/tmp" sudo cp "$BASE_DIR/peers-cjdns" "/var/www/html/cgi-bin/peers-cjdns" @@ -38,7 +39,8 @@ if [ ! -x "$(command -v nginx)" ] || [ ! -d "/etc/nginx/site-path-enabled" ]; th sudo chmod +x "/var/www/html/cgi-bin/peers-cjdns" sudo chmod +x "/var/www/html/cgi-bin/peers-yggdrasil" - + sudo chown -R www-data.www-data /var/www/html + BASE_DIR="$LAST_BASE" fi From c54c0b25646c965bf0d4af105eb309e8e71ad0ef Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 17:10:00 -0500 Subject: [PATCH 102/162] Added question about v0.4 mesh/adhoc bands --- docs/FAQ.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/FAQ.md b/docs/FAQ.md index 008ac2ca0..78a23b2b2 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -105,6 +105,12 @@ saveenv ``` ## Wireless +**Q:** Why do my Meshpoint/AdHoc nodes Release v0.3 or lower no longer mesh with V0.4 or higher? + +**A:** We dropped the band width of MeshPoint and AdHoc to 20MHz from 40MHz. This should provider a bit better responsivness in urban environments. Unfortunatlry the 20MHz and 40MHz bands do not work together. + +You can update your v0.3 or lower nodes to use 20MHz by editing the `/usr/bin/mesh-adhoc` or `/usr/bin/mesh-point` file and removing the HT40+ paramater from the iw line near the bottom of the file, then simply reboot. + **Q:** Can I use the on board wireless of my RaspberryPi/OrangePi/etc to mesh? **A:** Maybe. From 5fcb5402ffd5f1d085a21d50760466b4307ce2e9 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 18:43:25 -0500 Subject: [PATCH 103/162] Corrected conflicting # in sed --- scripts/grafana/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/grafana/install b/scripts/grafana/install index 1509c1939..a2b38df64 100755 --- a/scripts/grafana/install +++ b/scripts/grafana/install @@ -44,4 +44,4 @@ fi # Add entry into nginx home screen APP="

Grafana

The open platform for beautiful analytics and monitoring.
Go
" -sudo sed -i "s#<\!--APPLIST-->#$APP\n<\!--APPLIST-->#" "/var/www/html/index.html" +sudo sed -i "s|<\!--APPLIST-->|$APP\n<\!--APPLIST-->|" "/var/www/html/index.html" From 2297dd72d6e255f3b222887efa5b6ee2661401c2 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 20:17:18 -0500 Subject: [PATCH 104/162] Corrected wlan detection --- scripts/hostapd/install | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/hostapd/install b/scripts/hostapd/install index 446351690..723e0570e 100755 --- a/scripts/hostapd/install +++ b/scripts/hostapd/install @@ -138,7 +138,8 @@ sudo systemctl daemon-reload sudo systemctl enable hostapd.service # Find onboard adapter by driver and lock to wlan-ap -for wlan in $(find /sys/class/net -maxdepth 1 -name 'wlan*' | xargs -0 basename); do +for wlanfile in /sys/class/net/wlan*; do + wlan="$(basename "$wlanfile")" driverPath=$(readlink "/sys/class/net/$wlan/device/driver") driver=$(basename "$driverPath") # mac="$(cat /sys/class/net/$wlan/address)" From 292a11a1213d1eb8ced7a28f7d0890178bf4fb26 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 20:31:31 -0500 Subject: [PATCH 105/162] Updated wording for IPFS Pi Stream block --- scripts/ipfs-pi-stream/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ipfs-pi-stream/install b/scripts/ipfs-pi-stream/install index ed6315a37..571e54105 100755 --- a/scripts/ipfs-pi-stream/install +++ b/scripts/ipfs-pi-stream/install @@ -48,5 +48,5 @@ cp -r "$VIDEO_PLAYER_PATH" /var/www/html/video-player rm -rf "$BASE_DIR/tmp" # Add entry into nginx home screen -APP="

IPFS Pi Stream Player

IPFS Video player for Pi Stream.
Stream at /ipns/$IPFS_ID
Go
" +APP="

IPFS Pi Stream Player

IPFS Video player for Pi Stream.
M3U8 Stream located over ipns
Go and play with built in video player
" sudo sed -i "s#<\!--APPLIST-->#$APP\n<\!--APPLIST-->#" "/var/www/html/index.html" From de3f62815911ca0b5b3d33ce689181c23466d48e Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 20:32:14 -0500 Subject: [PATCH 106/162] Add a bit of spacing after titles --- scripts/nginx/common.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/nginx/common.css b/scripts/nginx/common.css index 1f13b28a2..e8d23ba1e 100644 --- a/scripts/nginx/common.css +++ b/scripts/nginx/common.css @@ -10,6 +10,7 @@ h1 { background:black; color:white; padding:5px; + margin-bottom:5px; } .app { display:inline-block; @@ -20,4 +21,4 @@ h1 { margin:5px; padding:5px; min-width:400px; -} \ No newline at end of file +} From aac80e2f5d6ac8d75d7eadf4b58a95fd56b9137e Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 20:35:03 -0500 Subject: [PATCH 107/162] Corrected grafana port --- scripts/grafana/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/grafana/install b/scripts/grafana/install index a2b38df64..d9bb5b4fa 100755 --- a/scripts/grafana/install +++ b/scripts/grafana/install @@ -43,5 +43,5 @@ else fi # Add entry into nginx home screen -APP="

Grafana

The open platform for beautiful analytics and monitoring.
Go
" +APP="

Grafana

The open platform for beautiful analytics and monitoring.
Go explore Grafana.
" sudo sed -i "s|<\!--APPLIST-->|$APP\n<\!--APPLIST-->|" "/var/www/html/index.html" From c2c3a3daa72408391a5e3d92d9d4e323ea0a7227 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 20:49:20 -0500 Subject: [PATCH 108/162] added yggdrasil detection for map --- scripts/nginx/peers-yggdrasil | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/scripts/nginx/peers-yggdrasil b/scripts/nginx/peers-yggdrasil index b1c6660aa..1a7781c6d 100644 --- a/scripts/nginx/peers-yggdrasil +++ b/scripts/nginx/peers-yggdrasil @@ -1,4 +1,15 @@ -#!/bin/sh -echo "Content-type: text/html\n\n"; +#!/bin/bash +echo -e "Content-type: text/html\n\n"; -yggdrasilctl --json getPeers \ No newline at end of file +if [ -z "$(which yggdrasilctl)" ]; then + echo "{}" + exit 0 +fi + +res=$(yggdrasilctl --json getPeers 2>/dev/null) + +if [[ $res == *"Fatal error"* ]]; then + echo "{}" +else + echo $res +fi From 7ae179875230d8ae27e111924fc8410697628cc7 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 20:52:14 -0500 Subject: [PATCH 109/162] Added better detection for yggdrasil --- scripts/status | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/status b/scripts/status index f0b6c3b90..201e57f5a 100755 --- a/scripts/status +++ b/scripts/status @@ -15,10 +15,12 @@ if [ "$(systemctl status cjdns.service | grep 'Active: ' | awk '{ print $2 }')" else echo -e "cjdns Service .............. $INACTIVE" fi -if [ "$(systemctl status yggdrasil.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then - echo -e "Yggdrasil Service ............ $ACTIVE" -else - echo -e "Yggdrasil Service .......... $INACTIVE" +if [ "$(which yggdrasilctl)" ]; then + if [ "$(systemctl status yggdrasil.service | grep 'Active: ' | awk '{ print $2 }')" = 'active' ]; then + echo -e "Yggdrasil Service ............ $ACTIVE" + else + echo -e "Yggdrasil Service .......... $INACTIVE" + fi fi if [ "$(which mesh-point)" ]; then @@ -119,7 +121,7 @@ if [ "$(which cjdroute)" ] && [ "$(ip addr | grep tun0)" ] ; then echo -e '---------------------------------------' fi -if [ "$(which yggdrasil)" ]; then +if [ "$(which yggdrasil)" ] && [ "$(ip addr | grep ygg0)" ]; then YGGIP=$(sudo ifconfig ygg0 | grep -E 'inet6 2[0-9a-fA-F]{2}:' | awk '{print $2}') echo -e '---------------------------------------' echo -e 'YGGDRASIL NODE' From af3ee6758fbe3333112c46e77a7c26a6aaa74d98 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 21:50:46 -0500 Subject: [PATCH 110/162] Better iteration through interfaces --- scripts/mesh-point/mesh-point | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/mesh-point/mesh-point b/scripts/mesh-point/mesh-point index 2612c3063..94e805a07 100755 --- a/scripts/mesh-point/mesh-point +++ b/scripts/mesh-point/mesh-point @@ -22,7 +22,8 @@ set -e sudo iw reg set CA # Find first 802.11s Mesh Point capable device -for int in $(find /sys/class/net/* -maxdepth 1 -print0 | xargs -0 -l basename); do +for wlanfile in /sys/class/net/*; do + int="$(basename "$wlanfile")" if [ -d "/sys/class/net/$int/wireless" ]; then phy=$(iw dev "$int" info | grep wiphy | awk '{print $2}') if [ ! -z "$phy" ]; then From 05793a0a345f2233e721902ba4fcd48e471a6995 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 22:21:56 -0500 Subject: [PATCH 111/162] Armbian bug workaround --- scripts/install2 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/install2 b/scripts/install2 index d5c8795fc..40b423ccf 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -117,7 +117,8 @@ fi echo -e "\e[1;32mStarting installation on ${BOARD_FAMILY} ${BOARD_NAME} (${BOARD_REVISION})...\e[0m" # Normalize OS environment -sudo apt-get update -y +# True required to avoid odd armbian bug. Update does work but reports missing file. +sudo apt-get update -y || true # Install firmware package for wireless drivers # #TODO# detect armbian From 207f1832c298c68687083f3ec4e263f98734c547 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 22:22:32 -0500 Subject: [PATCH 112/162] Armbian bug patch --- scripts/install | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/install b/scripts/install index c73439405..61a3dc992 100755 --- a/scripts/install +++ b/scripts/install @@ -26,7 +26,8 @@ if ps xa | awk '{print $5}' | grep -q dpkg; then fi # Get git -sudo apt-get update +# True required to avoid odd armbian bug. Update does work but reports missing file. +sudo apt-get update -y || true if ! [ "$(which git)" ]; then sudo apt-get install git -y fi From 319278ff4c1887f29271caf539ddcf4e1b271ab9 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 23:17:31 -0500 Subject: [PATCH 113/162] remove null byte that generates the warning --- scripts/install2 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/install2 b/scripts/install2 index 40b423ccf..9af7e2df0 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -15,7 +15,8 @@ BOARD_REVISION="?" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 ./do" ##TODO## Possibly use /sys/firmware/devicetree/base/model -BOARD_MODEL=$(cat /sys/firmware/devicetree/base/model) +# Use tr to remove null byte generating warning +BOARD_MODEL=$(tr -d '\0' < /sys/firmware/devicetree/base/model) BOARD_HARDWARE=$(grep Hardware /proc/cpuinfo | awk '{print $3}' | head -n 1) From 0518c6d5eac9f197a80ef33765935e512df47da5 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 12 Feb 2019 23:21:09 -0500 Subject: [PATCH 114/162] Made dialog for profile selection bigger --- scripts/functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/functions.sh b/scripts/functions.sh index 1789b30cd..e8fdf43e8 100644 --- a/scripts/functions.sh +++ b/scripts/functions.sh @@ -98,7 +98,7 @@ function askSelection { echo "$selection" > /tmp/selectionList # shellcheck disable=SC2086 - dialog $dialogGlobalParams --radiolist "$2" 10 55 8 --file /tmp/selectionList 2> /tmp/res + dialog $dialogGlobalParams --radiolist "$2" 15 55 8 --file /tmp/selectionList 2> /tmp/res rm -f selectionList response=$(cat /tmp/res) rm -f /tmp/res From 7bac64c6b6f61c6a7e8a8b7888274cb71b9a3a08 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 15 Feb 2019 16:01:21 -0500 Subject: [PATCH 115/162] Corrected read flag --- scripts/ssb/ssb-broadcast-service.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ssb/ssb-broadcast-service.sh b/scripts/ssb/ssb-broadcast-service.sh index c8908826b..b2ae9bfc7 100755 --- a/scripts/ssb/ssb-broadcast-service.sh +++ b/scripts/ssb/ssb-broadcast-service.sh @@ -15,7 +15,7 @@ while true; do if [ "$(which cjdns)" ]; then mycjdnsip=$(grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g') # shellcheck disable=SC2102,SC2046 - read -ar peers <<< $(sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{print $6".k"}' | xargs) + read -a peers <<< $(sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{print $6".k"}' | xargs) for peer in "${peers[@]}"; do ip=$(sudo /opt/cjdns/publictoip6 "$peer") # shellcheck disable=SC2102 @@ -26,7 +26,7 @@ while true; do # Add yggdrasil direct peers if [ "$(which yggdrasil)" ]; then myyggip=$(yggdrasilctl getself | grep address | awk '{print $3}') - read -ar peers <<< "$(sudo yggdrasilctl getPeers | grep -v "(self)" | awk '{print $1}' | grep -v bytes_recvd | xargs)" + read -a peers <<< "$(sudo yggdrasilctl getPeers | grep -v "(self)" | awk '{print $1}' | grep -v bytes_recvd | xargs)" for peer in "${peers[@]}"; do # shellcheck disable=SC2102 echo -n "net:$myyggip:8008~shs:$id" | sudo socat -T 1 - UDP6-DATAGRAM:[$peer]:8008 From ab3527a6897cf26fc5dfa4913cef503607fb16dd Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 15 Feb 2019 16:03:58 -0500 Subject: [PATCH 116/162] Corrected name of cjdns executable --- scripts/ssb/ssb-broadcast-service.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ssb/ssb-broadcast-service.sh b/scripts/ssb/ssb-broadcast-service.sh index b2ae9bfc7..5ed7739a5 100755 --- a/scripts/ssb/ssb-broadcast-service.sh +++ b/scripts/ssb/ssb-broadcast-service.sh @@ -12,7 +12,7 @@ while true; do fi # Manual cjdns peer unicast - if [ "$(which cjdns)" ]; then + if [ "$(which cjdroute)" ]; then mycjdnsip=$(grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g') # shellcheck disable=SC2102,SC2046 read -a peers <<< $(sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{print $6".k"}' | xargs) From 8080874caec4955490fb20ccf99dc4cbe3c44664 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 16 Feb 2019 00:03:54 -0500 Subject: [PATCH 117/162] Added sbot firewall rules --- scripts/firewall/rules.v6 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 7fe6021e3..06a133323 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -30,6 +30,8 @@ -A CJDNS -j ACCEPT -p tcp --dport 3000 -A CJDNS -j ACCEPT -p tcp --dport 5201 -A CJDNS -j ACCEPT -p tcp --dport 4001 +-A CJDNS -j ACCEPT -p tcp --dport 8008 +-A CJDNS -j ACCEPT -p udp --dport 8008 -A CJDNS -j ACCEPT -p tcp --dport 9090 -A CJDNS -j ACCEPT -p tcp --dport 9100 @@ -40,6 +42,8 @@ -A YGGDRASIL -j ACCEPT -p tcp --dport 3000 -A YGGDRASIL -j ACCEPT -p tcp --dport 5201 -A YGGDRASIL -j ACCEPT -p tcp --dport 4001 +-A YGGDRASIL -j ACCEPT -p tcp --dport 8008 +-A YGGDRASIL -j ACCEPT -p udp --dport 8008 -A YGGDRASIL -j ACCEPT -p tcp --dport 9090 -A YGGDRASIL -j ACCEPT -p tcp --dport 9100 From f26f73913aa1eed2465826d594cc6f26d02dd2c4 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 16 Feb 2019 00:06:36 -0500 Subject: [PATCH 118/162] Added SSB ports to docs --- docs/MODULES.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/MODULES.md b/docs/MODULES.md index ab01faf9c..9162a85d7 100644 --- a/docs/MODULES.md +++ b/docs/MODULES.md @@ -72,6 +72,7 @@ Default open ports to the device are below. Since both CJDNS and Yggdrasil use I | 53 | TCP/UDP | Accept | DNS Server | | 80 | TCP | Accept | HTTP | | 443 | TCP | Accept | SSH | +| 8008 | TCP/UDP | Accept | SSB | | 9100 | TCP | Accept | NodeExporter | | 9090 | TCP | Accept | Prometheus Server | | 3000 | TCP | Accept | Grafana | @@ -106,10 +107,10 @@ Default open ports to the device over IPv6 are | 53 | TCP/UDP | Accept | DNS Server | | 80 | TCP | Accept | HTTP | | 443 | TCP | Accept | SSH | -| 9100 | TCP | Accept | NodeExporter | | 5201 | TCP | Accept | IPerf3 | | 4001 | TCP | Accept | IPFS Swarm port | - +| 8008 | TCP/UDP | Accept | SSB | +| 9100 | TCP | Accept | NodeExporter | #### Change open ports To change the open ports you can edit the IPv6 configuration file located at `/etc/iptables/rules.v6` @@ -147,4 +148,4 @@ Specifying a protocol is not required, but recommended. If you use this rule, there is no point in having any other Yggdrasil client rules in the file. -You can specify a protocol, but that would limit the ports that are open. \ No newline at end of file +You can specify a protocol, but that would limit the ports that are open. From 3e79482405d7f29e879f3841d896236a13989583 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 16 Feb 2019 00:24:16 -0500 Subject: [PATCH 119/162] Corrected SBOT iptables --- scripts/firewall/rules.v6 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 06a133323..2fcde94eb 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -14,7 +14,8 @@ -A INPUT -j ACCEPT -p udp --dport 9001 -d ff02::114 # Any new raw INPUT rules go here - +-A INPUT -j ACCEPT -p tcp --dport 8008 +-A INPUT -j ACCEPT -p udp --dport 8008 # DO NOT EDIT - Redirect to named tables -A INPUT -i tun0 -d fc00::/8 -j CJDNS @@ -30,8 +31,6 @@ -A CJDNS -j ACCEPT -p tcp --dport 3000 -A CJDNS -j ACCEPT -p tcp --dport 5201 -A CJDNS -j ACCEPT -p tcp --dport 4001 --A CJDNS -j ACCEPT -p tcp --dport 8008 --A CJDNS -j ACCEPT -p udp --dport 8008 -A CJDNS -j ACCEPT -p tcp --dport 9090 -A CJDNS -j ACCEPT -p tcp --dport 9100 @@ -42,12 +41,12 @@ -A YGGDRASIL -j ACCEPT -p tcp --dport 3000 -A YGGDRASIL -j ACCEPT -p tcp --dport 5201 -A YGGDRASIL -j ACCEPT -p tcp --dport 4001 --A YGGDRASIL -j ACCEPT -p tcp --dport 8008 --A YGGDRASIL -j ACCEPT -p udp --dport 8008 -A YGGDRASIL -j ACCEPT -p tcp --dport 9090 -A YGGDRASIL -j ACCEPT -p tcp --dport 9100 # Yggdrasil client (YGGCLIENT) rules go here +-A YGGCLIENT -j ACCEPT -p tcp --dport 8008 +-A YGGCLIENT -j ACCEPT -p udp --dport 8008 # End, put nothing below this From 355d0fa7a1e344875030bb3c7f2c04905b50396d Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 16 Feb 2019 00:33:21 -0500 Subject: [PATCH 120/162] Get id only once, Fix checks --- scripts/ssb/ssb-broadcast-service.sh | 46 ++++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/scripts/ssb/ssb-broadcast-service.sh b/scripts/ssb/ssb-broadcast-service.sh index 5ed7739a5..d15cc0ddf 100755 --- a/scripts/ssb/ssb-broadcast-service.sh +++ b/scripts/ssb/ssb-broadcast-service.sh @@ -1,7 +1,6 @@ #!/bin/bash while true; do - id=$(sbot whoami | grep id | awk -F "\"" '{print $4}' | sed 's/.ed25519//' | sed 's/@//') if ! [ -z "$id" ]; then for int in $(find /sys/class/net/* -maxdepth 1 -print0 | xargs -0 -l basename); do ip=$(ip addr show "${int}" | grep -v inet6 | grep -v '127.0.0.1' |grep inet | head -n 1 | awk '{print $2}' | awk -F "/" '{print $1}') @@ -9,29 +8,30 @@ while true; do echo -n "net:$ip:8008~shs:$id" | sudo socat -T 1 - "UDP4-DATAGRAM:255.255.255.255:8008,broadcast,so-bindtodevice=${int}" & fi done - fi - # Manual cjdns peer unicast - if [ "$(which cjdroute)" ]; then - mycjdnsip=$(grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g') - # shellcheck disable=SC2102,SC2046 - read -a peers <<< $(sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{print $6".k"}' | xargs) - for peer in "${peers[@]}"; do - ip=$(sudo /opt/cjdns/publictoip6 "$peer") - # shellcheck disable=SC2102 - echo -n "net:$mycjdnsip:8008~shs:$id" | sudo socat -T 1 - UDP6-DATAGRAM:[$ip]:8008 - done - fi - - # Add yggdrasil direct peers - if [ "$(which yggdrasil)" ]; then - myyggip=$(yggdrasilctl getself | grep address | awk '{print $3}') - read -a peers <<< "$(sudo yggdrasilctl getPeers | grep -v "(self)" | awk '{print $1}' | grep -v bytes_recvd | xargs)" - for peer in "${peers[@]}"; do - # shellcheck disable=SC2102 - echo -n "net:$myyggip:8008~shs:$id" | sudo socat -T 1 - UDP6-DATAGRAM:[$peer]:8008 - done - fi + # Manual cjdns peer unicast + if [ "$(which cjdroute)" ]; then + mycjdnsip=$(grep -m 1 '"ipv6"' /etc/cjdroute.conf | awk '{ print $2 }' | sed 's/[",]//g') + # shellcheck disable=SC2102,SC2046 + read -a peers <<< $(sudo nodejs /opt/cjdns/tools/peerStats 2>/dev/null | awk '{ if ($3 == "ESTABLISHED") print $2 }' | awk -F. '{print $6".k"}' | xargs) + for peer in "${peers[@]}"; do + ip=$(sudo /opt/cjdns/publictoip6 "$peer") + # shellcheck disable=SC2102 + echo -n "net:$mycjdnsip:8008~shs:$id" | sudo socat -T 1 - UDP6-DATAGRAM:[$ip]:8008 + done + fi + # Add yggdrasil direct peers + if [ "$(which yggdrasil)" ]; then + myyggip=$(yggdrasilctl getself | grep address | awk '{print $3}') + read -a peers <<< "$(sudo yggdrasilctl getPeers | grep -v "(self)" | awk '{print $1}' | grep -v bytes_recvd | xargs)" + for peer in "${peers[@]}"; do + # shellcheck disable=SC2102 + echo -n "net:$myyggip:8008~shs:$id" | sudo socat -T 1 - UDP6-DATAGRAM:[$peer]:8008 + done + fi + else + id=$(sbot whoami | grep id | awk -F "\"" '{print $4}' | sed 's/.ed25519//' | sed 's/@//') + fi sleep 5 done From 5da7cdc8b79960b640b2667656897ab369905210 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 16 Feb 2019 00:45:20 -0500 Subject: [PATCH 121/162] Added tcp for 8008 port --- scripts/firewall/rules.v4 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/firewall/rules.v4 b/scripts/firewall/rules.v4 index 875327239..fbbc6f965 100644 --- a/scripts/firewall/rules.v4 +++ b/scripts/firewall/rules.v4 @@ -15,6 +15,7 @@ -A INPUT -p tcp -m tcp --dport 4001 -j ACCEPT -A INPUT -p tcp -m tcp --dport 5201 -j ACCEPT -A INPUT -p udp -m udp --dport 8008 -j ACCEPT +-A INPUT -p tcp -m tcp --dport 8008 -j ACCEPT -A INPUT -p tcp -m tcp --dport 9090 -j ACCEPT -A INPUT -p tcp -m tcp --dport 9100 -j ACCEPT -A INPUT -i wlan+ -j ACCEPT From 3cb863e2b1211855ccb65fffb4e73d1ca6342e8d Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sat, 16 Feb 2019 22:26:58 -0500 Subject: [PATCH 122/162] Update rules.v6 --- scripts/firewall/rules.v6 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 2fcde94eb..6649db816 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -7,6 +7,7 @@ :YGGCLIENT - [0:0] -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT +-A FORWARD -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT # Raw INPUT rules needed for Yggdrasil - DO NOT EDIT From 315e93209b15d2921d666700a84f4ae737feb915 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 17 Feb 2019 00:51:51 -0500 Subject: [PATCH 123/162] Updated rules to correct Ygg client errors --- scripts/firewall/rules.v6 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 6649db816..2e7d9d8a1 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -7,14 +7,13 @@ :YGGCLIENT - [0:0] -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT --A FORWARD -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -# Raw INPUT rules needed for Yggdrasil - DO NOT EDIT +# INPUT rules needed for Yggdrasil peering -A INPUT -j ACCEPT -p tcp --dport 12345 -A INPUT -j ACCEPT -p udp --dport 9001 -d ff02::114 -# Any new raw INPUT rules go here +# INPUT rules needed for SSB peering -A INPUT -j ACCEPT -p tcp --dport 8008 -A INPUT -j ACCEPT -p udp --dport 8008 @@ -22,6 +21,10 @@ -A INPUT -i tun0 -d fc00::/8 -j CJDNS -A INPUT -i ygg0 -d 200::/8 -j YGGDRASIL -A INPUT -j REJECT --reject-with icmp6-port-unreachable + +-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -p ipv6-icmp -j ACCEPT +-A FORWARD -o ygg0 -j ACCEPT -A FORWARD -i ygg0 -d 300::/8 -j YGGCLIENT -A FORWARD -j REJECT --reject-with icmp6-port-unreachable From a1e25c6640e0a72807e1b4d1ad6d6e9682c0e6e3 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 17 Feb 2019 16:21:06 -0500 Subject: [PATCH 124/162] fixed nat forwarding for cjdsn --- scripts/firewall/rules.v6 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index 2e7d9d8a1..b9dcd5c24 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -24,6 +24,7 @@ -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -p ipv6-icmp -j ACCEPT +-A FORWARD -o tun0 -j ACCEPT -A FORWARD -o ygg0 -j ACCEPT -A FORWARD -i ygg0 -d 300::/8 -j YGGCLIENT -A FORWARD -j REJECT --reject-with icmp6-port-unreachable From 5bcb3bfe6ef5d196825cc1911d34a7bf9fb73b07 Mon Sep 17 00:00:00 2001 From: makeworld <25111343+makeworld-the-better-one@users.noreply.github.com> Date: Sun, 17 Feb 2019 22:38:54 -0500 Subject: [PATCH 125/162] Made the file easier for uninformed users to edit, and so that they don't mess things up - Just comments --- scripts/firewall/rules.v6 | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/firewall/rules.v6 b/scripts/firewall/rules.v6 index b9dcd5c24..7c0ea1c14 100644 --- a/scripts/firewall/rules.v6 +++ b/scripts/firewall/rules.v6 @@ -5,29 +5,35 @@ :CJDNS - [0:0] :YGGDRASIL - [0:0] :YGGCLIENT - [0:0] + +# Add your own raw INPUT rules below - they will apply to everything +# Do not block everything here, that is handled below + +####################### +# DO NOT EDIT - Raw INPUT rules +####################### -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT - # INPUT rules needed for Yggdrasil peering -A INPUT -j ACCEPT -p tcp --dport 12345 -A INPUT -j ACCEPT -p udp --dport 9001 -d ff02::114 - # INPUT rules needed for SSB peering -A INPUT -j ACCEPT -p tcp --dport 8008 -A INPUT -j ACCEPT -p udp --dport 8008 - -# DO NOT EDIT - Redirect to named tables +# Redirect to named tables -A INPUT -i tun0 -d fc00::/8 -j CJDNS -A INPUT -i ygg0 -d 200::/8 -j YGGDRASIL -A INPUT -j REJECT --reject-with icmp6-port-unreachable - +# Allow clients to have outbound requests and receive their response -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -p ipv6-icmp -j ACCEPT -A FORWARD -o tun0 -j ACCEPT -A FORWARD -o ygg0 -j ACCEPT +# Redirect to YGGCLIENT table -A FORWARD -i ygg0 -d 300::/8 -j YGGCLIENT -A FORWARD -j REJECT --reject-with icmp6-port-unreachable +####################### # CJDNS rules -A CJDNS -j ACCEPT -p tcp --dport 22 From 8dc2bd4669fbb0bc53364fdf28e03d1527c8149d Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 18 Feb 2019 00:07:00 -0500 Subject: [PATCH 126/162] Added cjdns debian package for arm64 boards --- scripts/install2 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/install2 b/scripts/install2 index 9af7e2df0..d0b551899 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -71,8 +71,9 @@ elif [[ "$BOARD_HARDWARE" == 'nanopineo2' || "$BOARD_HARDWARE" == 'sun50iw1p1' | BOARD_NAME=$(grep BOARD_NAME /etc/armbian-image-release | awk -F '=' '{print $2}' | tr -d \" | sed 's/Orange Pi //g') BOARD_REVISION="experimental" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 CFLAGS=\"-s -static -Wall -march=armv8-a+crc+crypto -fomit-frame-pointer\" ./do" + CJDNS_PACKAGE="cjdns-neon-arm64-v4.deb" if [[ "$BOARD_HARDWARE" == "orangepizeroplus2-h5" ]]; then - SUPPORT_HOSTAP=true + SUPPORT_HOSTAP=true fi else From 2e55892652956bc5a161ebed326424c9a31946b3 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 18 Feb 2019 00:24:14 -0500 Subject: [PATCH 127/162] Skip shellcheck of read (breaks things) --- scripts/ipfs/ipfs-swarm.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/ipfs/ipfs-swarm.sh b/scripts/ipfs/ipfs-swarm.sh index a4e20f5c3..513c49091 100644 --- a/scripts/ipfs/ipfs-swarm.sh +++ b/scripts/ipfs/ipfs-swarm.sh @@ -1,4 +1,6 @@ #!/bin/bash +# shellcheck disable=SC2162 +true # Wait for ipfs to initalize attempts=15 From 320953b3283d0933ffb35aec658d43d80b9370ce Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 18 Feb 2019 00:33:56 -0500 Subject: [PATCH 128/162] skip shellcheck -r check --- scripts/ssb/ssb-broadcast-service.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/ssb/ssb-broadcast-service.sh b/scripts/ssb/ssb-broadcast-service.sh index d15cc0ddf..4d79fba06 100755 --- a/scripts/ssb/ssb-broadcast-service.sh +++ b/scripts/ssb/ssb-broadcast-service.sh @@ -1,4 +1,6 @@ #!/bin/bash +# shellcheck disable=SC2162 +true while true; do if ! [ -z "$id" ]; then From f06aa46a53ef252d185dc42c33ff20bbf832f586 Mon Sep 17 00:00:00 2001 From: ASoT Networks Date: Tue, 19 Feb 2019 01:48:13 -0500 Subject: [PATCH 129/162] Added set-mesh-repo script to contrib --- contrib/set-mesh-repo/armbian-armbian.list | 1 + .../armbian-default-armbian.list | 1 + .../set-mesh-repo/debian-default-sources.list | 11 +++ contrib/set-mesh-repo/debian-sources.list | 11 +++ .../set-mesh-repo/raspbian-default-raspi.list | 3 + .../raspbian-default-sources.list | 3 + contrib/set-mesh-repo/raspbian-raspi.list | 3 + contrib/set-mesh-repo/raspbian-sources.list | 3 + contrib/set-mesh-repo/set-repo.sh | 94 +++++++++++++++++++ 9 files changed, 130 insertions(+) create mode 100644 contrib/set-mesh-repo/armbian-armbian.list create mode 100644 contrib/set-mesh-repo/armbian-default-armbian.list create mode 100644 contrib/set-mesh-repo/debian-default-sources.list create mode 100644 contrib/set-mesh-repo/debian-sources.list create mode 100644 contrib/set-mesh-repo/raspbian-default-raspi.list create mode 100644 contrib/set-mesh-repo/raspbian-default-sources.list create mode 100644 contrib/set-mesh-repo/raspbian-raspi.list create mode 100644 contrib/set-mesh-repo/raspbian-sources.list create mode 100755 contrib/set-mesh-repo/set-repo.sh diff --git a/contrib/set-mesh-repo/armbian-armbian.list b/contrib/set-mesh-repo/armbian-armbian.list new file mode 100644 index 000000000..9f0efbf49 --- /dev/null +++ b/contrib/set-mesh-repo/armbian-armbian.list @@ -0,0 +1 @@ +deb http://__PREFIX__.mirror.tomesh.net/armbian/apt/ __CODENAME__ main __CODENAME__-utils __CODENAME__-desktop diff --git a/contrib/set-mesh-repo/armbian-default-armbian.list b/contrib/set-mesh-repo/armbian-default-armbian.list new file mode 100644 index 000000000..e920e2363 --- /dev/null +++ b/contrib/set-mesh-repo/armbian-default-armbian.list @@ -0,0 +1 @@ +deb http://apt.armbian.com __CODENAME__ main __CODENAME__-utils __CODENAME__-desktop diff --git a/contrib/set-mesh-repo/debian-default-sources.list b/contrib/set-mesh-repo/debian-default-sources.list new file mode 100644 index 000000000..0932d65c7 --- /dev/null +++ b/contrib/set-mesh-repo/debian-default-sources.list @@ -0,0 +1,11 @@ +deb http://httpredir.debian.org/debian __CODENAME__ main contrib non-free +#deb-src http://httpredir.debian.org/debian __CODENAME__ main contrib non-free + +deb http://httpredir.debian.org/debian __CODENAME__-updates main contrib non-free +#deb-src http://httpredir.debian.org/debian __CODENAME__-updates main contrib non-free + +deb http://httpredir.debian.org/debian __CODENAME__-backports main contrib non-free +#deb-src http://httpredir.debian.org/debian __CODENAME__-backports main contrib non-free + +deb http://security.debian.org/ __CODENAME__/updates main contrib non-free +#deb-src http://security.debian.org/ __CODENAME__/updates main contrib non-free diff --git a/contrib/set-mesh-repo/debian-sources.list b/contrib/set-mesh-repo/debian-sources.list new file mode 100644 index 000000000..f1901b333 --- /dev/null +++ b/contrib/set-mesh-repo/debian-sources.list @@ -0,0 +1,11 @@ +deb http://__PREFIX__.mirror.tomesh.net/debian __CODENAME__ main contrib non-free +#deb-src http://__PREFIX__.mirror.tomesh.net/debian __CODENAME__ main contrib non-free + +deb http://__PREFIX__.mirror.tomesh.net/debian __CODENAME__-updates main contrib non-free +#deb-src http://__PREFIX__.mirror.tomesh.net/debian __CODENAME__-updates main contrib non-free + +deb http://__PREFIX__.mirror.tomesh.net/debian __CODENAME__-backports main contrib non-free +#deb-src http:/__PREFIX__.mirror.tomesh.net/debian __CODENAME__-backports main contrib non-free + +deb http://__PREFIX__.mirror.tomesh.net/debian-security __CODENAME__/updates main contrib non-free +#deb-src http://__PREFIX__.mirror.tomesh.net/debian-security __CODENAME__/updates main contrib non-free diff --git a/contrib/set-mesh-repo/raspbian-default-raspi.list b/contrib/set-mesh-repo/raspbian-default-raspi.list new file mode 100644 index 000000000..21516636c --- /dev/null +++ b/contrib/set-mesh-repo/raspbian-default-raspi.list @@ -0,0 +1,3 @@ +deb http://archive.raspberrypi.org/debian/ __CODENAME__ main ui +# Uncomment line below then 'apt-get update' to enable 'apt-get source' +#deb-src http://archive.raspberrypi.org/debian/ __CODENAME__ main ui diff --git a/contrib/set-mesh-repo/raspbian-default-sources.list b/contrib/set-mesh-repo/raspbian-default-sources.list new file mode 100644 index 000000000..5fd0d1819 --- /dev/null +++ b/contrib/set-mesh-repo/raspbian-default-sources.list @@ -0,0 +1,3 @@ +deb http://raspbian.raspberrypi.org/raspbian/ __CODENAME__ main contrib non-free rpi +# Uncomment line below then 'apt-get update' to enable 'apt-get source' +#deb-src http://raspbian.raspberrypi.org/raspbian/ __CODENAME__ main contrib non-free rpi diff --git a/contrib/set-mesh-repo/raspbian-raspi.list b/contrib/set-mesh-repo/raspbian-raspi.list new file mode 100644 index 000000000..92f314b8f --- /dev/null +++ b/contrib/set-mesh-repo/raspbian-raspi.list @@ -0,0 +1,3 @@ +deb http://__PREFIX__.mirror.tomesh.net/raspberrypi/debian/ __CODENAME__ main ui +# Uncomment line below then 'apt-get update' to enable 'apt-get source' +#deb-src http://__PREFIX__.mirror.tomesh.net/raspberrypi/debian/ __CODENAME__ main ui diff --git a/contrib/set-mesh-repo/raspbian-sources.list b/contrib/set-mesh-repo/raspbian-sources.list new file mode 100644 index 000000000..4503b9572 --- /dev/null +++ b/contrib/set-mesh-repo/raspbian-sources.list @@ -0,0 +1,3 @@ +deb http://__PREFIX__.mirror.tomesh.net/raspbian/raspbian __CODENAME__ main contrib non-free rpi +# Uncomment line below then 'apt-get update' to enable 'apt-get source' +#deb-src http://__PREFIX__.mirror.tomesh.net/raspbian/raspbian __CODENAME__ main contrib non-free rpi diff --git a/contrib/set-mesh-repo/set-repo.sh b/contrib/set-mesh-repo/set-repo.sh new file mode 100755 index 000000000..2b83f0988 --- /dev/null +++ b/contrib/set-mesh-repo/set-repo.sh @@ -0,0 +1,94 @@ +#!/bin/bash +codename=$(lsb_release -cs) +distro=$(lsb_release -is) +mirror=$1 + +# cd to script directory +cd $(dirname "$0") + +# check if script is running as root +if [ "$EUID" -ne 0 ] +then + echo "Please run this script as root" + exit 1 +fi + +# set mirror values +if [ "$1" == "cjdns" ] +then + prefix="h" +elif [ "$1" == "yggdrasil" ] +then + prefix="y" +elif [ "$1" == "default" ] +then + # restore default sources + # Raspbian + if [ "$distro" == "Raspbian" ] + then + echo "Changing to Raspbian $1 repo." + cp raspbian-default-sources.list /etc/apt/sources.list + cp raspbian-default-raspi.list /etc/apt/sources.list.d/raspi.list + sed -i "s/__CODENAME__/$codename/g" /etc/apt/sources.list + sed -i "s/__CODENAME__/$codename/g" /etc/apt/sources.list.d/raspi.list + echo "Done. Restored to default." + # exit script with no error + exit 0 + # Debian / Armbian + elif [ "$distro" == "Debian" ] + then + echo "Changing to Raspbian $1 repo." + # check if there is /etc/apt/sources.list.d/armbian.list if so replace it + if [ -f /etc/apt/sources.list.d/armbian.list ] + then + cp armbian-default-armbian.list /etc/apt/sources.list.d/armbian.list + sed -i "s/__CODENAME__/$codename/g" /etc/apt/sources.list.d/armbian.list + fi + cp debian-default-sources.list /etc/apt/sources.list + sed -i "s/__CODENAME__/$codename/g" /etc/apt/sources.list + + echo "Done. Restored to default." + # exit script with no error + exit 0 + else + echo "Your distro: $distro is not supported." + fi + +else + echo "Usage: $0 { cjdns | default | yggdrasil }" + exit 1 +fi + +# detect distro and apply changes to sources +if [ "$distro" == "Raspbian" ] +then + echo "Changing to Raspbian $1 repo." + cp raspbian-sources.list /etc/apt/sources.list + cp raspbian-raspi.list /etc/apt/sources.list.d/raspi.list + + sed -i "s/__CODENAME__/$codename/g" /etc/apt/sources.list + sed -i "s/__CODENAME__/$codename/g" /etc/apt/sources.list.d/raspi.list + sed -i "s/__PREFIX__/$prefix/g" /etc/apt/sources.list + sed -i "s/__PREFIX__/$prefix/g" /etc/apt/sources.list.d/raspi.list + echo "Done. To restore to default repo run script with option default." + +elif [ "$distro" == "Debian" ] +then + echo "Changing to Debian $1 repo." + cp debian-sources.list /etc/apt/sources.list + + # check if there is /etc/apt/sources.list.d/armbian.list if so replace it + if [ -f /etc/apt/sources.list.d/armbian.list ] + then + cp armbian-armbian.list /etc/apt/sources.list.d/armbian.list + sed -i "s/__CODENAME__/$codename/g" /etc/apt/sources.list.d/armbian.list + sed -i "s/__PREFIX__/$prefix/g" /etc/apt/sources.list.d/armbian.list + + fi + + sed -i "s/__CODENAME__/$codename/g" /etc/apt/sources.list + sed -i "s/__PREFIX__/$prefix/g" /etc/apt/sources.list + echo "Done. To restore to default repo run script with option default." +else + echo "Your distro: $distro is not supported." +fi From fe0d26a724730a33ad0acbed18d276b93045b199 Mon Sep 17 00:00:00 2001 From: ASoT Networks Date: Tue, 19 Feb 2019 14:11:45 -0500 Subject: [PATCH 130/162] Removed extra empty line --- contrib/set-mesh-repo/set-repo.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/set-mesh-repo/set-repo.sh b/contrib/set-mesh-repo/set-repo.sh index 2b83f0988..9e90615f1 100755 --- a/contrib/set-mesh-repo/set-repo.sh +++ b/contrib/set-mesh-repo/set-repo.sh @@ -83,7 +83,6 @@ then cp armbian-armbian.list /etc/apt/sources.list.d/armbian.list sed -i "s/__CODENAME__/$codename/g" /etc/apt/sources.list.d/armbian.list sed -i "s/__PREFIX__/$prefix/g" /etc/apt/sources.list.d/armbian.list - fi sed -i "s/__CODENAME__/$codename/g" /etc/apt/sources.list From 696890fe36645ad5ac52299a74cd1d5090995b93 Mon Sep 17 00:00:00 2001 From: Joseph Turco Date: Wed, 20 Feb 2019 21:27:43 -0500 Subject: [PATCH 131/162] Peeringdocs (#301) * Peering instructions (#295) * remove shellcheck for -r that breaks line * Undo incorrect commit * updated MODULES.md with Depreciated Systems peering info * updated MODULES.md with Depreciated Systems peering info * fixed grammar mistakes (#297) * Spelling and format changes to MODULES.md (#298) * Spelling and format changes to MODULES.md * Grammar * I fixed all the spelling errors --- docs/MODULES.md | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/docs/MODULES.md b/docs/MODULES.md index 9162a85d7..94179a925 100644 --- a/docs/MODULES.md +++ b/docs/MODULES.md @@ -111,6 +111,7 @@ Default open ports to the device over IPv6 are | 4001 | TCP | Accept | IPFS Swarm port | | 8008 | TCP/UDP | Accept | SSB | | 9100 | TCP | Accept | NodeExporter | + #### Change open ports To change the open ports you can edit the IPv6 configuration file located at `/etc/iptables/rules.v6` @@ -130,6 +131,7 @@ These are standard `ip6tables` rules. The basic syntax is as follows: Make sure to put your rules in the right section of the file, there are different ones depending on the table, with comments defining each section. #### Yggdrasil Clients + Below are some different scenarios for opening up Yggdrasil clients. You will need to put these rules in `/etc/iptables/rules.v6`, in the Yggdrasil client rules section indicated by a comment. - **One client, one port** @@ -149,3 +151,108 @@ Specifying a protocol is not required, but recommended. If you use this rule, there is no point in having any other Yggdrasil client rules in the file. You can specify a protocol, but that would limit the ports that are open. + +## Adding deprecated.systems peer info into CJDNS and Yggdrasil (Optional) + +#### CJDNS + +Go to [Deprecated Systems](https://deprecated.systems/) website. You will see the following information: + +``` +cjdns peering + + "159.203.5.91:30664": { + "peerName": "deprecated.systems", + "login": "tomesh-public", + "password": "iuw4nklm3j89qno876ef2jabpvlg1j0", + "publicKey": "2scyvybg4qqms1c5c9nyt50b1cdscxnr6ycpwsxf6pccbmwuynk0.k" + } + + "[2604:a880:cad:d0::45:d001]:30664": { + "peerName": "deprecated.systems", + "login": "tomesh-public", + "password": "iuw4nklm3j89qno876ef2jabpvlg1j0", + "publicKey": "2scyvybg4qqms1c5c9nyt50b1cdscxnr6ycpwsxf6pccbmwuynk0.k" + } +``` + +This is the peering information that will give you the address (ipv4 or ipv6) and credentials to connect to +the node. You must either select to use just the ipv4 config, or you could use both. Now that we have this info, +connect to your mesh device, and edit the following config file: + +``` +$ sudo nano /etc/cjdroute.conf +``` + +This file contains everything that is required for cjdns to run, so be careful not to remove anything else, unless +you know what you are doing. You need to head down to this line: + +``` +// Nodes to connect to (IPv4 only). +"connectTo": +{ +``` + +This is where you input the ipv4 address. There is also a ipv6 field: + +``` +// Nodes to connect to (IPv6 only). +"connectTo": +{ +``` + +Insert the respective code, and the save (ctrl+X to save, then ctrl+S to confirm file name, then ENTER to confirm changes). +your code should look somewhat like this: +``` + // Nodes to connect to (IPv4 only). + "connectTo": + { + "159.203.5.91:30664": { + "peerName": "deprecated.systems", + "login": "tomesh-public", + "password": "iuw4nklm3j89qno876ef2jabpvlg1j0", + "publicKey": "2scyvybg4qqms1c5c9nyt50b1cdscxnr6ycpwsxf6pccbmwuynk0.k" + } + } +``` + +Next you should restart cjdns with a `sudo systemctl restart cjnds` command. This will reload cjdns +with the new config file. Run a `status` command on your node, and make sure when it prints out +the text, that cjdns is green with the text `[ACTIVE]`. if so, you have successfully connected to the remote peer, +if it says `[INACTIVE]`, then there might be a typo in your config file. Make sure its formatted correctly (the +config file is written using JSON). + +### Yggdrasil + +To connect to the "Deprecated Systems" node via Yggdrasil, you must do the similar as above, but with quite a few less steps. + +On the [deprecated.systems](https://deprecated.systems/) website, there is a section outlining the info for Yggdrasil: + +``` +"104.248.104.141:59168" +"[2604:a880:cad:d0::45:d001]:59168" +``` + +One is ipv4, the other ipv6. Head over to your mesh node yet again, and enter the following in your terminal: + +``` +$ sudo nano /etc/yggdrasil.conf +``` + +We are interested in this section of the config file: + +``` +List of connection strings for static peers in URI format, e.g. tcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j. +Peers: [] +``` + +This is where we are going to insert the code to connect to the peer node. Your code should look similar to this: + +``` +Peers: ["tcp://104.248.104.141:59168"] +``` + +Exit out of nano and save the changes. Restart Yggdrasil with a `sudo killall yggdrasil` command. Pass a `status` +command to terminal and you should see green text where Yggdrasil is printed with the words `[ACTIVE]` present. +You are now connected to the remote peer with Yggdrasil. If you see`[INACTIVE]`, then you need to check your code +for typos, make sure there are "" around the whole entire string. From 98f89c9626f1218462bbcdc70919c93cbcb4c8f5 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 21 Feb 2019 16:42:04 -0500 Subject: [PATCH 132/162] Yggdrasil Bump 3.3 (#302) --- scripts/yggdrasil/install | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/yggdrasil/install b/scripts/yggdrasil/install index bf9b8b8f0..631303802 100644 --- a/scripts/yggdrasil/install +++ b/scripts/yggdrasil/install @@ -2,8 +2,8 @@ set -e -YGGDRASIL_VERSION=0.3.2 -YGGDRASIL_HOST=419-115685026 +YGGDRASIL_VERSION=0.3.3 +YGGDRASIL_HOST=494-115685026 BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" From 796ff85427efa5d23ce28e86c94253d9cce29f52 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 21 Feb 2019 16:45:01 -0500 Subject: [PATCH 133/162] Script to configure github quickly (#279) --- contrib/github-setup/setid.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 contrib/github-setup/setid.sh diff --git a/contrib/github-setup/setid.sh b/contrib/github-setup/setid.sh new file mode 100644 index 000000000..56719d7ea --- /dev/null +++ b/contrib/github-setup/setid.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +if [ -z "$1" ] && [ -z "$2" ]; then + echo Syntax + echo setid \[git-hub login\] + exit 0 +fi + +git config --global user.email "$1@users.noreply.github.com" +git config --global user.name "$1" From 50470d4e16ea4ab5d31bcfd7ad40f988a1b8b097 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 22 Feb 2019 14:05:24 -0500 Subject: [PATCH 134/162] Enabled hostapd option on pi zero --- scripts/install2 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/install2 b/scripts/install2 index d0b551899..0befa137f 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -90,6 +90,7 @@ else if [[ $BOARD_REVISION == *"900092"* || $BOARD_REVISION == *"900093"* || $BOARD_REVISION == *"9000c1"* ]]; then BOARD_NAME="Zero" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 NO_TEST=1 CFLAGS=\"-s -mfpu=vfp -O2\" ./do" + SUPPORT_HOSTAP=true elif [[ $BOARD_REVISION == *"00"* ]]; then BOARD_NAME="1" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 NO_TEST=1 CFLAGS=\"-s -static -Wall\" ./do" From 7eada9d95cb64041d73d52ce034920a13af2ca90 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 22 Feb 2019 20:39:45 -0500 Subject: [PATCH 135/162] Remove presistent file on uninstall (#308) --- scripts/hostapd/uninstall | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/hostapd/uninstall b/scripts/hostapd/uninstall index 7f4e0b3d7..ba581d501 100755 --- a/scripts/hostapd/uninstall +++ b/scripts/hostapd/uninstall @@ -25,3 +25,4 @@ sudo rm -f /etc/hostapd/ca.pem sudo rm -f /etc/hostapd/server.pem sudo rm -f /etc/hostapd/nat.sh sudo rm -f /etc/systemd/system/hostapd.service +sudo rm -rf /etc/udev/rules.d/70-persistent-net.rules || true From 4760f95856c7f795aa55ccaf39cf87bd5ee0d764 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 22 Feb 2019 20:40:43 -0500 Subject: [PATCH 136/162] iptunnel server nat (#306) --- scripts/cjdns-iptunnel/cjdns-setup | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/cjdns-iptunnel/cjdns-setup b/scripts/cjdns-iptunnel/cjdns-setup index efaf66838..36529cadb 100755 --- a/scripts/cjdns-iptunnel/cjdns-setup +++ b/scripts/cjdns-iptunnel/cjdns-setup @@ -34,6 +34,11 @@ if [ -e /etc/cjdns.iptunnel.server ]; then fi done < /etc/cjdns.iptunnel.server + # If no NAT (masquarading) being done, start doing it + if [ -z "$(sudo iptables -L POSTROUTING -v -n -t nat | grep MASQUERADE)" ]; then + sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE + fi + # Configure as cjdns iptunnel client if client file is present (this is simply a newline-separated list # of cjdns public keys in /etc/cjdns.iptunnel.client, each key indicating an iptunnel exit server) elif [ -e /etc/cjdns.iptunnel.client ]; then From 50ec4d54c2e64d705e86ca7a591c4b95c44dc29d Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 22 Feb 2019 20:41:09 -0500 Subject: [PATCH 137/162] Added pi adhoc profile (#307) --- scripts/install2 | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/scripts/install2 b/scripts/install2 index 0befa137f..c1d379142 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -162,7 +162,7 @@ if [ "$(checkModule 'WITH_DIALOG')" ]; then fi -askSelection "A Basic node\nB IPFS Node\nC Monitor Node\nD SSB Node\nE Camera Node\nZ Custom" "Select node install type" Z +askSelection "A Basic node\nB IPFS Node\nC Monitor Node\nD SSB Node\nE Camera Node\nF Raspberry Pi Adhoc (Experimental) \nZ Custom" "Select node install type" Z case "$dialogREPLY" in "A") @@ -255,6 +255,25 @@ case "$dialogREPLY" in WITH_SSB_PATCHFOO=false WITH_IPFS_PI_STREAM=true ;; + "F") + echo "Raspberry Pi Ad-Hoc" + WITH_YGGDRASIL=true + WITH_MESH_POINT=false + WITH_AD_HOC=true + WITH_WIFI_AP=false + WITH_FIREWALL=true + WITH_CJDNS_IPTUNNEL=true + WITH_IPFS=false + WITH_PROMETHEUS_NODE_EXPORTER=true + WITH_EXTRA_TOOLS=true + WITH_WATCHDOG=true + WITH_YRD=true + WITH_PROMETHEUS_SERVER=false + WITH_GRAFANA=false + WITH_SSB=false + WITH_SSB_PATCHFOO=false + WITH_IPFS_PI_STREAM=false + ;; "Z") ;; *) From 75f43c866a26dc7028cb56d883173914fb4a5440 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 22 Feb 2019 20:50:39 -0500 Subject: [PATCH 138/162] add kill wpa-supplicant to adhoc script (#304) * wkill wpa_supplicant in adhoc script * Check first for wlan-ap then sudo kill --- scripts/mesh-adhoc/mesh-adhoc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/mesh-adhoc/mesh-adhoc b/scripts/mesh-adhoc/mesh-adhoc index be5dc158a..4744f76ce 100755 --- a/scripts/mesh-adhoc/mesh-adhoc +++ b/scripts/mesh-adhoc/mesh-adhoc @@ -5,6 +5,12 @@ set -e # Set wireless regulatory domain sudo iw reg set CA +# Is it safe to stop wpa_supplicant. Is AP running +if [ ! -d /sys/class/net/wlan-ap ]; then + # Kill wpa_supplicant with sometimes conflicts with IBSS Ad-Hoc + sudo killall wpa_supplicant || true +fi + # Select physical device that supports IBSS Ad-hoc mesh_dev="wlan0" @@ -21,7 +27,7 @@ sudo ifconfig $mesh_dev up # sudo ifconfig $mesh_dev 192.168.X.Y # Join the mesh network -# To join radio in HT40+ htmode (enable 802.11n rates) add HT40+ to end of this line +# To join radio in HT40+ htmode (enable 802.11n rates) add HT40+ to end of this line sudo iw dev $mesh_dev ibss join MESH_NAME 2412 # Restart cjdns From c29dd6a13ab2b142c584bbb475cf44c1ddd0dd48 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 22 Feb 2019 23:17:31 -0500 Subject: [PATCH 139/162] Added no neon binary installs --- scripts/install2 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/install2 b/scripts/install2 index c1d379142..d425ae7b2 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -58,7 +58,7 @@ if [[ "$BOARD_HARDWARE" == 'Allwinner' || "$BOARD_HARDWARE" == 'Generic' ]]; the fi #TODO# -O2 workaround. Needs to be resolved. CJDNS_BUILD_CMD="sudo Seccomp_NO=1 CFLAGS=\"-O2 -s -static -Wall -march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -fomit-frame-pointer -marm\" ./do" - CJDNS_PACKAGE="cjdns-neon-v4.deb" + CJDNS_PACKAGE="cjdns-neon-v4.deb" elif [[ "$BOARD_HARDWARE" == 'nanopineo2' || "$BOARD_HARDWARE" == 'sun50iw1p1' || "$BOARD_HARDWARE" == 'orangepizeroplus2-h5' || "$BOARD_HARDWARE" == 'rock64' || @@ -91,9 +91,11 @@ else BOARD_NAME="Zero" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 NO_TEST=1 CFLAGS=\"-s -mfpu=vfp -O2\" ./do" SUPPORT_HOSTAP=true + CJDNS_PACKAGE="cjdns-no-neon-v4.deb" elif [[ $BOARD_REVISION == *"00"* ]]; then BOARD_NAME="1" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 NO_TEST=1 CFLAGS=\"-s -static -Wall\" ./do" + CJDNS_PACKAGE="cjdns-no-neon-v4.deb" elif [[ $BOARD_REVISION == *"a01041"* || $BOARD_REVISION == *"a21041"* ]]; then BOARD_NAME="2" CJDNS_BUILD_CMD="sudo NO_TEST=1 CFLAGS=\"-mfpu=neon-vfpv4 -O2\" ./do" From 6073f1d4a5ba343cd116fd39b0cb7b92c6aa3d7c Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Sun, 24 Feb 2019 13:02:17 -0500 Subject: [PATCH 140/162] initial batman adv mesh --- contrib/batman-adv/batman-adv-mesh.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 contrib/batman-adv/batman-adv-mesh.sh diff --git a/contrib/batman-adv/batman-adv-mesh.sh b/contrib/batman-adv/batman-adv-mesh.sh new file mode 100644 index 000000000..3b495e685 --- /dev/null +++ b/contrib/batman-adv/batman-adv-mesh.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# Install batman adv +sudo apt-get install -y batctl + +# configure batman-adv +sudo modprobe batman-adv +sudo batctl if add wlan0 +sudo ifconfig bat0 up From 1f5e96f0389ba08ca9a759ca515ce458a5e629c3 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 25 Feb 2019 14:52:50 -0500 Subject: [PATCH 141/162] Make a local-link ip out of yggdrasil ip --- scripts/mesh-adhoc/mesh-adhoc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/mesh-adhoc/mesh-adhoc b/scripts/mesh-adhoc/mesh-adhoc index 4744f76ce..cee7be914 100755 --- a/scripts/mesh-adhoc/mesh-adhoc +++ b/scripts/mesh-adhoc/mesh-adhoc @@ -30,5 +30,13 @@ sudo ifconfig $mesh_dev up # To join radio in HT40+ htmode (enable 802.11n rates) add HT40+ to end of this line sudo iw dev $mesh_dev ibss join MESH_NAME 2412 +# Make a local-link ip out of yggdrasil ip if $mesh_dev does not have a local-link ip +if [ ! -z "$(which yggdrasilctl)" ]; then + if [ -z "$(ip addr show dev $mesh_dev | grep inet6\ fe)" ]; then + ip=$(yggdrasilctl getSelf | grep "IPv6 address" | awk '{print $3}') + ip address add dev $mesh_dev scope link fe80::${ip:20}/64 + fi +fi + # Restart cjdns sudo killall cjdroute From 3fc1a3ee8df7139071db2824a6696134a4461614 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 25 Feb 2019 14:53:09 -0500 Subject: [PATCH 142/162] Make a local-link ip out of yggdrasil ip --- scripts/mesh-point/mesh-point | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scripts/mesh-point/mesh-point b/scripts/mesh-point/mesh-point index 94e805a07..a54e89bf6 100755 --- a/scripts/mesh-point/mesh-point +++ b/scripts/mesh-point/mesh-point @@ -61,5 +61,13 @@ sudo iw dev $mesh_dev set mesh_param mesh_fwding=0 # Prevent trying to establish connections with nodes under -65 dBm sudo iw dev $mesh_dev set mesh_param mesh_rssi_threshold -65 +# Make a local-link ip out of yggdrasil ip if $mesh_dev does not have a local-link ip +if [ ! -z "$(which yggdrasilctl)" ]; then + if [ -z "$(ip addr show dev $mesh_dev | grep inet6\ fe)" ]; then + ip=$(yggdrasilctl getSelf | grep "IPv6 address" | awk '{print $3}') + ip address add dev $mesh_dev scope link fe80::${ip:20}/64 + fi +fi + # Restart cjdns sudo killall cjdroute From 10e96edb3cc0aae6360c7f268ee4c1fc185ab677 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 25 Feb 2019 15:00:02 -0500 Subject: [PATCH 143/162] better address truncating --- scripts/mesh-adhoc/mesh-adhoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mesh-adhoc/mesh-adhoc b/scripts/mesh-adhoc/mesh-adhoc index cee7be914..43aae9d3a 100755 --- a/scripts/mesh-adhoc/mesh-adhoc +++ b/scripts/mesh-adhoc/mesh-adhoc @@ -33,8 +33,8 @@ sudo iw dev $mesh_dev ibss join MESH_NAME 2412 # Make a local-link ip out of yggdrasil ip if $mesh_dev does not have a local-link ip if [ ! -z "$(which yggdrasilctl)" ]; then if [ -z "$(ip addr show dev $mesh_dev | grep inet6\ fe)" ]; then - ip=$(yggdrasilctl getSelf | grep "IPv6 address" | awk '{print $3}') - ip address add dev $mesh_dev scope link fe80::${ip:20}/64 + ip="$(sudo yggdrasilctl getSelf | grep "IPv6 address" | awk '{print $3}' | cut -d ":" -f5-8)" + ip address add dev $mesh_dev scope link fe80::${ip}/64 fi fi From 3dfc1dd676fc4a6e6c2ad43b2380a9c3199c0d7d Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 25 Feb 2019 15:00:20 -0500 Subject: [PATCH 144/162] Better address truncating --- scripts/mesh-point/mesh-point | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mesh-point/mesh-point b/scripts/mesh-point/mesh-point index a54e89bf6..33fa96428 100755 --- a/scripts/mesh-point/mesh-point +++ b/scripts/mesh-point/mesh-point @@ -64,8 +64,8 @@ sudo iw dev $mesh_dev set mesh_param mesh_rssi_threshold -65 # Make a local-link ip out of yggdrasil ip if $mesh_dev does not have a local-link ip if [ ! -z "$(which yggdrasilctl)" ]; then if [ -z "$(ip addr show dev $mesh_dev | grep inet6\ fe)" ]; then - ip=$(yggdrasilctl getSelf | grep "IPv6 address" | awk '{print $3}') - ip address add dev $mesh_dev scope link fe80::${ip:20}/64 + ip="$(sudo yggdrasilctl getSelf | grep "IPv6 address" | awk '{print $3}' | cut -d ":" -f5-8)" + ip address add dev $mesh_dev scope link fe80::${ip}/64 fi fi From eefedfeac4005116d0cd022f94982276037dfc17 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 26 Feb 2019 12:54:28 -0500 Subject: [PATCH 145/162] yggdrasil IP Tunnel (#305) Initial yggdrasill iptunnel script Update install added jq to install Remove sleep Added documentation and install and uninstall --- docs/MODULES.md | 34 +++++++++++ scripts/cjdns-iptunnel/uninstall | 7 ++- scripts/install | 1 + scripts/install2 | 57 ++++++++----------- scripts/uninstall | 4 +- scripts/yggdrasil-iptunnel/install | 22 +++++++ scripts/yggdrasil-iptunnel/uninstall | 13 +++++ .../yggdrasil-iptunnel/yggdrasil-pre-setup | 43 ++++++++++++++ scripts/yggdrasil-iptunnel/yggdrasil-setup | 40 +++++++++++++ 9 files changed, 186 insertions(+), 35 deletions(-) create mode 100644 scripts/yggdrasil-iptunnel/install create mode 100644 scripts/yggdrasil-iptunnel/uninstall create mode 100644 scripts/yggdrasil-iptunnel/yggdrasil-pre-setup create mode 100644 scripts/yggdrasil-iptunnel/yggdrasil-setup diff --git a/docs/MODULES.md b/docs/MODULES.md index 94179a925..128f70c3c 100644 --- a/docs/MODULES.md +++ b/docs/MODULES.md @@ -25,6 +25,8 @@ A short summary of each module is directly below. Documentation for specific abi | `WITH_WATCHDOG` | None | Set to `true` if you want to enable hardware watchdog that will reset the device when the operating system becomes unresponsive. | | `WITH_YRD` | None | Set to `true` if you want to enable [yrd](https://github.com/kpcyrd/yrd), a helpful command-line tool for cjdns. | | `WITH_YGGDRASIL` | None | Set to `true` if you want to install [Yggdrasil](https://yggdrasil-network.github.io/), an alternate and possibly more efficient mesh routing software than CJDNS. | +| `WITH_YGGDRASIL_IPTUNNEL` | None | Set to `true` if you want to use the yggdrasil iptunnel feature to set up an Internet gateway for your node. To configure as a server (exit Internet traffic for other nodes), create **/etc/yggdrasil.iptunnel.server** containing a newline-separated list of yggdrasil public keys of allowed clients and an ipaddress for that client. To configure as a client (use an exit server to access the Internet), create **/etc/yggdrasil.iptunnel.client** containing a newline-separated list of yggdrasil public keys of the gateway servers followed by the IP address set on the server. You can only configure as one or the other, not both and you can only have one entry on the client. | + To install all optional modules (not recommended), run the following command: @@ -50,6 +52,38 @@ Yggdrasil will give each node (like your Pi, for example) an IPv6 address, but i However, the Pi does have a firewall, so various commands need be run to allow access to clients. By default all Yggdrasil client access is blocked. See [**Firewall/IPv6/Yggdrasil Clients**](#yggdrasil-clients) to learn how to change that. +### Yggdrasil IPTunnel + +This module will allow you to tunnel internet from an EXIT node (server) that has Internet to another node that does not. To do this you must exchange public keys. The public key can be found in /etc/yggdrasil.conf + +#### Server + To configure as a server (exit Internet traffic for other nodes), + 1. create **/etc/yggdrasil.iptunnel.server** + 1. fill it with newline-separated list of: + - public key of the clients + - single white space + - IP Address in the 10.10.0.0/24 range that will be assigned to the client + +Example +``` +1234567890123456789012345678901234567890123456789012345678901234 10.10.0.1 +2345678901234567890123456789012345678901234567890123456789012345 10.10.0.2 +3456789012345678901234567890123456789012345678901234567890123467 10.10.0.3 +``` + +#### Client +To configure as a client (use an exit server to access the Internet), +1. create **/etc/yggdrasil.iptunnel.client** +1. place a single line containing + - public key of the server + - single space + - IP Address assigned to you by the server + +Example +``` +4567890123456789012345678901234567890123456789012345678901234567 10.10.0.4 +``` + ## IPFS IPFS stands for Interplanetary File System. It is an open-source, peer-to-peer distributed hypermedia protocol that aims to function as a ubiquitous file system for all computing devices. diff --git a/scripts/cjdns-iptunnel/uninstall b/scripts/cjdns-iptunnel/uninstall index 0a639c868..c1b5af52b 100755 --- a/scripts/cjdns-iptunnel/uninstall +++ b/scripts/cjdns-iptunnel/uninstall @@ -3,5 +3,10 @@ set -e # Uninstall scripts that configure cjdns iptunnel -sudo rm /etc/udev/rules.d/50-cjdns.rules sudo rm /usr/local/sbin/cjdns-setup +if [ -f /lib/systemd/system/cjdns.service ]; then + sudo sed -i /ExecStartPost/d /lib/systemd/system/cjdns.service +fi +if [ -f /etc/systemd/system/cjdns.service ]; then + sudo sed -i /ExecStartPost/d /etc/systemd/system/cjdns.service +fi \ No newline at end of file diff --git a/scripts/install b/scripts/install index 61a3dc992..2eb8c1c59 100755 --- a/scripts/install +++ b/scripts/install @@ -41,6 +41,7 @@ git checkout $TAG_PROTOTYPE_CJDNS_PI # Export environment variables export WITH_YGGDRASIL +export WITH_YGGDRASIL_IPTUNNEL export WITH_MESH_POINT export WITH_AD_HOC export WITH_WIFI_AP diff --git a/scripts/install2 b/scripts/install2 index d425ae7b2..cfefbdcc9 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -90,12 +90,12 @@ else if [[ $BOARD_REVISION == *"900092"* || $BOARD_REVISION == *"900093"* || $BOARD_REVISION == *"9000c1"* ]]; then BOARD_NAME="Zero" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 NO_TEST=1 CFLAGS=\"-s -mfpu=vfp -O2\" ./do" - SUPPORT_HOSTAP=true - CJDNS_PACKAGE="cjdns-no-neon-v4.deb" + SUPPORT_HOSTAP=true + CJDNS_PACKAGE="cjdns-no-neon-v4.deb" elif [[ $BOARD_REVISION == *"00"* ]]; then BOARD_NAME="1" CJDNS_BUILD_CMD="sudo Seccomp_NO=1 NO_NEON=1 NO_TEST=1 CFLAGS=\"-s -static -Wall\" ./do" - CJDNS_PACKAGE="cjdns-no-neon-v4.deb" + CJDNS_PACKAGE="cjdns-no-neon-v4.deb" elif [[ $BOARD_REVISION == *"a01041"* || $BOARD_REVISION == *"a21041"* ]]; then BOARD_NAME="2" CJDNS_BUILD_CMD="sudo NO_TEST=1 CFLAGS=\"-mfpu=neon-vfpv4 -O2\" ./do" @@ -164,14 +164,15 @@ if [ "$(checkModule 'WITH_DIALOG')" ]; then fi -askSelection "A Basic node\nB IPFS Node\nC Monitor Node\nD SSB Node\nE Camera Node\nF Raspberry Pi Adhoc (Experimental) \nZ Custom" "Select node install type" Z +askSelection "A Basic node\nB IPFS Node\nC Monitor Node\nD SSB Node\nE Camera Node\nZ Custom" "Select node install type" Z case "$dialogREPLY" in "A") echo "Basic node" - WITH_YGGDRASIL=true - WITH_MESH_POINT="" - WITH_WIFI_AP="" + WITH_YGGDRASIL=true + WITH_YGGDRASIL_IPTUNNEL=true + WITH_MESH_POINT="" + WITH_WIFI_AP="" WITH_FIREWALL=true WITH_CJDNS_IPTUNNEL=true WITH_IPFS=false @@ -187,7 +188,8 @@ case "$dialogREPLY" in ;; "B") echo "Basic IPFS node" - WITH_YGGDRASIL=true + WITH_YGGDRASIL=true + WITH_YGGDRASIL_IPTUNNEL=true WITH_MESH_POINT="" WITH_WIFI_AP="" WITH_FIREWALL=true @@ -205,7 +207,8 @@ case "$dialogREPLY" in ;; "C") echo "Monitor Node" - WITH_YGGDRASIL=true + WITH_YGGDRASIL=true + WITH_YGGDRASIL_IPTUNNEL=true WITH_MESH_POINT="" WITH_WIFI_AP="" WITH_FIREWALL=true @@ -223,7 +226,8 @@ case "$dialogREPLY" in ;; "D") echo "SSB Node" - WITH_YGGDRASIL=true + WITH_YGGDRASIL=true + WITH_YGGDRASIL_IPTUNNEL=true WITH_MESH_POINT="" WITH_WIFI_AP="" WITH_FIREWALL=true @@ -241,7 +245,8 @@ case "$dialogREPLY" in ;; "E") echo "IPFS Camera Node" - WITH_YGGDRASIL=true + WITH_YGGDRASIL=true + WITH_YGGDRASIL_IPTUNNEL=true WITH_MESH_POINT="" WITH_WIFI_AP="" WITH_FIREWALL=true @@ -257,25 +262,6 @@ case "$dialogREPLY" in WITH_SSB_PATCHFOO=false WITH_IPFS_PI_STREAM=true ;; - "F") - echo "Raspberry Pi Ad-Hoc" - WITH_YGGDRASIL=true - WITH_MESH_POINT=false - WITH_AD_HOC=true - WITH_WIFI_AP=false - WITH_FIREWALL=true - WITH_CJDNS_IPTUNNEL=true - WITH_IPFS=false - WITH_PROMETHEUS_NODE_EXPORTER=true - WITH_EXTRA_TOOLS=true - WITH_WATCHDOG=true - WITH_YRD=true - WITH_PROMETHEUS_SERVER=false - WITH_GRAFANA=false - WITH_SSB=false - WITH_SSB_PATCHFOO=false - WITH_IPFS_PI_STREAM=false - ;; "Z") ;; *) @@ -296,7 +282,9 @@ fi export MESH_NAME askModule "WITH_YGGDRASIL" "Yggdrasil routing engine" - +if [ "$WITH_YGGDRASIL" == "true" ]; then + askModule "WITH_YGGDRASIL_IPTUNNEL" "Internet Gateway over Yggdrasil" +fi askModule "WITH_MESH_POINT" "Mesh Point Interface" if [ "$WITH_MESH_POINT" == false ]; then askModule "WITH_AD_HOC" "Ad-Hoc Interface" @@ -305,7 +293,7 @@ if [ "$SUPPORT_HOSTAP" == "true" ]; then askModule "WITH_WIFI_AP" "WiFi Access Point" fi askModule "WITH_FIREWALL" "Basic Firewall" -askModule "WITH_CJDNS_IPTUNNEL" "Internet Gateway" +askModule "WITH_CJDNS_IPTUNNEL" "Internet Gateway over CJDNS" askModule "WITH_IPFS" "IPFS" if [ "$WITH_IPFS" == true ] && [ "$BOARD_FAMILY" == "Raspberry Pi" ]; then askModule "WITH_IPFS_PI_STREAM" "IPFS Pi Stream" "n" @@ -443,7 +431,10 @@ fi if [ "$(checkModule 'WITH_CJDNS_IPTUNNEL')" ]; then source cjdns-iptunnel/install fi - +# Configure Internet gateway using yggdrasil iptunnel +if [ "$(checkModule 'WITH_YGGDRASIL_IPTUNNEL')" ]; then + source cjdns-iptunnel/install +fi # IPFS if [ ! -x "$(command -v ipfs)" ] && [ "$(checkModule 'WITH_IPFS')" ]; then source ipfs/install diff --git a/scripts/uninstall b/scripts/uninstall index c894c1d94..9c41426bb 100755 --- a/scripts/uninstall +++ b/scripts/uninstall @@ -25,6 +25,7 @@ if [ -f "/etc/cjdroute.conf" ]; then fi # Uninstall optional modules +source "$BASE_DIR/cjdns-iptunnel/uninstall" source "$BASE_DIR/ssb/uninstall" source "$BASE_DIR/mesh-point/uninstall" source "$BASE_DIR/mesh-adhoc/uninstall" @@ -40,10 +41,11 @@ source "$BASE_DIR/yrd/uninstall" source "$BASE_DIR/shared/nodeinfo/uninstall" source "$BASE_DIR/nginx/uninstall" source "$BASE_DIR/yggdrasil/uninstall" +source "$BASE_DIR/yggdrasil-iptunnel/uninstall" sudo systemctl daemon-reload -sudo sed -i 's/service dnsmasq restart//' /etc/rc.local +sudo sed -i 's/service dnsmasq restart//' /etc/rc.local # Uninstall status script sudo rm -f /usr/local/bin/status diff --git a/scripts/yggdrasil-iptunnel/install b/scripts/yggdrasil-iptunnel/install new file mode 100644 index 000000000..ffc5e0727 --- /dev/null +++ b/scripts/yggdrasil-iptunnel/install @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -e + +BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +sudo apt-get -y install jq + +sudo cp "$BASE_DIR/yggdrasil-setup" "/usr/local/sbin/yggdrasil-setup" +sudo cp "$BASE_DIR/yggdrasil-pre-setup" "/usr/local/sbin/yggdrasil-pre-setup" + +sudo chmod a+x /usr/local/sbin/yggdrasil-pre-setup +sudo chmod a+x /usr/local/sbin/yggdrasil-setup + +# Update service to start script on cjdns start +if [ -f /etc/systemd/system/yggdrasil.service ]; then + sudo sed -i /ExecStartPost/d /etc/systemd/system/yggdrasil.service + sudo sed -i s#Restart=always#Restart=always\\nExecStartPost=/usr/local/sbin/yggdrasil-setup# /etc/systemd/system/yggdrasil.service + sudo sed -i "s#fi\"#fi; /usr/local/sbin/yggdrasil-pre-setup\"#" /etc/systemd/system/yggdrasil.service +fi + +sudo systemctl daemon-reload diff --git a/scripts/yggdrasil-iptunnel/uninstall b/scripts/yggdrasil-iptunnel/uninstall new file mode 100644 index 000000000..9332895b3 --- /dev/null +++ b/scripts/yggdrasil-iptunnel/uninstall @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -e + +# Uninstall scripts that configure yggdrasil iptunnel +sudo rm /usr/local/sbin/yggdrasil-setup +sudo rm /usr/local/sbin/yggdrasil-pre-setup +if [ -f /lib/systemd/system/yggdrasil.service ]; then + sudo sed -i /ExecStartPost/d /lib/systemd/system/yggdrasil.service +fi +if [ -f /etc/systemd/system/yggdrasil.service ]; then + sudo sed -i /ExecStartPost/d /etc/systemd/system/yggdrasil.service +fi diff --git a/scripts/yggdrasil-iptunnel/yggdrasil-pre-setup b/scripts/yggdrasil-iptunnel/yggdrasil-pre-setup new file mode 100644 index 000000000..f6a5a46bf --- /dev/null +++ b/scripts/yggdrasil-iptunnel/yggdrasil-pre-setup @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Convert existing yggdrasil config to json from hjson + +# Detect if there is a # as a first character of the file. +# If it is then its proably a hjson and needs to be converted into json +if [ ! -z "$(tr -d ' \t\r\f' < /etc/yggdrasil.conf | grep -i "^[#]")" ]; then + sudo mv /etc/yggdrasil.conf /etc/yggdrasil.conf.orig + sudo yggdrasil -useconffile /etc/yggdrasil.conf.orig -normaliseconf -json | sudo tee /etc/yggdrasil.conf > /dev/null +fi + +if [ -e /etc/yggdrasil.iptunnel.server ]; then + # Add each client to yggdrasil iptunnel allowed connections + while read -r PUBLIC_KEY IP_ADDR; do + if [[ "${PUBLIC_KEY}" =~ ^[0-z]{64}]]; then + IPv4Destinations="${IPv4Destinations} \"${IP_ADDR}/32\": \"${PUBLIC_KEY}\"," + fi + done < /etc/yggdrasil.iptunnel.server + + # Trim last , + IPv4Destinations="${IPv4Destinations%?}" + IPv4Sources="0.0.0.0/0" +elif [ -e /etc/yggdrasil.iptunnel.client ]; then + # Add each server to yggdrasil iptunnel connect-to's + while read -r PUBLIC_KEY IP_ADDR; do + if [[ "${PUBLIC_KEY}" =~ ^[0-z]{64} ]]; then + IPv4Destinations="\"0.0.0.0/0\": \"${PUBLIC_KEY}\"" + IPv4Sources="${IP_ADDR}/32" + fi + done < /etc/yggdrasil.iptunnel.client + fi + +# Check if there are values to set in the new config file +if [ ! -z "$IPv4Sources" ];then + # Re-write tunnel routing + sudo jq 'del(.TunnelRouting)' /etc/yggdrasil.conf > /tmp/yggdrasil.conf + sudo jq '.TunnelRouting.Enable = true' /tmp/yggdrasil.conf > /tmp/yggdrasil-edit.conf && sudo mv /tmp/yggdrasil-edit.conf /tmp/yggdrasil.conf + sudo jq '.TunnelRouting.IPv4Sources = "__IPv4Sources__"' /tmp/yggdrasil.conf > /tmp/yggdrasil-edit.conf && sudo mv /tmp/yggdrasil-edit.conf /tmp/yggdrasil.conf + sudo jq '.TunnelRouting.IPv4Destinations = "__IPv4Destinations__"' /tmp/yggdrasil.conf > /tmp/yggdrasil-edit.conf && sudo mv /tmp/yggdrasil-edit.conf /tmp/yggdrasil.conf + sudo sed -i "s#\"__IPv4Sources__\"#[\"$IPv4Sources\"]#" /tmp/yggdrasil.conf + sudo sed -i "s#\"__IPv4Destinations__\"#\{$IPv4Destinations\}#" /tmp/yggdrasil.conf + sudo mv /tmp/yggdrasil.conf /etc/yggdrasil.conf +fi diff --git a/scripts/yggdrasil-iptunnel/yggdrasil-setup b/scripts/yggdrasil-iptunnel/yggdrasil-setup new file mode 100644 index 000000000..00965288b --- /dev/null +++ b/scripts/yggdrasil-iptunnel/yggdrasil-setup @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +# Enable forwarding for ipv4 and ipv6 +echo 1 > /proc/sys/net/ipv4/ip_forward +echo 1 > /proc/sys/net/ipv6/conf/all/forwarding + +SUBNET4="10.10.0." + +# Give yggdrasil enough time to create an ygg0 interface before we start adding routes +sleep 5 + +if [ -e /etc/yggdrasil.iptunnel.server ]; then + # Add route for cjdns ygg0 interface + sudo route add -net "${SUBNET4}0/24" ygg0 || true + + # If no NAT (masquarading) being done, start doing it + if [ -z "$(sudo iptables -L POSTROUTING -v -n -t nat | grep MASQUERADE)" ]; then + sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE + fi +# Configure as yggdrasil iptunnel client if client file is present (this is simply a newline-separated list +# of cjdns public keys in /etc/yggdrasil.iptunnel.client, each key indicating an iptunnel exit server) +elif [ -e /etc/yggdrasil.iptunnel.client ]; then + + # Add each server to yggdrasil iptunnel connect-to's + while read -r PUBLIC_KEY ASSIGNED_IP; do + if [[ "${PUBLIC_KEY}" =~ ^[0-z]{64} ]]; then + sudo ip addr add dev ygg0 ${ASSIGNED_IP}/32 + fi + done < /etc/yggdrasil.iptunnel.client + + # Remove NAT from eth0 if it exists + sudo iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE || true + + # Route NAT traffic through to yggdrasil ygg0 interface to use iptunnel exit server + sudo iptables -t nat -A POSTROUTING -o ygg0 -j MASQUERADE + + # Special hack to change default route without removing original one + sudo route add -net 0.0.0.0/1 ygg0 + sudo route add -net 128.0.0.0/1 ygg0 +fi From e03a712554835cff05619830786cef2fa50d9574 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 26 Feb 2019 12:56:48 -0500 Subject: [PATCH 146/162] corrected space --- scripts/yggdrasil-iptunnel/yggdrasil-pre-setup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/yggdrasil-iptunnel/yggdrasil-pre-setup b/scripts/yggdrasil-iptunnel/yggdrasil-pre-setup index f6a5a46bf..04c24678d 100644 --- a/scripts/yggdrasil-iptunnel/yggdrasil-pre-setup +++ b/scripts/yggdrasil-iptunnel/yggdrasil-pre-setup @@ -12,7 +12,7 @@ fi if [ -e /etc/yggdrasil.iptunnel.server ]; then # Add each client to yggdrasil iptunnel allowed connections while read -r PUBLIC_KEY IP_ADDR; do - if [[ "${PUBLIC_KEY}" =~ ^[0-z]{64}]]; then + if [[ "${PUBLIC_KEY}" =~ ^[0-z]{64} ]]; then IPv4Destinations="${IPv4Destinations} \"${IP_ADDR}/32\": \"${PUBLIC_KEY}\"," fi done < /etc/yggdrasil.iptunnel.server From 621949eb23497dba77686b3e781a9f78562d5da1 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 26 Feb 2019 12:59:01 -0500 Subject: [PATCH 147/162] Update MODULES.md --- docs/MODULES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/MODULES.md b/docs/MODULES.md index 128f70c3c..6c12b5b21 100644 --- a/docs/MODULES.md +++ b/docs/MODULES.md @@ -60,7 +60,7 @@ This module will allow you to tunnel internet from an EXIT node (server) that ha To configure as a server (exit Internet traffic for other nodes), 1. create **/etc/yggdrasil.iptunnel.server** 1. fill it with newline-separated list of: - - public key of the clients + - EncryptionPublicKey key of the clients - single white space - IP Address in the 10.10.0.0/24 range that will be assigned to the client @@ -75,7 +75,7 @@ Example To configure as a client (use an exit server to access the Internet), 1. create **/etc/yggdrasil.iptunnel.client** 1. place a single line containing - - public key of the server + - EncryptionPublicKey of the server - single space - IP Address assigned to you by the server From ad492414e02a2b1f512ba3461712120f7e8f0f6a Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Tue, 26 Feb 2019 18:27:44 -0500 Subject: [PATCH 148/162] re-added pi profile --- scripts/install2 | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/scripts/install2 b/scripts/install2 index cfefbdcc9..f52018b1f 100755 --- a/scripts/install2 +++ b/scripts/install2 @@ -164,7 +164,7 @@ if [ "$(checkModule 'WITH_DIALOG')" ]; then fi -askSelection "A Basic node\nB IPFS Node\nC Monitor Node\nD SSB Node\nE Camera Node\nZ Custom" "Select node install type" Z +askSelection "A Basic node\nB IPFS Node\nC Monitor Node\nD SSB Node\nE Camera Node\nF Raspberry Pi Adhoc (Experimental)\nZ Custom" "Select node install type" Z case "$dialogREPLY" in "A") @@ -262,6 +262,25 @@ case "$dialogREPLY" in WITH_SSB_PATCHFOO=false WITH_IPFS_PI_STREAM=true ;; + "F") + echo "Raspberry Pi Ad-Hoc" + WITH_YGGDRASIL=true + WITH_MESH_POINT=false + WITH_AD_HOC=true + WITH_WIFI_AP=false + WITH_FIREWALL=true + WITH_CJDNS_IPTUNNEL=true + WITH_IPFS=false + WITH_PROMETHEUS_NODE_EXPORTER=true + WITH_EXTRA_TOOLS=true + WITH_WATCHDOG=true + WITH_YRD=true + WITH_PROMETHEUS_SERVER=false + WITH_GRAFANA=false + WITH_SSB=false + WITH_SSB_PATCHFOO=false + WITH_IPFS_PI_STREAM=false + ;; "Z") ;; *) From be79cdc60e7da29240d32bca8ae9c25bd912605a Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Wed, 27 Feb 2019 16:34:42 -0500 Subject: [PATCH 149/162] SSB Update (#315) * added unsafe-perm in case installed in root *renamed to ssb-server * Updated startup binary * updated sbot refrences * created file for plugins * Workarounds for faster install * Remove sleep replace with creating folder * Force remove all ssb-server packages --- scripts/ssb-patchfoo/config | 7 +++++++ scripts/ssb-patchfoo/install | 16 +++++++++++----- scripts/ssb/ssb.service | 2 +- scripts/ssb/uninstall | 1 + 4 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 scripts/ssb-patchfoo/config diff --git a/scripts/ssb-patchfoo/config b/scripts/ssb-patchfoo/config new file mode 100644 index 000000000..ce61ea20d --- /dev/null +++ b/scripts/ssb-patchfoo/config @@ -0,0 +1,7 @@ +{ + "plugins": { + "ssb-private": true, + "ssb-backlinks": true, + "patchfoo": true + } +} diff --git a/scripts/ssb-patchfoo/install b/scripts/ssb-patchfoo/install index 5e0cec6ba..9639a39a4 100755 --- a/scripts/ssb-patchfoo/install +++ b/scripts/ssb-patchfoo/install @@ -6,18 +6,24 @@ BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CURRENT_DIR="$(pwd)" -sleep 5 +# Make folder if service did not +mkdir -p ~/.ssb/node_modules || true # shellcheck disable=SC2164 cd ~/.ssb/node_modules # Install dependencies -npm install asyncmemo hashlru pull-stream pull-cat multicb hyperscript pull-paramap ssb-contact ssb-sort stream-to-pull-stream emoji-server pull-paginate ssb-mentions busboy mime-types pull-identify-filetype human-time pull-hyperscript jpeg-autorotate pull-catch diff pull-split pull-utf8-decoder ssb-web-resolver highlight.js pull-box-stream base64-url ssb-backlinks ssb-private +npm install --unsafe-perm asyncmemo hashlru pull-stream pull-cat multicb hyperscript pull-paramap ssb-contact ssb-sort stream-to-pull-stream emoji-server pull-paginate ssb-mentions busboy mime-types pull-identify-filetype human-time pull-hyperscript jpeg-autorotate pull-catch diff pull-split pull-utf8-decoder ssb-web-resolver highlight.js pull-box-stream base64-url ssb-backlinks ssb-private # Install patchfoo and enable plugin git clone https://github.com/ssbc/patchfoo.git patchfoo -sbot plugins.install ssb-private -sbot plugins.install ssb-backlinks -sbot plugins.enable patchfoo + +# Replace ssb-server plugins.install with a static config file +# This will prevent the installation of these modules a second time +# and compiling downlevel for a 3rd time +cp "$BASE_DIR/config" ~/.ssb +#ssb-server plugins.install ssb-private +#ssb-server plugins.install ssb-backlinks +#ssb-server plugins.enable patchfoo # Stop ssb service to process plugin sudo systemctl stop ssb diff --git a/scripts/ssb/ssb.service b/scripts/ssb/ssb.service index 1e3746a6f..9b617af4e 100644 --- a/scripts/ssb/ssb.service +++ b/scripts/ssb/ssb.service @@ -7,7 +7,7 @@ After=network.target User=__USER__ Group=__USER__ Type=simple -ExecStart=/usr/bin/sbot server +ExecStart=/usr/bin/ssb-server start ExecStop=/bin/kill -s QUIT $MAINPID Restart=on-failure RestartSec=10s diff --git a/scripts/ssb/uninstall b/scripts/ssb/uninstall index b525e019f..0d988c873 100755 --- a/scripts/ssb/uninstall +++ b/scripts/ssb/uninstall @@ -16,6 +16,7 @@ sudo rm -f /usr/bin/sbot || true sudo rm -f /etc/systemd/system/ssb.service sudo rm -f /etc/systemd/system/ssb-broadcast.service sudo rm -f /usr/local/bin/ssb-broadcast-service.sh +sudo rm -rf /usr/lib/node_modules/ssb-server || true if [ -d "$HOME/.ssb" ]; then echo "Found ~/.ssb" From 33ff20a673fbb04ca0a099b8be15d2032c54d123 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Wed, 27 Feb 2019 21:23:42 -0500 Subject: [PATCH 150/162] NodeExporter ygg rx/tx (#311) * Added yggdrasil peers report * missing json import * Remove sudo (already running as root) * Added cjdns peer information * Nodeexporter cjdns * Added cjdns keys from peerStats mac addresses for better linking for nodes s (#277) * correced inverted quotes * Corrected formatting * rollback of old code --- .../nodestats-tomesh.py | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/scripts/prometheus-node-exporter/nodestats-tomesh.py b/scripts/prometheus-node-exporter/nodestats-tomesh.py index 3927ff598..06aedd1e3 100644 --- a/scripts/prometheus-node-exporter/nodestats-tomesh.py +++ b/scripts/prometheus-node-exporter/nodestats-tomesh.py @@ -3,6 +3,7 @@ import time import shlex import subprocess +import json path = "/var/lib/node_exporter/ne-stats.prom" @@ -14,7 +15,7 @@ while 1: fifo = open(path, "w") - fifo.write("tomeshV 1.1\n") + fifo.write("tomeshV 1.2\n") s="" if os.path.isfile("/sys/devices/virtual/thermal/thermal_zone0/temp"): @@ -23,6 +24,35 @@ fifo.write("hw_temp ") fifo.write(s) + + #Wireless Link Dump + + # Get cjdns peer information + remotePeers = {} + myaddress="" + if os.path.isfile("/opt/cjdns/tools/cexec"): + command_line = "/opt/cjdns/tools/cexec \"Core_nodeInfo()\"" + args = shlex.split(command_line) + interfaces = subprocess.Popen(args,stdout=subprocess.PIPE) + interfaces.wait() + output = interfaces.stdout.read(); + data = json.loads(output) + tmp=data["myAddr"].split(".") + myaddress=tmp[5] + ".k" + myaddress=myaddress.splitlines()[0] + command_line = "/opt/cjdns/tools/peerStats" + args = shlex.split(command_line) + interface = subprocess.Popen(args,stdout=subprocess.PIPE) + interface.wait() + output = interface.stdout.read() + peers = output.split("\n") + for peer in peers: + words2= peer.split(" ") + if len(words2) > 1: + tmp=words2[1].split(".") + remotePubKey=tmp[5] + ".k" + remotePeers[words2[0]]=remotePubKey + # Look through wireless interfaces command_line = "iw dev" args = shlex.split(command_line) @@ -72,6 +102,9 @@ rx=-1 tx=-1 signal=-100 + cjdnsdata="" + if station in remotePeers: + cjdnsdata=',sourcekey="' + myaddress + '", key="' + remotePeers[station] + '"' if words3[1].find("signal") > -1: signal=words3[3] if words3[1].find("mesh") > -1 and words3[2].find("plink") > -1: @@ -81,9 +114,21 @@ if words3[1].find("tx") > -1 and words3[2].find("bytes") > -1: tx=words3[3] if words3[1].find("TDLS") > -1: - fifo.write('mesh_node_signal{sourcemac="' + mac + '",mac="' + station + '",link="' + linkstatus + '"} ' + signal + "\n") + fifo.write('mesh_node_signal{sourcemac="' + mac + '",mac="' + station + '",link="' + linkstatus + '"' + cjdnsdata + '} ' + signal + "\n") fifo.write('mesh_node_rx{sourcemac="' + mac + '",mac="' + station + '"} ' + rx + "\n") fifo.write('mesh_node_tx{sourcemac="' + mac + '",mac="' + station + '"} ' + tx + "\n") + + if os.path.isfile("/usr/bin/yggdrasilctl"): + args = shlex.split("sudo /usr/bin/yggdrasilctl -json getPeers") + interfaces = subprocess.Popen(args,stdout=subprocess.PIPE) + interfaces.wait() + raw_json = interfaces.stdout.read(); + peers = json.loads(raw_json.decode()) + + for peer,data in peers["peers"].items(): + fifo.write('mesh_node_ygg_peer_rx{peer="'+peer+'",endpoint="'+str(data["endpoint"])+'"}'+" "+str(data["bytes_recvd"])+"\n") + fifo.write('mesh_node_ygg_peer_tx{peer="'+peer+'",endpoint="'+str(data["endpoint"])+'"}'+" "+str(data["bytes_sent"])+"\n") + fifo.close() time.sleep(1) From e581ea9dc2dd695308abcb50a4d6bf8241c4f725 Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Thu, 28 Feb 2019 16:00:12 -0500 Subject: [PATCH 151/162] Fix Documentation Errors (#313) * corrected typo * Grafana bug description * Update MODULES.md * Spelling errors --- docs/MODULES.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/MODULES.md b/docs/MODULES.md index 6c12b5b21..e33121728 100644 --- a/docs/MODULES.md +++ b/docs/MODULES.md @@ -250,7 +250,7 @@ your code should look somewhat like this: } ``` -Next you should restart cjdns with a `sudo systemctl restart cjnds` command. This will reload cjdns +Next you should restart cjdns with a `sudo systemctl restart cjdns` command. This will reload cjdns with the new config file. Run a `status` command on your node, and make sure when it prints out the text, that cjdns is green with the text `[ACTIVE]`. if so, you have successfully connected to the remote peer, if it says `[INACTIVE]`, then there might be a typo in your config file. Make sure its formatted correctly (the @@ -290,3 +290,18 @@ Exit out of nano and save the changes. Restart Yggdrasil with a `sudo killall yg command to terminal and you should see green text where Yggdrasil is printed with the words `[ACTIVE]` present. You are now connected to the remote peer with Yggdrasil. If you see`[INACTIVE]`, then you need to check your code for typos, make sure there are "" around the whole entire string. + + +# Grafana + +[Grafana](https://grafana.com/) is a dashboard used to display Prometheus collected data. Once installed you can visit `http://:3000`. Default login is `admin`/`admin`. You can skip the welcome screen/wizard by clicking on the Grafana logo at the top left corner. + +## Known install bugs + +At times Grafana will not start up properly during install and the dashboards will not install. To install them manually run the following commands from the `prototype-cjdns/pi/scripts/grafana` folder + +``` +BASE_DIR=`pwd` +curl --user admin:admin -X POST -H 'Content-Type: application/json' --data-binary "@$BASE_DIR/datasource.json" http://localhost:3000/api/datasources +curl --user admin:admin -X POST -H 'Content-Type: application/json' --data-binary "@$BASE_DIR/dashboard.json" http://localhost:3000/api/dashboards/db +``` From 6788446e0ad61dd460c589047958c30f86fff30f Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 1 Mar 2019 19:46:55 -0500 Subject: [PATCH 152/162] skip failed mkdir --- scripts/prometheus-node-exporter/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/prometheus-node-exporter/install b/scripts/prometheus-node-exporter/install index f61b620fe..1751422e5 100755 --- a/scripts/prometheus-node-exporter/install +++ b/scripts/prometheus-node-exporter/install @@ -14,7 +14,7 @@ elif uname -m | grep -q aarch64; then ARM_VERSION=64 fi if [[ ! -f "/usr/local/bin/node_exporter" ]]; then - mkdir "$BASE_DIR/tmp" + mkdir "$BASE_DIR/tmp" || true wget "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-arm${ARM_VERSION}.tar.gz" -O "$BASE_DIR/tmp/node_exporter.tar.gz" tar xvfz "$BASE_DIR/tmp/node_exporter.tar.gz" -C "$BASE_DIR/tmp" --strip 1 sudo cp "$BASE_DIR/tmp/node_exporter" /usr/local/bin/node_exporter From 721e1c168964ed165ad308f1d550d721ef6596db Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Fri, 1 Mar 2019 21:12:52 -0500 Subject: [PATCH 153/162] Added exceptions --- .../nodestats-tomesh.py | 232 +++++++++--------- 1 file changed, 119 insertions(+), 113 deletions(-) diff --git a/scripts/prometheus-node-exporter/nodestats-tomesh.py b/scripts/prometheus-node-exporter/nodestats-tomesh.py index 06aedd1e3..d505a9c5d 100644 --- a/scripts/prometheus-node-exporter/nodestats-tomesh.py +++ b/scripts/prometheus-node-exporter/nodestats-tomesh.py @@ -16,119 +16,125 @@ fifo = open(path, "w") fifo.write("tomeshV 1.2\n") - - s="" - if os.path.isfile("/sys/devices/virtual/thermal/thermal_zone0/temp"): - with file("/sys/devices/virtual/thermal/thermal_zone0/temp") as f: - s = f.read() - fifo.write("hw_temp ") - fifo.write(s) - - - #Wireless Link Dump - - # Get cjdns peer information - remotePeers = {} - myaddress="" - if os.path.isfile("/opt/cjdns/tools/cexec"): - command_line = "/opt/cjdns/tools/cexec \"Core_nodeInfo()\"" - args = shlex.split(command_line) - interfaces = subprocess.Popen(args,stdout=subprocess.PIPE) - interfaces.wait() - output = interfaces.stdout.read(); - data = json.loads(output) - tmp=data["myAddr"].split(".") - myaddress=tmp[5] + ".k" - myaddress=myaddress.splitlines()[0] - command_line = "/opt/cjdns/tools/peerStats" - args = shlex.split(command_line) - interface = subprocess.Popen(args,stdout=subprocess.PIPE) - interface.wait() - output = interface.stdout.read() - peers = output.split("\n") - for peer in peers: - words2= peer.split(" ") - if len(words2) > 1: - tmp=words2[1].split(".") - remotePubKey=tmp[5] + ".k" - remotePeers[words2[0]]=remotePubKey - - # Look through wireless interfaces - command_line = "iw dev" - args = shlex.split(command_line) - interfaces = subprocess.Popen(args,stdout=subprocess.PIPE) - interfaces.wait() - output = interfaces.stdout.read(); - ints = output.split("\n") - for int in ints: - if int.find("Interface") > -1: - words = int.split() - currentitn=words[1] - - # Read mac address from system file - with open("/sys/class/net/" + currentitn + "/address") as f: - mac = f.readlines() - mac = [x.strip() for x in mac][0] - - command_line = "iw dev " + currentitn + " info" + try: + s="" + if os.path.isfile("/sys/devices/virtual/thermal/thermal_zone0/temp"): + with file("/sys/devices/virtual/thermal/thermal_zone0/temp") as f: + s = f.read() + fifo.write("hw_temp ") + fifo.write(s) + + + #Wireless Link Dump + + # Get cjdns peer information + remotePeers = {} + myaddress="" + if os.path.isfile("/opt/cjdns/tools/cexec"): + command_line = "/opt/cjdns/tools/cexec \"Core_nodeInfo()\"" args = shlex.split(command_line) - interface = subprocess.Popen(args,stdout=subprocess.PIPE) - interface.wait() - output = interface.stdout.read() - types = output.split("\n") - for type in types: - if type.find("type") > -1: - words2= type.split(" ") - if (words2[1] == "mesh") or (words2[1] == "IBSS"): - meshtype=words2[1] - fifo.write("wlan_mesh{type=\"" + meshtype + "\", iface=\"" + currentitn + "\"} 1\n") - - # Loop through connected stations - command_line = "iw dev " + currentitn + " station dump" - args = shlex.split(command_line) - links = subprocess.Popen(args,stdout=subprocess.PIPE) - links.wait() - output = links.stdout.read() - linksline = output.split("\n") - station="" - signal="" - - for link in linksline: - if link <> "" : - words3 = link.replace("\t"," ").split(" ") - if words3[0].find("Station") > -1: - station=words3[1] - linkstatus="" - rx=-1 - tx=-1 - signal=-100 - cjdnsdata="" - if station in remotePeers: - cjdnsdata=',sourcekey="' + myaddress + '", key="' + remotePeers[station] + '"' - if words3[1].find("signal") > -1: - signal=words3[3] - if words3[1].find("mesh") > -1 and words3[2].find("plink") > -1: - linkstatus=words3[3] - if words3[1].find("rx") > -1 and words3[2].find("bytes") > -1: - rx=words3[3] - if words3[1].find("tx") > -1 and words3[2].find("bytes") > -1: - tx=words3[3] - if words3[1].find("TDLS") > -1: - fifo.write('mesh_node_signal{sourcemac="' + mac + '",mac="' + station + '",link="' + linkstatus + '"' + cjdnsdata + '} ' + signal + "\n") - fifo.write('mesh_node_rx{sourcemac="' + mac + '",mac="' + station + '"} ' + rx + "\n") - fifo.write('mesh_node_tx{sourcemac="' + mac + '",mac="' + station + '"} ' + tx + "\n") - - - if os.path.isfile("/usr/bin/yggdrasilctl"): - args = shlex.split("sudo /usr/bin/yggdrasilctl -json getPeers") - interfaces = subprocess.Popen(args,stdout=subprocess.PIPE) - interfaces.wait() - raw_json = interfaces.stdout.read(); - peers = json.loads(raw_json.decode()) - - for peer,data in peers["peers"].items(): - fifo.write('mesh_node_ygg_peer_rx{peer="'+peer+'",endpoint="'+str(data["endpoint"])+'"}'+" "+str(data["bytes_recvd"])+"\n") - fifo.write('mesh_node_ygg_peer_tx{peer="'+peer+'",endpoint="'+str(data["endpoint"])+'"}'+" "+str(data["bytes_sent"])+"\n") - + interfaces = subprocess.Popen(args,stdout=subprocess.PIPE) + interfaces.wait() + output = interfaces.stdout.read(); + try: + data = json.loads(output) + tmp=data["myAddr"].split(".") + myaddress=tmp[5] + ".k" + myaddress=myaddress.splitlines()[0] + command_line = "/opt/cjdns/tools/peerStats" + args = shlex.split(command_line) + interface = subprocess.Popen(args,stdout=subprocess.PIPE) + interface.wait() + output = interface.stdout.read() + peers = output.split("\n") + for peer in peers: + words2= peer.split(" ") + if len(words2) > 1: + tmp=words2[1].split(".") + remotePubKey=tmp[5] + ".k" + remotePeers[words2[0]]=remotePubKey + except: + pass + # Look through wireless interfaces + command_line = "iw dev" + args = shlex.split(command_line) + interfaces = subprocess.Popen(args,stdout=subprocess.PIPE) + interfaces.wait() + output = interfaces.stdout.read(); + ints = output.split("\n") + for int in ints: + if int.find("Interface") > -1: + words = int.split() + currentitn=words[1] + + # Read mac address from system file + with open("/sys/class/net/" + currentitn + "/address") as f: + mac = f.readlines() + mac = [x.strip() for x in mac][0] + + command_line = "iw dev " + currentitn + " info" + args = shlex.split(command_line) + interface = subprocess.Popen(args,stdout=subprocess.PIPE) + interface.wait() + output = interface.stdout.read() + types = output.split("\n") + for type in types: + if type.find("type") > -1: + words2= type.split(" ") + if (words2[1] == "mesh") or (words2[1] == "IBSS"): + meshtype=words2[1] + fifo.write("wlan_mesh{type=\"" + meshtype + "\", iface=\"" + currentitn + "\"} 1\n") + + # Loop through connected stations + command_line = "iw dev " + currentitn + " station dump" + args = shlex.split(command_line) + links = subprocess.Popen(args,stdout=subprocess.PIPE) + links.wait() + output = links.stdout.read() + linksline = output.split("\n") + station="" + signal="" + + for link in linksline: + if link <> "" : + words3 = link.replace("\t"," ").split(" ") + if words3[0].find("Station") > -1: + station=words3[1] + linkstatus="" + rx=-1 + tx=-1 + signal=-100 + cjdnsdata="" + if station in remotePeers: + cjdnsdata=',sourcekey="' + myaddress + '", key="' + remotePeers[station] + '"' + if words3[1].find("signal") > -1: + signal=words3[3] + if words3[1].find("mesh") > -1 and words3[2].find("plink") > -1: + linkstatus=words3[3] + if words3[1].find("rx") > -1 and words3[2].find("bytes") > -1: + rx=words3[3] + if words3[1].find("tx") > -1 and words3[2].find("bytes") > -1: + tx=words3[3] + if words3[1].find("TDLS") > -1: + fifo.write('mesh_node_signal{sourcemac="' + mac + '",mac="' + station + '",link="' + linkstatus + '"' + cjdnsdata + '} ' + signal + "\n") + fifo.write('mesh_node_rx{sourcemac="' + mac + '",mac="' + station + '"} ' + rx + "\n") + fifo.write('mesh_node_tx{sourcemac="' + mac + '",mac="' + station + '"} ' + tx + "\n") + + + if os.path.isfile("/usr/bin/yggdrasilctl"): + args = shlex.split("sudo /usr/bin/yggdrasilctl -json getPeers") + interfaces = subprocess.Popen(args,stdout=subprocess.PIPE) + interfaces.wait() + raw_json = interfaces.stdout.read(); + try: + peers = json.loads(raw_json.decode()) + + for peer,data in peers["peers"].items(): + fifo.write('mesh_node_ygg_peer_rx{peer="'+peer+'",endpoint="'+str(data["endpoint"])+'"}'+" "+str(data["bytes_recvd"])+"\n") + fifo.write('mesh_node_ygg_peer_tx{peer="'+peer+'",endpoint="'+str(data["endpoint"])+'"}'+" "+str(data["bytes_sent"])+"\n") + except: + pass + except: + fifo.write('mesh_node_error 1\n') fifo.close() time.sleep(1) From af87b0165579d0fd31161a4d00341175ea6129fe Mon Sep 17 00:00:00 2001 From: Benedict Lau Date: Sun, 3 Mar 2019 08:46:13 -0500 Subject: [PATCH 154/162] Name of ESPRESSOBIN Co-Authored-By: darkdrgn2k --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 60cf38106..9e9860c59 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ List of tested hardware: | NanoPi Neo 2 | [Armbian](https://dl.armbian.com/nanopineo2/) | 160k, 95K | 67 Mbps | 1 (+2*) | 10/100/1000 | *USB Headers, Gigabit Eth | | Rock64 | [Armbian](https://dl.armbian.com/rock64/) | 255k, 168K | 94 Mbps | 3 | 10/100/1000 | 1 USB 3.0, Gigabit Eth | | Pine64 | [Armbian](https://dl.armbian.com/pine/nightly/) | 227k, 151k | 78 Mbps | 2 | 10/100/1000 | Gigabit Eth | -| EspressoBin | [Armbian](https://dl.armbian.com/espressobin/) | 186k, 128K | 73 Mbps | 2 | 10/100/1000 | 1 USB 3.0, 3x Gigabit Eth, Sata, mPCIE. Use stable and apt-get upgrade after boot | +| ESPRESSObin | [Armbian](https://dl.armbian.com/espressobin/) | 186k, 128K | 73 Mbps | 2 | 10/100/1000 | 1 USB 3.0, 3x Gigabit Eth, SATA, mPCIe. Use stable and apt-get upgrade after boot | | MK802ii | Debian | 30k, 40k | 25Mbps | | | Android box. Single Core. Onboard wifi does Meshpoint | ## Development From d0cbb9c371d556e104092a5aca4f2b074057ba33 Mon Sep 17 00:00:00 2001 From: Benedict Lau Date: Sun, 3 Mar 2019 08:46:54 -0500 Subject: [PATCH 155/162] MK802ii wording Co-Authored-By: darkdrgn2k --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e9860c59..5b065376a 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ List of tested hardware: | Rock64 | [Armbian](https://dl.armbian.com/rock64/) | 255k, 168K | 94 Mbps | 3 | 10/100/1000 | 1 USB 3.0, Gigabit Eth | | Pine64 | [Armbian](https://dl.armbian.com/pine/nightly/) | 227k, 151k | 78 Mbps | 2 | 10/100/1000 | Gigabit Eth | | ESPRESSObin | [Armbian](https://dl.armbian.com/espressobin/) | 186k, 128K | 73 Mbps | 2 | 10/100/1000 | 1 USB 3.0, 3x Gigabit Eth, SATA, mPCIe. Use stable and apt-get upgrade after boot | -| MK802ii | Debian | 30k, 40k | 25Mbps | | | Android box. Single Core. Onboard wifi does Meshpoint | +| MK802ii | Debian | 30k, 40k | 25Mbps | | | Android box. Single core. Onboard WiFi supports Mesh Point | ## Development You can install from a specific tag or branch, such as `develop`, with: From f4a3e55e347044c380ff6960cdc1f83d837e20b3 Mon Sep 17 00:00:00 2001 From: Benedict Lau Date: Sun, 3 Mar 2019 08:47:14 -0500 Subject: [PATCH 156/162] Capitalization Co-Authored-By: darkdrgn2k --- contrib/batman-adv/batman-adv-mesh.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/batman-adv/batman-adv-mesh.sh b/contrib/batman-adv/batman-adv-mesh.sh index 3b495e685..7a04cc632 100644 --- a/contrib/batman-adv/batman-adv-mesh.sh +++ b/contrib/batman-adv/batman-adv-mesh.sh @@ -3,7 +3,7 @@ # Install batman adv sudo apt-get install -y batctl -# configure batman-adv +# Configure batman-adv sudo modprobe batman-adv sudo batctl if add wlan0 sudo ifconfig bat0 up From c559f1be553b4755487e05a201492ccc5b8b324a Mon Sep 17 00:00:00 2001 From: Benedict Lau Date: Sun, 3 Mar 2019 08:47:38 -0500 Subject: [PATCH 157/162] Grammer in FAQ Co-Authored-By: darkdrgn2k --- docs/FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 78a23b2b2..efda6e6d4 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -105,7 +105,7 @@ saveenv ``` ## Wireless -**Q:** Why do my Meshpoint/AdHoc nodes Release v0.3 or lower no longer mesh with V0.4 or higher? +**Q:** Why do my MeshPoint/AdHoc nodes on v0.3 or lower no longer mesh with v0.4 or higher? **A:** We dropped the band width of MeshPoint and AdHoc to 20MHz from 40MHz. This should provider a bit better responsivness in urban environments. Unfortunatlry the 20MHz and 40MHz bands do not work together. From 617bef235e4bf087f98b4ad457c01f8f41128229 Mon Sep 17 00:00:00 2001 From: Benedict Lau Date: Sun, 3 Mar 2019 08:48:04 -0500 Subject: [PATCH 158/162] Update docs/FAQ.md Co-Authored-By: darkdrgn2k --- docs/FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index efda6e6d4..06145a28d 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -107,7 +107,7 @@ saveenv **Q:** Why do my MeshPoint/AdHoc nodes on v0.3 or lower no longer mesh with v0.4 or higher? -**A:** We dropped the band width of MeshPoint and AdHoc to 20MHz from 40MHz. This should provider a bit better responsivness in urban environments. Unfortunatlry the 20MHz and 40MHz bands do not work together. +**A:** We dropped the band width of MeshPoint and AdHoc to 20MHz from 40MHz in v0.4. This should provide a bit better responsiveness in urban environments. Unfortunately the 20MHz and 40MHz bands do not work together. You can update your v0.3 or lower nodes to use 20MHz by editing the `/usr/bin/mesh-adhoc` or `/usr/bin/mesh-point` file and removing the HT40+ paramater from the iw line near the bottom of the file, then simply reboot. From 40ac3c306cd62692f97c62aee8ea405bc38824ff Mon Sep 17 00:00:00 2001 From: Benedict Lau Date: Sun, 3 Mar 2019 08:51:21 -0500 Subject: [PATCH 159/162] Mesh point support woring Co-Authored-By: darkdrgn2k --- scripts/mesh-point/mesh-point | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mesh-point/mesh-point b/scripts/mesh-point/mesh-point index 33fa96428..32bbafbad 100755 --- a/scripts/mesh-point/mesh-point +++ b/scripts/mesh-point/mesh-point @@ -10,7 +10,7 @@ function isMeshable { elif [ "$(basename $(readlink /sys/class/net/$interface/device/driver))" == 'xradio_wlan' ]; then result='' # Indicate interface is actually not meshable else - result='1' # Indicate interface is meshable + result='1' # Indicate interface supports mesh point fi echo $result From b90be017af5df6373938554c1964fa7420676e54 Mon Sep 17 00:00:00 2001 From: Benedict Lau Date: Sun, 3 Mar 2019 08:53:10 -0500 Subject: [PATCH 160/162] Remove enter after if Co-Authored-By: darkdrgn2k --- scripts/yggdrasil-iptunnel/yggdrasil-setup | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/yggdrasil-iptunnel/yggdrasil-setup b/scripts/yggdrasil-iptunnel/yggdrasil-setup index 00965288b..4c170b308 100644 --- a/scripts/yggdrasil-iptunnel/yggdrasil-setup +++ b/scripts/yggdrasil-iptunnel/yggdrasil-setup @@ -20,7 +20,6 @@ if [ -e /etc/yggdrasil.iptunnel.server ]; then # Configure as yggdrasil iptunnel client if client file is present (this is simply a newline-separated list # of cjdns public keys in /etc/yggdrasil.iptunnel.client, each key indicating an iptunnel exit server) elif [ -e /etc/yggdrasil.iptunnel.client ]; then - # Add each server to yggdrasil iptunnel connect-to's while read -r PUBLIC_KEY ASSIGNED_IP; do if [[ "${PUBLIC_KEY}" =~ ^[0-z]{64} ]]; then From 9e4f1aec91ac283203a3946bc16029d0d0d4417f Mon Sep 17 00:00:00 2001 From: Benedict Lau Date: Sun, 3 Mar 2019 08:56:11 -0500 Subject: [PATCH 161/162] Spacing Co-Authored-By: darkdrgn2k --- scripts/prometheus-node-exporter/nodestats-tomesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/prometheus-node-exporter/nodestats-tomesh.py b/scripts/prometheus-node-exporter/nodestats-tomesh.py index d505a9c5d..75ccc5506 100644 --- a/scripts/prometheus-node-exporter/nodestats-tomesh.py +++ b/scripts/prometheus-node-exporter/nodestats-tomesh.py @@ -25,7 +25,7 @@ fifo.write(s) - #Wireless Link Dump + # Wireless Link Dump # Get cjdns peer information remotePeers = {} From 7d6f186aaad906d9d681c5af9149c3076577998e Mon Sep 17 00:00:00 2001 From: darkdrgn2k Date: Mon, 4 Mar 2019 08:19:00 -0500 Subject: [PATCH 162/162] updated rpi3b+ notes --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b065376a..24ed643f1 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ List of tested hardware: | Hardware | Base OS | [CJDNS Benchmark](https://github.com/phillymesh/cjdns-optimizations) (salsa20/poly1305, switching) | iPerf3 | USB | Ethernet | Notes | | :-------------------------|:----------------|:--------------------------------------------------------------------------------------------------------------|:-------|:----|:---------|:---------| -| Raspberry Pi 3b+ | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 405k, 119k | ~90 Mbps| 2 | 10/100/1000 | Eth only 320mbps. Cjdns speed unstable. Dual band | +| Raspberry Pi 3b+ | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 405k, 119k | ~90 Mbps| 2 | 10/100/1000 | Eth only ~320mbps. Onboard wifi dual band | | Raspberry Pi 3b | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 350k, 100k | 89 Mbps | 2 | 10/100 | | | Raspberry Pi 2 | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 145k, 55k | 39 Mbps | 2 | 10/100 | | | Raspberry Pi 1 A+ | [Raspbian Lite](https://www.raspberrypi.org/downloads/raspbian/) | 35k, - | ~9 Mbps | 1 | None | |