From 5109987e18945b268347a55fd436d6dccbb7bfca Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Fri, 17 Apr 2020 14:07:22 +0200 Subject: [PATCH] all: initial commit Signed-off-by: Elias Naur --- .gitignore | 8 + LICENSE | 27 + Makefile | 31 + PATENTS | 24 + README.md | 53 ++ android/build.gradle | 43 + android/gradle.properties | 1 + android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58694 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + android/gradlew | 183 ++++ android/gradlew.bat | 103 +++ android/src/main/AndroidManifest.xml | 28 + android/src/main/ic_launcher-playstore.png | Bin 0 -> 21900 bytes .../src/main/java/com/tailscale/ipn/App.java | 81 ++ .../java/com/tailscale/ipn/IPNService.java | 102 +++ .../src/main/java/com/tailscale/ipn/Peer.java | 125 +++ .../res/drawable-hdpi/ic_notification.png | Bin 0 -> 641 bytes .../res/drawable-mdpi/ic_notification.png | Bin 0 -> 406 bytes .../res/drawable-xhdpi/ic_notification.png | Bin 0 -> 879 bytes .../res/drawable-xxhdpi/ic_notification.png | Bin 0 -> 1415 bytes .../res/drawable-xxxhdpi/ic_notification.png | Bin 0 -> 1843 bytes .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1566 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 1672 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3261 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1471 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 1383 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2494 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2991 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 3704 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 5388 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3496 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 3544 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 7795 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 5708 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 7317 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 11427 bytes .../res/values/ic_launcher_background.xml | 4 + build.sh | 10 + cmd/tailscale/backend.go | 287 +++++++ cmd/tailscale/callbacks.go | 92 ++ cmd/tailscale/logo.go | 217 +++++ cmd/tailscale/main.go | 526 ++++++++++++ cmd/tailscale/multitun.go | 287 +++++++ cmd/tailscale/pprof.go | 18 + cmd/tailscale/store.go | 121 +++ cmd/tailscale/tailscale.png | Bin 0 -> 24866 bytes cmd/tailscale/ui.go | 794 ++++++++++++++++++ go.mod | 12 + go.sum | 187 +++++ jni/gojni.h | 25 + jni/jni.c | 101 +++ jni/jni.go | 267 ++++++ 54 files changed, 3772 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 PATENTS create mode 100644 README.md create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.jar create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100755 android/gradlew create mode 100644 android/gradlew.bat create mode 100644 android/src/main/AndroidManifest.xml create mode 100644 android/src/main/ic_launcher-playstore.png create mode 100644 android/src/main/java/com/tailscale/ipn/App.java create mode 100644 android/src/main/java/com/tailscale/ipn/IPNService.java create mode 100644 android/src/main/java/com/tailscale/ipn/Peer.java create mode 100644 android/src/main/res/drawable-hdpi/ic_notification.png create mode 100644 android/src/main/res/drawable-mdpi/ic_notification.png create mode 100644 android/src/main/res/drawable-xhdpi/ic_notification.png create mode 100644 android/src/main/res/drawable-xxhdpi/ic_notification.png create mode 100644 android/src/main/res/drawable-xxxhdpi/ic_notification.png create mode 100644 android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 android/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 android/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 android/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 android/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 android/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 android/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 android/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 android/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 android/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 android/src/main/res/values/ic_launcher_background.xml create mode 100755 build.sh create mode 100644 cmd/tailscale/backend.go create mode 100644 cmd/tailscale/callbacks.go create mode 100644 cmd/tailscale/logo.go create mode 100644 cmd/tailscale/main.go create mode 100644 cmd/tailscale/multitun.go create mode 100644 cmd/tailscale/pprof.go create mode 100644 cmd/tailscale/store.go create mode 100644 cmd/tailscale/tailscale.png create mode 100644 cmd/tailscale/ui.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 jni/gojni.h create mode 100644 jni/jni.c create mode 100644 jni/jni.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c67ccb8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build + +# The destination for the Go Android archive. +android/libs diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..eb7c3f6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2020 Tailscale & AUTHORS. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Tailscale Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c8b92fe --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +DEBUG_APK=tailscale-debug.apk +RELEASE_AAB=tailscale-release.aab +APPID=com.tailscale.ipn +AAR=android/libs/ipn.aar +KEYSTORE=tailscale.jks +KEYSTORE_ALIAS=tailscale + +all: $(APK) + +aar: + mkdir -p android/libs + go run gioui.org/cmd/gogio -buildmode archive -target android -appid $(APPID) -o $(AAR) tailscale.com/tailscale-android/cmd/tailscale + +$(DEBUG_APK): aar + (cd android && ./gradlew assembleDebug) + mv android/build/outputs/apk/debug/android-debug.apk $@ + +$(RELEASE_AAB): aar + (cd android && ./gradlew bundleRelease) + mv ./android/build/outputs/bundle/release/android-release.aab $@ + +release: $(RELEASE_AAB) + jarsigner -sigalg SHA256withRSA -digestalg SHA-256 -keystore $(KEYSTORE) $(RELEASE_AAB) $(KEYSTORE_ALIAS) + +install: $(DEBUG_APK) + adb install -r $(DEBUG_APK) + +clean: + rm -rf android/build $(RELEASE_AAB) $(DEBUG_APK) $(AAR) + +.PHONY: all clean install aar release diff --git a/PATENTS b/PATENTS new file mode 100644 index 0000000..560a2b8 --- /dev/null +++ b/PATENTS @@ -0,0 +1,24 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Tailscale Inc. as part of the Tailscale project. + +Tailscale Inc. hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable (except as stated +in this section) patent license to make, have made, use, offer to +sell, sell, import, transfer and otherwise run, modify and propagate +the contents of this implementation of Tailscale, where such license +applies only to those patent claims, both currently owned or +controlled by Tailscale Inc. and acquired in the future, licensable +by Tailscale Inc. that are necessarily infringed by this +implementation of Tailscale. This grant does not include claims that +would be infringed only as a consequence of further modification of +this implementation. If you or your agent or exclusive licensee +institute or order or agree to the institution of patent litigation +against any entity (including a cross-claim or counterclaim in a +lawsuit) alleging that this implementation of Tailscale or any code +incorporated within this implementation of Tailscale constitutes +direct or contributory patent infringement, or inducement of patent +infringement, then any patent rights granted to you under this License +for this implementation of Tailscale shall terminate as of the date +such litigation is filed. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3be4972 --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# Tailscale Android Client + +https://tailscale.com + +Private WireGuard® networks made easy + +## Overview + +This repository contains the open source Tailscale Android client. + +## Using + +Available on [Play Store](https://play.google.com/store/apps/details?id=com.tailscale.ipn). + +## Building + +[Go](https://golang.org), the [Android +SDK](https://developer.android.com/studio/releases/platform-tools), +the [Android NDK](https://developer.android.com/ndk) are required. + +``` +$ make tailscale-debug.apk +$ adb install -r tailscale-debug.apk +``` + +We only guarantee to support the latest Go release and any Go beta or +release candidate builds (currently Go 1.14) in module mode. It might +work in earlier Go versions or in GOPATH mode, but we're making no +effort to keep those working. + +## Bugs + +Please file any issues about this code or the hosted service on +[the tailscale issue tracker](https://github.com/tailscale/tailscale/issues). + +## Contributing + +`under_construction.gif` + +PRs welcome, but we are still working out our contribution process and +tooling. + +We require [Developer Certificate of +Origin](https://en.wikipedia.org/wiki/Developer_Certificate_of_Origin) +`Signed-off-by` lines in commits. + +## About Us + +We are apenwarr, bradfitz, crawshaw, danderson, dfcarney, +from Tailscale Inc. +You can learn more about us from [our website](https://tailscale.com). + +WireGuard is a registered trademark of Jason A. Donenfeld. diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..7191462 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,43 @@ +buildscript { + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.6.0' + } +} + +allprojects { + repositories { + google() + jcenter() + flatDir { + dirs 'libs' + } + } +} + +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + defaultConfig { + minSdkVersion 23 + targetSdkVersion 29 + versionCode 2 + versionName "0.1" + } + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } +} + +dependencies { + //implementation 'com.google.android.gms:play-services-auth:18.0.0' + implementation "androidx.core:core:1.2.0" + implementation "androidx.browser:browser:1.2.0" + implementation "androidx.security:security-crypto:1.0.0-rc01" + implementation ':ipn@aar' +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..5bac8ac --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1 @@ +android.useAndroidX=true diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..490fda8577df6c95960ba7077c43220e5bb2c0d9 GIT binary patch literal 58694 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 literal 0 HcmV?d00001 diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..a4b4429 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 0000000..2fe81a7 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 0000000..9109989 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,103 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7082d8b --- /dev/null +++ b/android/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/android/src/main/ic_launcher-playstore.png b/android/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..00513bca861ba126f18947be89ca1e98e099318b GIT binary patch literal 21900 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 literal 0 HcmV?d00001 diff --git a/android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/src/main/res/mipmap-hdpi/ic_launcher.png b/android/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..40e1553776086b04e8535d6afac979068d208687 GIT binary patch literal 1566 zcmV+(2I2XMP)4UXfF_1caXJ9c7YCyo(Cv79I+jzg2QITQqU{s4l+p&YoxQbBM6 zVu_CfQd{o@q_Q{nt)(fDg{H)w}YbeZZI@*nbJEJqsx1? zQy-`=-2jO(dL?O)3cXH=*o>}wz0#mjkoM;%74$s>213zYI}!6qjQk)2r;V7j7sOmb zI9hIiW493`P@e>Ggm?tug52kJ06Hd!k&0ab3e*Ae`o;J6vvivP^#z2;2X+Q12!MRS zkJ&Uc0MPM(5dP5q012PKS3>~#h0sSw0H9Ah0cgYS01f+u&khA3F&rgQY?NfO6J%;? ziloySG9txWGBy->nk16rB$vxE!Zm(tg%>)Y3p$}2Hoz8B0VIYclAp?xrNt6Czf|6* za_KC|WU{)3O0fi)DHh1exrKc`T;n&~)8mC~=#cA#4X_0^nF1g@Ef^#>QclY+me>G47~bU@c0Z;9EUH??{OP$T^!!yt$vPVkB~n@Rx2k=1CX;8 za{zJxdgK5h>%>M|UyUDJwj>#~%LiT1sg?0e0nkM5SyEZAke`40k=)+CMZWv?8}jjooSFRxtSIy{!jk~OLWx}X!f*QpJ##Z&-IPZ!CJUwp4J|F1^Kd^8TNHkc%(B(iD&pZ+N`uqYT_HQCX15 zcd7)UTn6OY(Ivnr8QX_8mrG~RubpUbzGWC`#Y8w=Q zpve}3tmU>`jc(c_U8AN!;fLxNgljBDwaNp_ZQ2`s?SnLpT1Ktl!*8gew8{j_y!Pqj z#UW}KwL(u`Xrhm$UmO~J^^DpD1s-oLhCa%g%2KbMjUHY=VTbCM2N3#TzuB^f7mOZ% zLDh?;0S_SbQC7&7I{wnh0V=GUcmQF2XXyh}ogBf#qEc-aK)x#1T6kLK2wta$II%5( zy&L(a8?Ld(#M`p4#39aZ90SJ27Iy!zMGC^T-Wv(6W58Ln9s_pPVh%vgw;BckiX4Fv zBz7`_!tdGrgSug_f5R|99-r{4oj=J81S90M+w&R&D4RXe?nk|kQ5yF7#hVz4f{i}t z73$N=;|pw4AN_S-+y0{gFb$mS@1OSig4;kFLo#S_f)DV8f^(btR)mji1Q~26@##FJ z^y#OD-gFOnKX(uNzxH^1U%EZMudGDOW@=;@A`*#@3?#3_uln+zTfwTuaAf7cHQlA za&oF(p055tUnZ-{V4(edL0eBw4vhA4JsyxQkd$Qk=y^aplJmhDb>Io-oiE+{6&`ou z3j&{>?od@qgoPR0;r4?PZ#rvEoBMOC{fG5o2MU(@HcwQohuOmSrAMV*$EHbd4`YPAx8pK(7?>967M_Z0r;1cIm$T|>tbr2lv>eQZ1mRER=T2}yVP)69-dA@ougmd)w9Z69$&rO3&MLf>MS@zN% zl64yWB&7d2@kyrm*s0h>(+v&z^pN@0$3rp?IB*zr{CxD7ed___A1- zAuxFd&vQUa#kLNbWOZNr;V9Q(AsE;ocu?B`;l1t!HR{s0aAvbsk}_=00qd7r=8DQ0 z%+dt?F^RiJ5G$hOlap!(cL0-4=e~R?&iP(#VA6 zID}8GR4`w#sH1&M9D+7kIi;jDw=a_S#(`V|1A{}b^ard+Cqt6U+T-4g_KM{<>@Fm( z4NkEUn^SbEt(=w`z@(!cVHBZ zGj05O#?rLu;)I%z8kF_deAB@eo^UAyKb{F3w*BWv=>!3>xqjVUsYLYdUDf;w#z#UI z3XkL}9o85{Y%Kp25-Qvm0PL__nA7=CIyqHJLsS#+wR7iV=3ZUR6$!I8nF-#bvvzJz zR3XPQ4XcZ%g!bOUek4a>7H|D>wE>ox;tl$cq?4-om0cIb`dDg!kV-ulT3;!)FNtNa zD>02Vri(IEZe_8e$$=b9RLh3sm--*5D;A#%5vZ#MYh#qV$czjf?p*>BAy+I%u@LBTkUzMEICU4}R9@zIhDS)5K z3$*QeX~ru_J%HA`Xfp?-*Hx_@do=YW#Ku`Vz1ZzYApf2lO%-C_Iitr|6ty`eWpY$w zm)&Z>4X0qhCCH5#+y76=>F&3Eq^}lV@7{RdhzoqZu|K=of=S~yN&kpa6e9uc<$5?7 z+FQkU3>v@+;{8s>`9}KICm+bO)VQSuWT06$D61geYiA#~*0P}joBkes+(|`Rbi@eD z?W|iHpqV|@(a#BlKwKPck_f9YqIPCk7*eyY0#>6)ETG|nYgTD*XK122;4z8NB1&%D zsDs1F2aZ7y))tjR^~$|NEh&X7KjzCLcYAVhk~U*U9ocNAsGkVL^M?wrJb7_><~Wuo zQ`hYT1QNB`K-ESU2I&fRk=N8$WZ`WHIL{WY0Oym#3`Dx^-GkkAcia4ur)46QWGCaB z&J2?D=MxSAnS6y#8*!NXNH;ZYrqQ1BKH=#Z0xUfvj}^(ao+^6r#)OpoVS(%=X5c9q zuIE*iMCucL1tClG&%$J)rNs4{V0xE7lTre|lU(}Cgt-j*WcTIT#npHXfo#0j-c)9( zAeni}^r-_NQ2_Lc(E3-RGOzu|Rk!SS%YotFVBlL*?7k>rrDlW1ioFuxhmrGg^Kq?l H4!`m@^q>QA literal 0 HcmV?d00001 diff --git a/android/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..f866669f77001fef9d1c8ec49e64a331346cdab5 GIT binary patch literal 3261 zcmV;u3_|mXP)$Uf9c7Aqt*T!p`9|I)?45olF=C@7KJ|wD|P|>Pts!9;`p+tS@ zkJMKlc&Pe<`jDnAq)pm}G;LE-Ma|Ds)k+O9rBXx!Aqg08KwxgqH*;sXyPlby-5nbn zk90J{XHQ3$E zX0y%7d_Jn{dODrW>LC2aHQcL(=X^P=r(Qf#sh$o+(T8O<_l%5b-B-HH+Yqlk4=m;QX8jl(9Bi_FlhgeU0sE{B^h^rINl;dsH-X6x>#PbVlgYFb zm=`UeX)Skq7KLIv|tK$@4`}e)t!^h_KufRQ|k_$@I^TkhtR` zXE*{io-118L7Q%>s=jkZowp@@S<60B=7iZ?CJ|#=)xSI=np89^ExW@>I2pa0>DeBZ z$#yd}ldrlXsDrw`@gO|Yu&P-mDVbgV3W=+v>2pl85{0AZdf58Ut!LY|4ztmb?QCTG z7ue9IjjXqCz;nm)Jq5O5!{^zKZClx{o!gBw{^Pn=9tCP|6Sa%>fdhDe3;0CL6hGZe zsp?9<%&mb>D1#K*pD!0qp)gpmDp7i9&MgU~g|f8ynr> z$^-XN&P~8}!Vw8LElslekXH0R2)U@*O^X7qr|m{7sIQ&ol+)Cf3|4@L<%LNCA$?A>K+X4%|wPxUQAc{}q0 ze=qfc7r4t~BpTIzQ_OT$HEL@ZIlG zK)?&!)8=qwYKgQuQjMuKnA(#&?Gy|`-7%zk0k&ssgk|%~ZGFhj9o~eDa(4B>7yP~O zK7+&4P-S0KG_UN>yi6sW;tz|q(CB05JBnsTPZS+I;9zRFj{BNRR1N-HTt-7H z9;-AJktFRzB{MVBD<02w%4WixRhps0FThb^sKsc4rwyL~wMWO?gd_ShbO7sQ@;*v(=Ho~tB{>I=mi8!_C%p)#Tu>Nt0S1oK z$>+EWs)zOUuV5=ztv1dXVZ`xDXcz4R2k=yi;srwPo5hpqZ@Foau_#9cPtBK^y5BSY zR9gMLQ_|m9rlFuILUXPUs@0%*PnMY}nTyeAG$G2QWb{fY`mo!`^?=h|jArqaGR9@n zIL-e^ihg9FnOBj_r6lr0^0Rh}kjA2)tYl8qDj=OklGSV0v!338nnC8f3v6)h!z|Zb zsF?@a2M#^Ayf#0SlAkO0L)I3P#Z>4_H3HIT@;A17A3JsOB)js-M{Mf$O?KEu($#03P7l zwR^9D)3bmi^$n865^?K|<&0Wra(dRQgGShX@au=z_}Tv$fXeCm#HZ}|@#Cy-V3n(I zjvjrMUB2{zEsu}rI_|p(3H;Fx+Oy;F9^nJdiYeS;Jfw}2EZRgzZ3IQJSgeaiu!~*= zG_-ju`|tQ!TTm8FUY{^J=)?mW;v^i4a3AHIcz{3JapM7;!0Sao6bD|4L?R^tBafit z$o*XPA|M2D$BrFiw{K0l0t1b|_bwY)F=)#NW>l#@2<7bRgD?13st=sN>l%DoIU-e` zprO8dnt-CwRGu_w(#tSk=wHQNKl3+FoxAesW%lS}Uzx@Oj@a@!l?dhXHjW#7!QTrH z;012CVV-NyWH{V4U?ZSpw^sqJSha@z`(OX`1nm066?W(w-<&>^r_stweTz`OoCo-V zznA*J3*24=6bf~%m?j|dK^ZDA;l;%K(4c&k8kC!94J!H|{Tlh8UQs}cObv=AygKOz z*$2T%he9D$9L20*zD-uV5AzS|C?=(~b0mvMxqv{e6fC{&HBg+5IOwtuanQKOI7kQ- z|3R_{mhaIk2V+0JGpeb|Vk-z<%!Pn|UIRTD`kQu41Li_(;bIWb$3 zN-N*5XD&8a=UfbqcnytK`8wue%c=dr8s=iwWHpvZ{m7VV*i2R%G!IJTugJQms?v~v9YSj`HiAN0g0kWO4dAO7X4TkLmY!x2N5x*4VYWujQ_aq z7DxHAF2+Z%u7vcw5g?i}a9w&{8jePHqf(`bYrQM0h+h!oIYq*_j{9!$R9!2pYSx;d zvi3;i5yQM}{ZHwEceLV?q`vB=MZG?(%_F#Tih#w49OY(WZQklzJefX2eNOPcS3DrW zwn(J&Q70`z*goXL?hZu0UM8!E%V z{vbrW*0i7!p`2ZWUeEp@Ya3oXk-}cHiJIpX0s3u{Cr5wL@ znB5BuwFw%vhq?Atxld75A<=lWEB*t+)P(o5{Me(2xso-(t(bJ9a&~j8I`$~u!L)+n zo*$!+0ZDqO);E+P*-S!`UxtuGQ}bh&D`wkX1cYpXU%OmoZd$RV^eXjD=Y6dCO=_rJ zxT&dWMJlb1i~h)uebPupIOUVXd=AR_u}|8N_?4$`@gLW5-z}fxb*KHkEiTG6@~!*OC*HUEk4Pkf44V|`?0k|Y zvs0pwoZi(aczjpG2pKkSHFCyCtYh^7XZ*)?uP?PA&KYueSEIPiF0D<4!_h<7C&v5a z+eZo(h3J6m?&yep+Y*xKlj?oj2MKkoI$&uA=UR4{*}d&k+z(B{iA18`MIYMR+ru;Q z1&4-!$v6{F!dpMpZPHkM4EMob~RyL$h2r%~I&+dM25PyLB7 zt^?NK3~SEx7%3da+r%lNzRpnVR(tK;04}1$F}r-e^RG0VA{5flv^m$ z`L%dLdJQ9;kPVnB3acK?qPjBwG=;&FYYf^#n>2Jk1q=oj6Vsge*omc0F=M0%1O~$4 zj>pLd{4$wVJ~VvPJz<&iI_rZa<_An{$@)%*VwSrj)Hi$#c%u!Tt{C8L$L508xMcx? zT(tqV(9+T}9Eo-vjU}X)lalg2@-Ik`%c8(4o036XDDRWD{1H6Cn`=ylw;7x--x4y? zC4tsfJk2x_c5L-ihc=NJ9PH{!{C)gR2)}WS z?yW%?l;w4F&LhToHV5YUXS<wZwSZh)I?$>oRgNrfEpr$t#>>el1~?L0L17Y2!Q| v7@<^h>OTtOsaKY2_Jlt66*XwOYv-P?tVEqN9^?sUz!6d9`G@529SFQk^ zPG>iogyk|7;3`f)neISCLxX!$1eh##ve}!-?r0{n;K;kUh5Zj0o4rZ=O+K8})+FKt zt5baeg3U>>Sd@kb`e)S8{OH~xnf0ZTqOc4O9v|#aDRAxW?J@yAe}MLl49YMN(&X}}BLHCo z&*u_@d0M<#oZlbhV*2}fvO>+w8Q47@u9NMSDgqFv@DOiNY<&h73Wm5Cgo>5zjwpcT zM{jZ$7Z;00)e(S2d0xY=KwJigoY*@&pulx^cgd1D5{W1<2q~#EHa&?!4lyq!-`eU| zBxf)fq&WEq;3Vkw@v+_ymoO9VADSM_mDXM)uK<3-fgQ)=kl_FJGbOUwBd0Qh@xc z$B)zMpDS71w-+x^qNh*xu0SY4=jZ0Kn6>%^1Bf#ZprO!V7B)ee7mKJ|! zB{Gr4!SgpHjegibY|MJ$@*QL)h>z z^OrACTcmTnS8{u~&VWr%PpcyUvH$Z=3tX>_9XOc9A?A6+E`0qJwfaKqZ3!#CAAayY z7kBdH>*@$VvYvY5lw!e;&(D#^8<52|VqS{*=jJMnvqY69GLm;SC)9rX^%qJ?b7ixW z*zNJriPuihcNf2*%a^{Vcg~!l&RDmiQXyf_v6x5L!1Lo16Xb06C@R&FBTv(pUwlpr z^FPqsN3%4#{~`H|q1Hg-4}>Wc?huEOd^H>iiP z#>vc1q1xE;^h;8lCEvT$IEgVyp{+)TiI$i*%Oa6c=TRzAZIG}6C)`}_7S@q=Q>rIH zU2NKOI9=)rzzmx^2BIaF?grWe=?M!%wL!w>k{=oF&l!4p#mP?<0Z3R(RlFetEwQvb z^6ERP4H7o9lkhxmA`6GZcYdUl4mD`Zcmhx=QEf6;E(jamySidAbp#;RarKeAASNm4 z)e5>wG-kO1=4NMQrLv22!vPBfL+a%K=2ht~Abc&` ziuzIsrRJKN+GJf_-Eb+5ap(b;V!WR#qMBJPv-?YIwP`LJ`tV*=5eVE Z{{o1<=6XwWjeP(B002ovPDHLkV1f~~#kBwc literal 0 HcmV?d00001 diff --git a/android/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..7b0fc3f47e840939e1d9f9b2fb177fe4c30edf42 GIT binary patch literal 1383 zcmZuxeK^wz9CsIyl1wF|t(PNL*``j!*kN(QW6R5=pEHGtDX*7#IXjcB7t-Y@u-7!MLxn zo0r(Q(4A8NvD>Bkg&Ouw90U+P4H(2WW9~QiU8$cyAm}s5^xp(kvAR!@h(Ly0!SAbV zeIUQEHs@VKdU`q#PB6PJjCgoa_lR-W73ot`Sa+T6YVX29BxkJ^za~pY$xGEQJR0wj=;b$M)={@3OAg=_=K# z9em468H=N}YoABVs1~;I#rxM%YZ6QhPtWwEoE>f5LczmFNHS=azw6XNEgK~AZo)Z< ze($*U1XuZ3H9+#$jRKv1kAZl{OW4-UL#JW?_gTqLGKI4C_7t+o!elb)n!2(WlxErf zEb^Y7P>d_gV|YS#gkI`;P9A4K2oObvGlDu$LS~FOI<>pA=Yri5mIiaD`^k^n>FP}m zDe^5kbe$4ns|^Di#A=i8%s!!KhFqA32SuGF;C*Kex}hDe>fEDC*njTkPJCMtT(>e@ zUXB4yD~a_f3yR)o0&MOw6tbj^s-?;<-EC^IJI?fBdTp(^5sj~pFfw=o2`POf6G>*h zFwx-cItnhU#1hAk51Kc+ulkuy#5O5q8{S0gwPc=D&t``J0C4rgjA;e7Z{{3-k9e~5 zSbcT%1%W`o#J+%b=}ft!lE$@@CZI`<@ZmY{A<hl48@s~9ul!l*F*fqx0e(%4%%H6DU-)vsEPoQoLL{j`JxFgPUB^A~JlT?4 zjY?9QXVHaqX?`v?m`4lX^~u;6YWnTMDq&wi$*JB-^HT=pyaP5Jbak_SniI_y3Q@Fe z@B$DBE1`y>)(;H4+pr%yX7#3pc3b|8Z4It2yC*&|?#h^7hD%j=6I*ZaWj0FL+{tS` zbdA0YgUB4ni>RaAB>57(Xsg`n!l=LbzGjCwJ#EE7q>KeAgGkpk+YHAAmT-?5#7xN@ z8nM?Um*=P2eW9BhxnE~r;i8{WO}q(e~ZnumPj>&QHfE%1R_34okyp_>7&|*4^KEBW~W7A^mlWhf0tSyFwoR6 z7S1o+Un&~2?wyj`s}?toM!x4a0jh~us~|D+-QHx_$bj8m8#JP8zTmbY)ypbIcP9X; z%;doW#+dhO&OFMCXowlwop;m6dI(AAu_Q8|mo<>{3^hTrcHdO>-5snqT>jo)^br7Jox;*%hTBx8}I*5mYezWpGI>w!SPevFGbd_(LKtq Y9k-9t3=YBTHUd-ybH)u_Y41<{7jrMA2mk;8 literal 0 HcmV?d00001 diff --git a/android/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..7c4f14eaed7ef7327bf4ad59b3ee912e349342a0 GIT binary patch literal 2494 zcmV;v2|@OWP)TM;C}~6=3Z*8Is)o@1 zNdLtWkg7G+L}E5tpKr zsY!{r@R{u@$u;s86u93X4*C4SonC+NDMbyAkc^W|kX$xo!uV_iI?%;4|93}>qqlb1 zs|FtMs=?DFR|y=Oi{P2$vw;UnODl`)Y|Q6hF30a&pD*~JqH1Fqpl&I?z|^b+x@pg9 zV_4IQiR5X_TYOl7Nk;0)V8Sv?U}QCT(*QN66A(O`fDJp_^8h~ZZ8A1#8uu#NVLEgN3BKG;8bLF1#4(%U`>sUtg0%;R4pU~QWlP~`ucj-+|39>C!njdbjvHMSl_0NX}Y~VT`U}l>UPOKla;{3JhmD0yrhQK@&SvT z=fU#=$9O;i+Re?q-L|?L);BYsKXq!VR>r!!I&5{@T3hh_R5Bg{lWs+8oavt6d7t0{ zR;P`f5lClyYuYJP$JPjSdp35mP+95}!jW>JZa-}THqOK#d$kK3#=PmMvxlROo^8N+ zk)f`RHl_u`7O0wR`XUZadM!ucb~4j`s`b*4@>v2RDyJ_W3WaT)A>t_9>XVPjv~m z`y5w8dcbBHLGbZA3IWI0H#cQDyk&C_D=)9i3gWeE*OJ5O@ij=#A`xWhCQm_8cV(Ue zmo@{ZdG7N9o+DtvdC&$sp9!9KxTdz2b+omxF3LXf_y(dwg{>|euC9*h8-z^N+7f3K zmDOp%&SR3i{uj92&$TWHN%99}v#Olt!h$0>dY(2SL6%AChGwA~Vgb@sMY;wiN~u?! zPH)t@+^p0|M`Kl$cl)-zgK`5ja?0{Ud`i_%fCA+wGwuF@i-FA}`;KRn_&K@cz)RCP z06NswH?jx6{t$b3-*;F?XE)I!BIb3hj(uh4F1G)>Lu_;ZpzSSerPGQSyKl$+Y-s2J zyLbBz%48MOIv{z~^MpB-N=r&g&|Qs-902&ed%wxv`{%oC>gIJ_KE8T|9Xoc6g~H`o z;J4rRWj6NqUo740pM1nlojl1ZtFtl->)P1EE+k&IbZ_4Hgq=J4JJ!@3pC%5pca|?- zzQS@qk|Yo1|9^`dh_|-0_b1-7j99>~eZ=^u*i2R1xBOi3Vh>6Ou)G4kRW zHu>qbEd3KFPOwO{%GLp|&p+XGI(?P{4q4U|pLR*)z@bAw$TDEcZ(sOLnxUOv-6hoh z(;t7&8rC&ix~*-Ux?^^_@BaO7bUK^t9Z>w2SGnEc6on)yIGqDWj~*3*O1ylY#cEOo z9XK!29l!WCYiaGUbhmE1SEzgGg9)}}aI4UPl}=~Wa)3$*FHvYh7x^KPtI$OV?#Xbgn+WQWNL$e$}KzJ2#5SLf3 zVXwZDu-&D;%>(Jp300fFICV0M8rMGlknP^RC*x8Kvm-~2WI2q@dhD@-dh)P!K-S(V zE-rTP#oS_w?6cFQ(T2wL>}SW1vp3)PvmT_UfBh@AZQFL+Teh;gmJL5StaBc;8KIru z{k1)50i5dG%Gtq#kF!@VB-mfa$5`V0IW~0Qk+f6IN~5xxAk0hoLM~tS`hPmpMTT6C z^cHVvr`%mV?WIF)p&qc{JWm_Z9aCGkP7msu+6HmyVPJDh%F~3oK*w%e$GP<3Uapk* zES3|u%u>SP^y~xXv{HgDvluD-_p@3~c&$4?`;dBq27~(fd^ue#DgHB}a@ssfr zI=*Dd5}$ozpY&)+sY`wovl#vqFmw_%-{_?H0T-%D(d~*Z6BNLtY2{|Hz+ z2O8I{o1*Ux>bRc(rWr?z8E<3UF1P%Q;lvbXl^FLS`(WsVxeZ1ic3B9wHR}0)P)Uq> z>8&?j*J~TQ@&MTe0SnH9HrObD$5>JCf8CzvfMu?4HS_eVIwwbUy5&=b697AjaUUjT z=Fmwb=n=ZQH|ZrYs!G2mo=$^;2v~3)w85q%!ArlyJ46G^qT6}Fv6w`olX%v2!gwuo z>n=3x)(Z}9=K}_Y{M&s?lW#2Gb2!~kP%vFjdz&&Jj--I!G6MEG+4>P|-YIyVPWOO^ z%T}z|K}Fwd=4qIYcx~T2&N$zh;(=pLtW7rVH#mRKe7xjK1$H!w1u+STIGnD>>8`lQ zIbzK(XYq=4Dx*k4eSfi})OCo~Uai|m+PVurLrCUe9IG>@pdeOKQu?UN?H#3F;)?D} zwnKK5(Lv)Gm*gGA8dytTb5?nNK29TPq>!YPq-^QZWxaIGe-DA@k(7kTtB%WF^r zeE`A#@tH^RC7=UcJVVchjWr65H5cSJ6EM8Y0D{1a6ciNHP|+1HDk|!N;Q#mx-x)fk z#xn&A@na9Wi!VP4-X^(go(_Kh@Hs<@jL!<7V{}sU@^ga!0jKn?qSP!IbN~PV07*qo IM6N<$f+MTY1ONa4 literal 0 HcmV?d00001 diff --git a/android/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7fea58ce0d20be0f622e855326e0a33e00c5072a GIT binary patch literal 2991 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 literal 0 HcmV?d00001 diff --git a/android/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..7605dee50940d189aaa4d8e3016f5d1f85bffc4a GIT binary patch literal 3704 zcmb`Kdo)!2{>S&Y=b@Aa5mKk7``HBro2#eeXW{C?r4S3DHN1yMiRzPb^7ch~*BQXP@&}_iq zqN=CEBr?JL;IOG&{qvU?&s8>uErz}!VZUcbj$-i4_fvtS29q+ACB!_54M~674@uY# zLcht{)hFB&bktvu zCcOh|*VqearGPZmP&};E*0okMWB*G3nIf3S#opr*jCL7n zNviKy^kFVMsV-_GFuks9w9yYqsrm|ifmuzYtlTMGk)oQ&QKy+n%mItgr{(fM$K9)3 z+nO30m@d^nHa)K!*;4(Eeb%8u%}RWOUXtnv(y<{RDYyFn(!WgG<(HjRyzND&lzJ0C z{%}VVeswbPUPNCE*fEY4o~gfp!1}E=Vq+qcmO`IwV zgwa|Db(ANWtF8{4hv5^GiUhhAA)vZj%0N!s;D1^0FEe$on7hZ=*K6N~#_y@0n1nZ7 z9p%>Hx_s$TpOE(Jed?wQaf4h|Zas=TWH!c`H+^2?KDf zNZ2NTnH<~MW&=OsmzvKjhKZ>VHo|t1;MjI^{PK>e&5gH@mPsVPdi@AwgKy*5ag>;b z%HDgBxeSV5_Y5n8(iE%QO^VHzGRcQ5eH*PB;k_Y}gk+K&~%cnYK|CT^vR{-id&LygE?x`IbcWcg7<+hR{}rZnJnx$Tf&N!U+2 zpxG)^fk5Dzb*Wv$;^t?w#sSH?C|#8NV9fhc@#^iKis^RazxeHDqU2dI3d$og2@C1c)NX*?BvR8iJ_5;vt8S2~Q3<(mf5|W|WK=f|D7CNL`{T(qs zGu~4fvKJ-BRqci{H5pN|50!>uBk`ezn4tMNb-~b6mV0B8#Sl;QNgE$I53f?;rfdP^ zj`S8lsO2>?U5DRQaOS{%T0df|@ZeGMDcNUS>*Q;P_ zC(}{wxE-c>*##tiUSHpJ*Mkbsd|aDe<@8Yyb#MudmvP@gJ9N(6lir9i4>I>$ZNK!f z-u$VC9OLy-Vum`(7w5DS+%-00mtgebS^XPe%?ov}_(NROOPeHX7iHfY4tqs2AD#|( zUcQz5ge-bLVW*rW`m*wE7}g~G@)FG`qP3$6PVR}d^rn*8U5MJ?o>4=-_LAXf68mh* z64;+x-BgE-ZdoEXL>Islh~>_JajbucN`P=z1XC@ zF|Dt;9XR6a-`WJzP~@knFl~N3NIYMgD72O^xZB+X-1$>Lq|h?|6bfLADH6X+i4^*O z_Bqu`m)wlsn?{)l(d8r|^`x*x^Y@q@rzB$Oq>Wy{_eysdVu0^|Nkm{B8GX;Voy- zujcrvZT|L;q*mj2bz+{9; z$ZC9KSNb5tA(g_DLxZI}-Ky_R&rB~9p)Ska16qUqmHR^q+=hbp&n#&Tt3YkWSuj>B z0#n|8ohySpC}E$r@c5g2$)T>8_o`y&Ke*L@SFNFI$fQyu$|LSY@G;nR_-A&KZj-6tK3GA&wGa;i4!Iis5F`}E9Lp^ z!7n?;PDIK+?6F*dZts9iM*~|8HNas9nqeLwAG0Af(=-YDKg8zGr%uO1T=_k-$z30M zuCqJ1yA0@f)4hf$ly1kfFVaNYnBI{_%&kvf1SPlnZ|!=l|J_yDpT!D{*Jypx03)j` zMa)hZ!ZI7{B(2BQdv;M3P&q=~vjsDE9Wl~Bi<<9# zto2TE>NZQaSw85R*604JVoSI9VqM#UAx_BU2#go5sn<1-5wzON+WKd#R4Sc4lG)?q z*a%q0*XK)Zy{1T>8euYcw|nM`1LjUe-7b`Ztrx$NclmNoo!K(ZWI`JQ3YxeR0 literal 0 HcmV?d00001 diff --git a/android/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..361e863386d5f97bb402fa6ff809047c94d8e908 GIT binary patch literal 5388 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 JtFO5{`48+Oovr`? literal 0 HcmV?d00001 diff --git a/android/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..377ed1b1325a598a9b18bd9f0e34da8e3b3b589c GIT binary patch literal 3544 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 FV1izWEBpWe literal 0 HcmV?d00001 diff --git a/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..5b314276f1e3f9e3705ef45101f6aa6a936c527c GIT binary patch literal 5708 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 literal 0 HcmV?d00001 diff --git a/android/src/main/res/values/ic_launcher_background.xml b/android/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..16b8946 --- /dev/null +++ b/android/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #1F2125 + \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..26382cd --- /dev/null +++ b/build.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +set -e + +mkdir -p android/libs +go run gioui.org/cmd/gogio -buildmode archive -target android -appid com.tailscale.ipn -o android/libs/ipn.aar tailscale.com/tailscale-android/cmd/tailscale +(cd android && ./gradlew assembleDebug) diff --git a/cmd/tailscale/backend.go b/cmd/tailscale/backend.go new file mode 100644 index 0000000..a5f52dd --- /dev/null +++ b/cmd/tailscale/backend.go @@ -0,0 +1,287 @@ +// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "errors" + "fmt" + "log" + "path/filepath" + "reflect" + "time" + + "github.com/tailscale/wireguard-go/device" + "github.com/tailscale/wireguard-go/tun" + "golang.org/x/sys/unix" + "tailscale.com/ipn" + "tailscale.com/logpolicy" + "tailscale.com/logtail" + "tailscale.com/logtail/filch" + "tailscale.com/tailscale-android/jni" + "tailscale.com/types/logger" + "tailscale.com/wgengine" + "tailscale.com/wgengine/router" + "tailscale.com/wgengine/tstun" +) + +type backend struct { + engine wgengine.Engine + backend *ipn.LocalBackend + logger logtail.Logger + devices *multiTUN + settings func(*router.Config) error + lastCfg *router.Config + + jvm jni.JVM +} + +type androidRouter struct { + backend *backend +} + +const defaultMTU = 1280 // minimalMTU from wgengine/userspace.go + +// errVPNNotPrepared is used when VPNService.Builder.establish returns +// null, either because the VPNService is not yet prepared or because +// VPN status was revoked. +var errVPNNotPrepared = errors.New("VPN service not prepared or was revoked") + +func newBackend(dataDir string, jvm jni.JVM, store *stateStore, settings func(*router.Config) error) (*backend, error) { + logf := wgengine.RusagePrefixLog(log.Printf) + pol := logpolicy.New("tailnode.log.tailscale.io") + b := &backend{ + jvm: jvm, + devices: newTUNDevices(), + settings: settings, + } + genRouter := func(logf logger.Logf, wgdev *device.Device, tundev tun.Device) (router.Router, error) { + return &androidRouter{backend: b}, nil + } + var logID logtail.PrivateID + logID.UnmarshalText([]byte("dead0000dead0000dead0000dead0000dead0000dead0000dead0000dead0000")) + const logPrefKey = "privatelogid" + storedLogID, err := store.read(logPrefKey) + // In all failure cases we ignore any errors and continue with the dead value above. + if err != nil || storedLogID == nil { + // Read failed or there was no previous log id. + newLogID, err := logtail.NewPrivateID() + if err == nil { + logID = newLogID + enc, err := newLogID.MarshalText() + if err == nil { + store.write(logPrefKey, enc) + } + } + } else { + logID.UnmarshalText([]byte(storedLogID)) + } + b.SetupLogs(dataDir, logID) + engine, err := wgengine.NewUserspaceEngineAdvanced(logf, tstun.WrapTUN(logf, b.devices), genRouter, 0) + if err != nil { + return nil, fmt.Errorf("runBackend: NewUserspaceEngineAdvanced: %v", err) + } + local, err := ipn.NewLocalBackend(logf, pol.PublicID.String(), store, engine) + if err != nil { + engine.Close() + return nil, fmt.Errorf("runBackend: NewLocalBackend: %v", err) + } + b.engine = engine + b.backend = local + return b, nil +} + +func (b *backend) Start(notify func(n ipn.Notify)) error { + return b.backend.Start(ipn.Options{ + StateKey: "ipn-android", + Notify: notify, + }) +} + +func (b *backend) LinkChange() { + if b.engine != nil { + b.engine.LinkChange(false) + } +} + +func (r *androidRouter) Up() error { + return nil +} + +func (r *androidRouter) Set(cfg *router.Config) error { + return r.backend.setCfg(cfg) +} + +func (r *androidRouter) Close() error { + return nil +} + +func (b *backend) setCfg(cfg *router.Config) error { + return b.settings(cfg) +} + +func (b *backend) updateTUN(service jni.Object, cfg *router.Config) error { + if reflect.DeepEqual(cfg, b.lastCfg) { + return nil + } + err := jni.Do(b.jvm, func(env jni.Env) error { + cls := jni.GetObjectClass(env, service) + m := jni.GetMethodID(env, cls, "newBuilder", "()Landroid/net/VpnService$Builder;") + builder, err := jni.CallObjectMethod(env, service, m) + if err != nil { + return fmt.Errorf("IPNService.newBuilder: %v", err) + } + bcls := jni.GetObjectClass(env, builder) + + // builder.setMtu. + setMtu := jni.GetMethodID(env, bcls, "setMtu", "(I)Landroid/net/VpnService$Builder;") + const mtu = defaultMTU + if _, err := jni.CallObjectMethod(env, builder, setMtu, jni.Value(mtu)); err != nil { + return fmt.Errorf("VpnService.Builder.setMtu: %v", err) + } + + // builder.addDnsServer + addDnsServer := jni.GetMethodID(env, bcls, "addDnsServer", "(Ljava/lang/String;)Landroid/net/VpnService$Builder;") + for _, dns := range cfg.DNS { + _, err = jni.CallObjectMethod(env, + builder, + addDnsServer, + jni.Value(jni.JavaString(env, dns.String())), + ) + if err != nil { + return fmt.Errorf("VpnService.Builder.addDnsServer: %v", err) + } + } + + // builder.addSearchDomain. + addSearchDomain := jni.GetMethodID(env, bcls, "addSearchDomain", "(Ljava/lang/String;)Landroid/net/VpnService$Builder;") + for _, dom := range cfg.DNSDomains { + _, err = jni.CallObjectMethod(env, + builder, + addSearchDomain, + jni.Value(jni.JavaString(env, dom)), + ) + if err != nil { + return fmt.Errorf("VpnService.Builder.addSearchDomain: %v", err) + } + } + + // builder.addRoute. + addRoute := jni.GetMethodID(env, bcls, "addRoute", "(Ljava/lang/String;I)Landroid/net/VpnService$Builder;") + for _, route := range cfg.Routes { + _, err = jni.CallObjectMethod(env, + builder, + addRoute, + jni.Value(jni.JavaString(env, route.IP.String())), + jni.Value(route.Bits), + ) + if err != nil { + return fmt.Errorf("VpnService.Builder.addRoute: %v", err) + } + } + + // builder.addAddress. + addAddress := jni.GetMethodID(env, bcls, "addAddress", "(Ljava/lang/String;I)Landroid/net/VpnService$Builder;") + for _, addr := range cfg.LocalAddrs { + _, err = jni.CallObjectMethod(env, + builder, + addAddress, + jni.Value(jni.JavaString(env, addr.IP.String())), + jni.Value(addr.Bits), + ) + if err != nil { + return fmt.Errorf("VpnService.Builder.addAddress: %v", err) + } + } + + // builder.establish. + establish := jni.GetMethodID(env, bcls, "establish", "()Landroid/os/ParcelFileDescriptor;") + parcelFD, err := jni.CallObjectMethod(env, builder, establish) + if err != nil { + return fmt.Errorf("VpnService.Builder.establish: %v", err) + } + if parcelFD == 0 { + return errVPNNotPrepared + } + + // detachFd. + parcelCls := jni.GetObjectClass(env, parcelFD) + detachFd := jni.GetMethodID(env, parcelCls, "detachFd", "()I") + tunFD, err := jni.CallIntMethod(env, parcelFD, detachFd) + if err != nil { + return fmt.Errorf("detachFd: %v", err) + } + + // Create TUN device. + tunDev, _, err := tun.CreateUnmonitoredTUNFromFD(int(tunFD)) + if err != nil { + unix.Close(int(tunFD)) + return err + } + + b.devices.add(tunDev) + + return nil + }) + if err != nil { + b.lastCfg = cfg + b.CloseTUNs() + return err + } + b.lastCfg = cfg + return nil +} + +// CloseVPN closes any active TUN devices. +func (b *backend) CloseTUNs() { + b.lastCfg = nil + b.devices.Shutdown() +} + +// SetupLogs sets up remote logging. +func (b *backend) SetupLogs(logDir string, logID logtail.PrivateID) { + logcfg := logtail.Config{ + Collection: "tailnode.log.tailscale.io", + PrivateID: logID, + } + logcfg.LowMemory = true + drainCh := make(chan struct{}) + logcfg.DrainLogs = drainCh + go func() { + // Upload logs infrequently. Interval chosen arbitrarily. + // The objective is to reduce phone power use. + t := time.NewTicker(2 * time.Minute) + for range t.C { + select { + case drainCh <- struct{}{}: + default: + } + } + }() + + filchOpts := filch.Options{ + ReplaceStderr: true, + } + + var filchErr error + if logDir != "" { + logPath := filepath.Join(logDir, "ipn.log.") + logcfg.Buffer, filchErr = filch.New(logPath, filchOpts) + } + + logf := wgengine.RusagePrefixLog(log.Printf) + b.logger = logtail.Log(logcfg, logf) + + log.SetFlags(0) + log.SetOutput(b.logger) + + log.Printf("goSetupLogs: success") + + if logDir == "" { + log.Printf("SetupLogs: no logDir, storing logs in memory") + } + if filchErr != nil { + log.Printf("SetupLogs: filch setup failed: %v", filchErr) + } +} diff --git a/cmd/tailscale/callbacks.go b/cmd/tailscale/callbacks.go new file mode 100644 index 0000000..e5cfabe --- /dev/null +++ b/cmd/tailscale/callbacks.go @@ -0,0 +1,92 @@ +// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +// JNI implementations of Java native callback methods. + +import ( + "sync/atomic" + "unsafe" + + "tailscale.com/tailscale-android/jni" +) + +// #include +import "C" + +var ( + vpnPrepared = make(chan struct{}, 1) + + // onConnect receives global IPNService references when + // a VPN connection is requested. + onConnect = make(chan jni.Object) + // onDisconnect receives global IPNService references when + // disconnecting. + onDisconnect = make(chan jni.Object) + // onConnectivityChange is notified every time the network + // conditions change. + onConnectivityChange = make(chan struct{}, 1) + + // onPeerCreated receives global instances of Java Peer + // instances being created. + onPeerCreated = make(chan jni.Object) + // onPeerDestroyed receives new global instances of Java Peer + // instances about to be destroyed + onPeerDestroyed = make(chan jni.Object) +) + +var ( + connected atomic.Value +) + +func init() { + connected.Store(true) +} + +//export Java_com_tailscale_ipn_Peer_fragmentCreated +func Java_com_tailscale_ipn_Peer_fragmentCreated(env *C.JNIEnv, this C.jobject) { + jenv := jni.EnvFor(uintptr(unsafe.Pointer(env))) + onPeerCreated <- jni.NewGlobalRef(jenv, jni.Object(this)) +} + +//export Java_com_tailscale_ipn_Peer_fragmentDestroyed +func Java_com_tailscale_ipn_Peer_fragmentDestroyed(env *C.JNIEnv, this C.jobject) { + jenv := jni.EnvFor(uintptr(unsafe.Pointer(env))) + onPeerDestroyed <- jni.NewGlobalRef(jenv, jni.Object(this)) +} + +//export Java_com_tailscale_ipn_Peer_onVPNPrepared +func Java_com_tailscale_ipn_Peer_onVPNPrepared(env *C.JNIEnv, this C.jobject) { + select { + case vpnPrepared <- struct{}{}: + default: + } +} + +//export Java_com_tailscale_ipn_Peer_onSignin +func Java_com_tailscale_ipn_Peer_onSignin(env *C.JNIEnv, this C.jobject) { + // TODO(eliasnaur) +} + +//export Java_com_tailscale_ipn_IPNService_connect +func Java_com_tailscale_ipn_IPNService_connect(env *C.JNIEnv, this C.jobject) { + jenv := jni.EnvFor(uintptr(unsafe.Pointer(env))) + onConnect <- jni.NewGlobalRef(jenv, jni.Object(this)) +} + +//export Java_com_tailscale_ipn_IPNService_disconnect +func Java_com_tailscale_ipn_IPNService_disconnect(env *C.JNIEnv, this C.jobject) { + jenv := jni.EnvFor(uintptr(unsafe.Pointer(env))) + onDisconnect <- jni.NewGlobalRef(jenv, jni.Object(this)) +} + +//export Java_com_tailscale_ipn_App_onConnectivityChanged +func Java_com_tailscale_ipn_App_onConnectivityChanged(env *C.JNIEnv, cls C.jclass, newConnected C.jboolean) { + connected.Store(newConnected == C.JNI_TRUE) + select { + case onConnectivityChange <- struct{}{}: + default: + } +} diff --git a/cmd/tailscale/logo.go b/cmd/tailscale/logo.go new file mode 100644 index 0000000..af01750 --- /dev/null +++ b/cmd/tailscale/logo.go @@ -0,0 +1,217 @@ +// Code generated for package main by go-bindata DO NOT EDIT. (@generated) +// sources: +// tailscale.png +package main + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// Mode return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _tailscalePng = []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x04\x00\x00\x00\x00\xca\b\x06\x00\x00\x00;!2B\x00\x00\x00\tpHYs\x00\x00\x9e\x1b\x00\x00\x9e\x1b\x01b8\xb7\xfd\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00 \x00IDATx\x9c\xec\xddw\x9c$e\x9d?\xf0\u03f7:UU\xcf\xec.\xbb \"(9\x83\bJ\x92\f\x82\xa0\xe8OP\f\x88\x8az\x9e'\x86\xd3\u00c0\xf1\xe4\x0e\xef\xf4\x8c\u725e\t\u00ddpg\x0e\x04A\x11AP\x82\x9c\x04%\a1\x00\xb2\xbb3]\xa1\xab\xba\xeb\xf3\xfbc\x06X\x96\x9deB\xf7<\xd5\u075f\xf7\xeb5/v{\xba\xab>\xc3\xf6t=\u03f7\x9e`\x10\x11YK\x9aF\xc7z\xc4\xf7\\\xe7\x98\x19/\xa9\ac\a\xb9N!\"\"\"\"2H<\xd7\x01DDDDDDD\xa4\xffT\x00\x10\x11\x11\x11\x11\x11\x11\x19\x01U\xd7\x01DD\u028ed\xc3u\x86\x19\xe4fV\xb8\x0e!\"\"\xe2\x12\xc9\n\xca\u066f\xa1\x99e\xaeC\x88\xac\xa9\x8c\xbf(\"\"\xa5\xc1(\xda4O\xe3?\xba\u03b1.\xf4p\x1c\x80\xef\xba\xce!\"\"\xe2R\xdeN>\f\xf2\xef]\xe7X\x87\xdb\x00l\xed:\x84\u021a4\x05@DDDDDDd\x04\xf4}\x04\x00\xc9J\xa7\x1d\x1d\xdc\xef\xf3\xccG\xb5k7X\xb3\xf9'\xd79DDDDDDD\xfam1\xa6\x004H\xbbp\x11\xce3g\xb9\xc7W\x008\xdbu\x0e\x11\x11\x11\x11\x11\x11\x91~\xd3\x14\x00\x11\x11\x11\x11\x11\x11\x91\x11\xa0\x02\x80\x88\x88\x88\x88\x88\x88\xc8\bP\x01@DDDDDDd\x04\xa8\x00 \"\"\"\"\"\"2\x02T\x00\x10\x11\x11\x11\x11\x11\x11\x19\x01*\x00\x88\x88\x88\x88\x88\x88\x88\x8c\x00\x15\x00DDDDDDDF\x80\n\x00\"\"\"\"\"\"\"#@\x05\x00\x11\x11\x11\x11\x11\x11\x91\x11\xa0\x02\x80\x88\x88\x88\x88\x88\x88\xc8\bP\x01@DDDDDDd\x04\xa8\x00 \"\"\"\"\"\"2\x02T\x00\x10\x11\x11\x11\x11\x11\x11\x19\x01*\x00\x88\x88\x88\x88\x88\x88\x88\x8c\x00\x15\x00DDDDDDDF\x80\n\x00\"\"\"\"\"\"\"#@\x05\x00\x11\x11\x11\x11\x11\x11\x91\x11\xa0\x02\x80\x88\x88\x88\x88\x88\x88\xc8\bP\x01@DDDDDDd\x04\xa8\x00 \"\"\"\"\"\"2\x02T\x00\x10\x11\x11\x11\x11\x11\x11\x19\x01*\x00\x88\x88\x88\x88\x88\x88\x88\x8c\x00\x15\x00DDDDDDDF\x80\n\x00\"\"\"\"\"\"\"#@\x05\x00\x11\x11\x11\x11\x11\x11\x91\x11\xa0\x02\x80\x88\x88\x88\x88\x88\x88\xc8\bP\x01@DDDDDDd\x04T]\a\x10\x91\xf21+n%*\xff\xe2:\xc7L\f\xb8\xcdu\x06\x11\x11\x11\x11\x91A\xa3\x02\x80\x88;~\x0f\xf2&\x83]_\x14\xb8\xb1\xf0\xbck\x83 \xb8\xab_?\xaf\xf4\x17I?O\x92\xa9\xf7\x92qG\xd2v6`\x87<\x8d7\xab\x00\xdeC\xef\x8cG\xbd\xaf\x1e\xfdN\x9a\xf1zd\xf6\xc85i\xea\xba\u01a9\xc7`\xf0\xd8E\x9e\u019d,\x89\xee$p\xab\x11\xb7\xc2\xc3o\xd1\u016fkax\xbd\n\x03\xe5C\xb2\x9ee\xd1\xf6(\xb03\xe0\xed\xe2\x91;\u04b0\x15\x80-rL\u0760\x98~\u00c0f\xb0u\xb6_8\xbb\xf6\xcbC\x9fA\x00\n\x02\xe8\x1ar\x0f@\x1a\xe7Y\x12\xddl\x86\x1b\v\xe2&\xd0n@\xa5\xb8\xa9^o\xfe\xde\u0332\xde\xfd\xb4\"\x8b\x87\xfc\xeb\x92NZ\u007f\x1a\xad\xb2+\xc8]\x01\xec\x06`\xdb\x1cS\x853\x9b\xfe\xbd\xb1\xa9\xbf\xe0\xe1\xbe\xc2\xc3\ax\xcc\x11\xf1\xf0S\u05fe\xa6O\x97\xfes\xaf\x82,\x89\"\x18n\x06\xed\x06cq\xbdyv}V\xd8o\xc20\xbc\xb7??\xa9{\xc6U\xab6\xe8\xe7\t\xe2Z-\xa8y(\xe7\xff@\xc3\xebki\xfeM\xd71\x00\x00K\x97N\fk\xa7\x93\xa4\x97e\xad\x1d\xad\xf0\xf6\x01\xb0/`\xcf\x04\xb8-\xca;\x05%\x02p\xb9\x01?\a\xbcK\xaa\xbe\xff+3k\xbb\x0e\xb5\xd8H\x06\x98\x9c\f\x1f\xff\x99\x8b\xac(\n[\xb6l\xe5b\x9d\x8eQ\xb4i\xee\u13cbu\xbe\xb9\xa0\x87\xe3\x1a\x8d\xe6w]\xe7X\f\x9c\x98\xd80\xabV\x0f2\xe3!\x00\x0e\x02\xb0-\xa6\xaa\xfe\xa5A\xe0O\x9e\xe1\n\x14\xbc\x02\xf0.\xad\x06\xc1\xaf\x86\xf5s}\u0431\xd5\xda8\xf3\xbc\x83\r\xc53a\xf6L\x00{\x00\xa8\xbb\u03b5\x96\x14\xc0\xb5 \u007fMx\x97\u0503\xf4\"\xb3\xe5\xab]\x87\x1a5i\x9an\u5c73/h\u03c4\x87}A\xec\x04\xa0\xe6:\xd7\f2\x00\xbf&p\x89g\xfcy\xb5\u047c\xcc\xccZ\xaeC-\x86,\x8d?\x02\xf2\xef]\xe7X\x87\xdb\xeaAsk\xd7!\u0288\x93\x93O\xc8*\x95C\r\xdc\x17\xc0\x010\xec\x8cr]\xd7\xef\x06x9\xcc\xfb%:\xc5\xcfk\xcd\xe6uf6C\xe9n\xb0X\x96DC\xf1\x83\f\xbc\x02{\u055b\u036b\\\xc7\xe8\x95$I\xb6\xacXq\xa4\x01\xcf&q0\x80\xa5\xae3-@\x02\u0615\xc6\u2f2eW=\xd7\xf7\xfd\xdb]\aZ\fy\x12\xbd\x9b\xc0\x87\\\xe7X\x87\a\xebAs\xc5b\x9dL\x05\x007HV:\xed\xe8`\xc2{6\xc0CA\xec\x8a\xf2\x16\r\u05cdXe\x1e.\"pA\xa7\xb0\x1f\x85a\xf8\a\u05d1F\x15\xc9J'm\x1dP\xa0r\xa4\x19\x8f\x04\xb1;\x1es\v\xbf\xf4:\x00\xae4\xe0|\x168\xaf\xdel\xfe\xdau\xa0a\xc4\xc9\xc9'dU;\u00a6>{\x0e\x03\xb0\xb1\xebL\v\xd0\x01p5\x81\x9fX\x85\xe7\xd6\xebc\u05f9\x0e\xd4/*\x00\f\x86,\x8a\xf60\x0f\xcf!p\f\x80\xbd0@\xd7u\x02\u007f2\xe0<\xd2~\\\x0f\x92\xf3\xcdVL\xb8\xce4_*\x00\x94\xc5\x10\x14\x00\xb28\xde\x1b\x1eN\x00\xf1\x1c\x80\u06fb\xce\xd3GW\x19yN\xc7*\xe7\x06Ap\xa7\xeb0\xfd\xa2\x02\xc0\x14\x15\x00\x16W\x16E{\xc2x\x12\u034e7`S\xd7yz\xecF\x02\xe7\xd2*_\xf5}\xff6\xd7a\x86\x1dI\xaf\x93\xa6\xfb\x92\xdd\xe3iv\x82\x01\x9b\xb8\xce\xd4cw\xd3\ucfc8\u0397|\u007f\xc9\xef]\x87\x19d\xed\xf6\xe4\x0e^\xe1\x9d@\u00f1 \xf6\xc0\x00uJ\xe6\xc6~O\xf0\x1cx<\xb7\xd1\x18\xfb\xad\xeb4\xbd\xa4\x02@y%I\xb2E\x95\xdd\x17\u04fcW\x02\xdc\xceu\x9e\x1ei\x93\xb8\u040c\xe7\xd6\xfc\xe6\xb7\x06m\xa4\x8d\n\x00e1\xa0\x05\x80\xac\xd5\u069dU\xef\xc5F\x9e\x00\xe0)\xae\xf3,2\x02\xf8%i\x9f\xa8\a\xc1\xb7\u032c\xe3:P/\xa9\x000E\x05\x80\xfe\x8b\xe3x\xf3\x8a\xf1\xf5\x06\xbc\x04\xc0\x16\xae\xf3,\x02\x02v1\x89\xcf\u05c3\xe0\u06da\xb3\xdb[i\x9anm(N\x01\xf9\x8a!\xec\xf4\xcf\xe4*\x00\x9f\xab\xf9\xe1\xd7\xcc,q\x1df\x10\xa4i\xbaU\x85\xdd\x17\x13x\x11\x80]\\\xe7q\xe0\x06\x18>]k\x84g\x9bY\xec:\xccB\xa9\x00P.$\x1bY\x1a\x1do\xb0\xbf\x05\xb0\x8f\xeb<}\xd6\x02\xf0\r\x148\xab\xdel^\xe3:\xccl\xa8\x00P\x16\x03T\x00 \xe9gIr\xac\x19\xdf\x04`?\xd7y\u0280\xc0\x9f\x00|\xae\x9eu>iK\x97>\xe8:O/\xa8\x000E\x05\x80\xfe\u0262hOx\xf6V\x80\u01e3\xbcsj\xfb\xed~\x9a}\xb9[\xe0Sa\x18\xde\xe3:\u0320\"\xe9eIr\x9c\x19\xfe\x16\xe0!\x18\xbc\xe1\xfd\xbd\xf2\x00\x81\xb3:\x05>\xd3l6K\xf9\xb9\xe5\x12\xc9J\xbb\x1d\x1f\xed\x11\xa7\x028\x14\xa3\xfb>Y\xd3j\x90_\xe9\xc0\xfb\xc8 \u007f\x06\xa9\x00P\x0el\xb56\xc9*v\xaa\x01\xa7\x00\xd8\xc8u\x1e\a~\x05\xf0\xd35\xbf\xf9\xdfe^\xc4uH\x878I?\xa4i\xbaM\x96D\x9f\xc9\xd3\xf8/f<\a\xea\xfc?\u0300M\rx_^\xaf\xdd\xd9N\xe3\u007f\xe5\u0295\xcb\\g\x12)\xabN\x1a\x1d\x9d%\xad\x9f\xc1\xc3U\x00_\x82\xd1\xed\xfc\x03\xc0FF\xbe\xbdj\xbc-K\xa2\xaf\xb4\u06edQ\xbc\x139o$\x83,\x8d\xfe&O\xa3\u07d9\xf1\u007f\x01\x8ez\xa7nC\x03\xde]\xf3pG\x96D\x9f\x8f\xe3x3\u05c1\u0280\xad\xd6&\xed$:#O\xe3{=\xe2{\x00\x0e\xc3h\xbfO\u05b4\x14f\xa7V\x8d\xb7fI\xf4\xa58\x8e\x9f\xe4:\x90\f\x9e$I\xb6\xc8\xe2\xd6'\xf2\x8a\xddn\xc0;1\x9a\x9d\u007f\x00\xd8\x1b\xb0\xb3\xf34\xbe%K\xe37\x91,\xdfb\xdaP\x01@f!\xcbZ\xbbeI|\xb6\xc7\xee\x8d\x00^\x0f<\xb4\x8f\xad<\x16\u01cd|[\xee\xd7o\xcb\xe3\xd6i$\u02f6\xaa\xb4\x883Y\x14=-K\xe2\x8b\v\u21c0\x1d\xe8:O\xc9\xd4\x00\x9cd\x85]\x97\xa7\u0477\xdb\xed\xc9\x1d]\a*\xb3\xa9\xe1\xa5\xf1\x9b\xf24\xbe\x13\xc4\u007f\x00\xb6\x8d\xebL%S\apJ\xd5xK;\x8d?\xdc\xef\x1d\x9f\xca*I\x92\xa7\xac\xd1)y\x17\x06{A\xbf~\xab\x038\xb9j\xfc};\x8d\xcf$\xef\x1fw\x1dH\u028f\xad\xd6&Y\x12}\xb6\x82\xe2\x16\x98\x9d\n p\x9d\xa9$\xb6\x00\xf9\xf1<\x8do\xcf\xd2\xe8oI\x96\xeaF\x87\n\x002\xa3,\x8a\x9e\xdeN\xa2\xf3\u0475\xdf\x00|9\x80\xaa\xebL\x03d9\xcd\xce\xcc\xd3\xf87\x9d4:\xcau\x18\x11\x97\xe28~R\x96D_\x86\x87_\x03<\xd8u\x9e\x923\x12\xc7Y\xe1\xfd_\x96D_\x8c\xe3xs\u05c1\u0284d%K\xa2W\xe5i|3\u020f\x03x\x82\xebL%\x17\x18\xf9\x0f\xb9_\xbb-K\xe37\x92\x1c\x89v_\x9a\xa6[eI\xeb\x1b\xea\x94\xccKh\xe4i\x9d4\xbc)KZ\xaf \xa9\x91\x12\xf2\x18$\x9by\x12\xbd7\xaf\xd8-\x00^\x87\xd1\x1e\u0277>\x1b\x83\xf8\xf7<\x8dnh\xc7\xf1\v]\x87y\xc8H\\\bdn\x92$\xd9\"K\xa2\xb3\xe0\xe1J\x03\x8ep\x9dg\xc0\xedP\x10?\u0292\xf8l\x92c\xae\u00c8,&\x92^\x1e\xb7\xfe\xbej\xfc=\x80W@\u05dc\xb9\xa8\x00xe\xd5\xf8\xbb<\x89\u07a5\xd1DSE\xe9<\x8d/\a\xf0\x05\x00Ov\x9dg\xa0\x10\x1b\x80\xfcd\u078e\u007f\x9dE\xd1\xd3\\\xc7\xe9\x17NL\xach\xa7\xf1\x99\x1e\xbb7\x00v\"\u02b5\xa7\xf8@!\xb0\x19`_\xce\xd3\xe4\xc2(\x8a\x9e\xe8:\x8f\x94G'\x8d\x8e\xc9\xd3\xf8\x06\x02\x1f\x00\xa0\xb6\xed\xac\xd86f<7KZ?k\xb7'wp\x9dF\x8d1y\x18y\xffx\x96\xb6\xfe\xad\x82\xe2\x16\x00\xaf\x85\xde\x1f=\u0117\xe7itM\x16E{\xb9N\"\xb2\x18\x92$\xd9\"O\x93\x8bh\xf6\x11\x00\xa5\x9c\x037 B\x02g\xe4ir]\x9eL\x8e\xe4\xe8\tNNn\x94%\u0457\xe0\xe1W\x00\xf6v\x9dg\xa0\x11O\x83\x87_\xb6\x93\xe8\x83e\x1b\x92\xba\x10$ky\xdc:-\xafU\xef0\xf24\x00\r\u05d9\x86\a\x0f\xady\xf8M'\x8d\x8eq\x9dD\u070a\xe3x\xb3<\x8d\xbeU\x10\xdf\xc7h\xec\xd8\xd3\av\xa0\x15\xde5y\x12\xbd\xcfea_\x1d<\x01\x00\xb4\xe3\xf8\xffu\xd2\xf0&\xd0\xde\x02\r\xe3\xe9\x13\xdb\x06\x1e.\u02d3\xd6;4\xa4N\x86Y;\x8e\x8f\xafXq-\xc0\x83\\g\x19\x1e\u071e\xf0.\u0292\xe8,\x92M\xd7i\x16K'\x8d\x8e\u026a\xdeu\x00N\x86\x16m\ub57a\x01\xef\xc9\xd3\xf8\xb2$I\x06~\xfb\xde\x81\xf7\xe7i|u\x96\xb5vs\x11@\x05\x80\x11\x17\xc7\xf1f\xed$\xfa\xa1\x19\xffgj\xb8\x97\xf4Y\x8d\xb0\u007f\xce\xd3\xe4\xeca\xba\xfb\"\x02\x00$\xebY\x12}\u064c\xe7\x80\x18\xc9E\xc7\xfa\xcc\x00\xbc6O\x93\xab\x87}4\x11W\xaf^\x9e%\xad\xff*\x88\xef\x1b\xb0\xa9\xeb\xc3sE\u04b24~\x13\x8d?\x83\x16\xf9[L\x1e\x81\x0ffI\xf4\xa5\xb2\x8fL#Ym'\xd1?\xc2x\x19\x80\xad]\xe7\x19a;U\x8d\x97\xa6i\xba\xad\xeb \xd2\x1f\xed8>\u044a\xcaU\x00\x9c/X7\nh86O\xeb\xbfj\xb7'\x17e4\x93\n\x00#&M\xd3m\xf24\xbe\x02\xc0+]g\x11\x00\xc0\xdey\u057bH\xc3\xe9dPeYk7\x8f\xdd+\x01n\xe7:\xcbh\xb2\x13\xf3v\xfc\x8bA_\xa5\x9bd#O\x93\xb3\xa7\xb7\xf6\x1b\xf9\x1d\x0f\x1c99O\xe3\x1f\x96ud\x1a'&6\xcc\xd3\xe4|\x03N\x87V\xf7/\x83-\x8d\xddK\x86a\x1d\ty\x04Ik\xa7\xf1\x99f\xfc\x06\x80\x91Yo\xa6\x1cl[+\xbc\xcb\xf2d\xf2\x90~\x9fI\x05\x80\x11\xd2I\xa3\xa3\xc0\x97\xb8\xce\"\xa8\x1b\xec\xec<\x8e\xdf\u06af\x13\xa8\x000\u4987\xf2|\x98\u018fB\xff\xdeewr'\x8dOw\x1dB\xe4\xf1\xb0\xd5\xda\xc4c\xf7\"\xed\x1cR:+h8?\x8f\xe3}]\a\x99\x8dv{rgc\xe5\xa7\xd0~\xd2%\u0103\xb34\xfe\x8e\xebN]\x96F\xaf5\xe39\x00JQ\x8c\x90\x99\u0601y\x9a|\xc1u\n\x99\x1f\xf2\xc1\xa5y\x1a\x9e\xaf\xad{K\xc5h\xfch\xbf\x16hU\x87p\x88\x91\xac\xe6i\xfcE#\xff\xc1u\x16\x99\x1d\x02\xef\u03d3d\u007f\xd79DfB\xb2\x92W\xec\xab\x00\xb6t\x9dE\u0585\xe34\xfe8\x8b\xe3\xbd]'Y\x9f<\x8e\xf7\xb3\xc2\xfb\x85\xb6\xf8+/\x03\x8e\xc8\xd3\xe8lW#\xd3\xf2$z\x0f\x88\xb3\xa0\xf9\xfe\x03\x82/\u0352\x96\u0597\x1a0\x9c\x98X\x91\xb7\x1b\x17\x01\x18\xa8\xd1c\xa3\x82\xc0\a\xf3$zw\xaf\x8f\xab\x02\xc0\x90\"\xe9\xe5i\xf2e\x00';\x8e\"s\xe3\x11\xc5\xd9e]\x84I$K\x93\x0f\x018\xccu\x0eY\xaf%\xf0x^\xbb\xdd\xda\xd5u\x90u\xc9\xe2xo\x1a~\f@\x8b\x9f\x96\x9e\x9d\xd0I\xe3E\xdf\"\xb0\x9dD\x1f$\xf0\xc1\xc5>\xaf,\x94}FR\xbf\xa3R\ny\xad\xf2O\x00V\xb8\xce!sD\xec\xdciG\xfb9\x8f11\xb1\xc2c\xf1\x03\x00Op\x9dE\xe6\x83\xe3Vx\xdf\xec\xe7\xce\x00\x9d4:\x1a\xe4\xbf\xf5\xeb\xf8\xb2\x88\x88\x0f\x92\u007f]\xe2:\x86\xac[\x96&g\x90x\xa1\xeb\x1c2gu\xc2\xfb\xdf4M\xb7Z\xe8\x81\u0539\x18\"\x9d4:\x8af\x1a:>\xe9:\x87\xf4\xdc\xe6Y\xbb\xf9\xde^\x1e0\b\x82;\v\xab\x1c\x06\xe0\xae^\x1eW\xdc2\xe0\r$C\xd79F\x1dI\xeb4\xea_\x01\xf0\x14\xd7Y\xa4\xa7>\xd5nO\xee0\x9f\x17\xaa\x000dja\xf8K\x148\x04\xc0\x83\xae\xb3H\xcf\xec4\u0750\x16YTy\x1c\xef\a\xe0\x99\xaes\u022ct\x8d|G=h\xbe\xc6\xccr\xd7aH6\xe1\xf1\xeb\x00|\xd7Y\xa4\xf7\x8c<\xb5\u075e\u063e\x97\xc7\xf4}\xff\xf6.\xbcg\x01\xb8\xad\x97\xc7\x15\xa7\x96di\xf4\x02\xd7!F]\u078e\xff\x96\x86\xe7\xba\xce!=\x17\x1a\xbd\xaf\x93\xac\xcd\xf5\x85*\x00\f\xa1z\xb3y\r\n\x1c\x06\u0bee\xb3H\x8f\x18Nv\x1dAF\x90\u01f7\xba\x8e\xd0g9\f+A\xacr\x1ddal\xd23\x1cW\v\xc7>\xec:\xc9C\xf24\xfe\x18`\u06fa\xce!}S\xb7\xa2\xf2\xa9^\x1f4\b\x82\xbb;\xb4\x83\xa1\"\xc0\xd00x'\xbb\xce0\xca\xd24}*\b-\x10>\xac\x88=:I\xf4\x96\xb9\xbe\xac\u068f,\xe2^\xbd\u067c6\x8b\xa2#\xe0a\x90\xf7\\\x8e`\xb8\x99\u011f=C\x8b\xc4\x04\x88\x98\x9e\xc5^Q\xac\x04\x80\xc2l)\xcc<+\x18\xc2l\x03\x82\xcbmj\x9b\xa9-\x00l\xe46~\x0f\x19N$\xf9\xf7f\xd6v\x1dEF\x03''7\u0289\xe7\xb9\u03b1\x00\x0f\x02v\x1d\xc0[\x8c\xbc\xb9\xeb\xd9\xcdf\u016d\xddn\xa5\x15dY\vK\x97N\x98Yw\xcd\x17\x90\xf4\xb1zu\x906\x1a\u02ea\xc0\xe6Dw+\u009ej\xe0V\xa0\xed\x04\xc3\xce(_\xe1\xfcnz\u0171\xd5\xc6\xd8\xff\xb9\x0e\xf2\x904\x8d\x8e\x05\xf1\x1a\xd79\xa4\xef\x0eK\xd3\xe8X\xdfo~\xbf\x97\a\r\xc3\xf0\x9e8\x8e\x0f\xae\x1a\u007f\n`\xc1\xdb]9\xd2\x06p+\x81{=\xc3j\x12\xad\xe9\xf6K\xcbc\xb1\x1aDQ\x98\x8d\xc1\xacf(\x1a\xa0-7b\x03\x1a6$\xb0\xa5\x01\x9b\x000\xd7?Do\xf0\xe0$I\xb6\b\x82@\xd3;\x16\x19\xc9J\x9e\xc6gc8\x17\xd8$\xa6\xa6\f\xfd\xc1\f\u007fb\xc1?\xd2\xf3R\x90m\x8f\x8c\v\xb3\x10f\r+8\x0e\xe3\x06\x80=\x19\xc0\x93\x01l\x8a!\xeb\xff\xd2\xec\x03i\x9a~\xc7\xf7\xfd\x9bg\xfb\x9a\xa1\xfa\x1f \x8fVo6\xaf\u0262\xe8\xb0\xe9\"@\xd9\xf7\xef\xbe\x01\xc4O\xe1\xe1\x06cqs\xce\xca\xcda\x18\xfea!\a$\x19\xe6q\xbc\x1d<\xee\x06\xc3n\xa0\xed\x0f`\x0f\f\xe6N\t\u02f3$y.\x80s]\a\x91\u0450W\xed\x18\f\xd6\xefJ\a\xe0/\rv\x01i\x17\u0502\xe0\xea\xb5;\xf8\x8f\xc7\xccR\x00)\x80\x95\x98Z\x90\xec\xe7k~\x9f+W.\xeb\x06\xf5\xfd\xbb\xb0\x03\x8c<\x10\xc0\xdep\xdbH\xbf\xb2\xd6\xe5q\x16\x8c\xfd\xd9a\x86G!\xef\x1f\xef\xa4\xf8\f]\a\xe9\x13\x03\xfeX\x00\xd7\x1b\xf9;xv\x93\xb1\xf8\x1d\vo\xa2\xa8TV5\xf2|\x12cc-\x00\xc0\xea\xd5>\xaa\xd5Fn\xb6\xa9W\xc1f\x05lK\x90\xbb\x02\xd8\rS\u05e19\x0f\xd9,#\x0f\xf8\x00\xc9\x1f\x98YO\xff\u0267\x8b\x00\aU\xad\xb8\x18\xb0mzy\xec>\xb8\x03\xc0Oav\x9d\xa1\xf8}\x17\xd5[\x1a\x8d\xc6]s\xfd\xfcY\x13\xc9F\x96\xb5\xb6B\xb7\xb2+<\xecn,\xf6\x05\xec\x19\x00\uaf4b\xbdh\xbc*\x8a\x97\x03\xf8\x90\xeb \xa3&o\u01ef\x03\xb0\x9f\xeb\x1c=\xf2\x17\x80\x17\xc3\xec\x12\x14vm-\bn4\xb3\xd6\\\x0fB\xd2\u03d3d7x\xdc\x13\xc43\x00\x1c\t`\xe3\xde\xc7]T\xbe\xb1\xfb)L\xfd,\xb3\xa2\x02\xc0\x90\xab7\x9b\xd7fY\xebPt\xed'\x006t\x9dg\rw\x01\xb8\x90\xb4\x8b\xebE\xf1S\x1b\xeb}\x03\xd6\xccb\x00\xd7N\u007f\x01\x98j\xc0g\x8d\xc6\xe1\x9e\xc7\x13H<\a@\xd0\xeb\xf3\xf6\x8b\x19\x8f\x82\n\x00\xb2H\x8c\xf6<\x0e\xc6\xfd\xa7{\x8c\xfc\xf7j\x81/\xdb\xd8\xd8_\xfay\"\xdb`\x83U\x00~0\xfd\x85$I\xb6\xac\xa2x)\x81\x97\x02\x98\xd7B<\xf3\xc7\xff\xae\xf9\xcdW\x99Y\xb2\xb8\xe7]\xbf<\t\u03c0\xe1I\xaes\xf4PL\xe0\x123;\x9f\u05bd\xa0\xde\x18\xbfi\x96\xaf{\xe8\xdf\xe5\xcfX\xe3\x1a\x04\x00$\u01fa\xed\xf8YE\x81\xa3a8\x1eS\xa3\xd6\x06\x13\xb1G\x96\xc5\xcf\x05\xf0\xdd^\x1f:\f\xc3?DQtP\u0373\x8b\x01n\xd7\xeb\xe3/\xc0\xfd\x80]\b\xf0\xe2.\xbc\x8b\x83 \xe8\xf9\xee\x05\u04e3\xfdn\x9c\xfe\xfao`\xea\xa6F\xb7\x1d\x1fX\x10\xc7\xc3p\x1c\x88\rz}\xde~!p4T\x00XTl\xb56\xce\v\x9c1\xe0\xe3H\xee\xa2\xd99\xd6\xe57\xeb\xcd\xe6\u057d8\xe0t\xa1\xff\xca\xe9\xaf\u03d0\xf4\xf28\u0793\x1e\x8e\xf3\x80W\x10\u062c\x17\xe7Yl\x06\x1c\u044e\xa2\xe3\x1a\xcd\xe6wf\xf5\xfc,\x89.\xecs\xa4J\x89\xf7\xff\xbd\x01\xc0\x9f\\\x87\x00\x80\xc2*o\x98\xcb\u040d\xb9j\xb7[\xbbXa?\x81\u06c6F\f\xe0\u007f\f\u0157\xaa\xfe\xd8%\xbd\xbec0W\\\xb5j\x83N\xbdz\n\xcd\xde\b`s\x97Yf\xe9\xcez\xd0\\\xb4\x15\\\xf3$z7\xcby\xc1~\xb0\x1e4\x17mD\v\xa3h\xd3\xdc\xc3\x1f\x17\xeb|sA\x0f\xc75\x1a\u035e7\xbcI\x86y\x1a\xdf\x0f\xa0\u032b7?\b\xb3\xf7\xd5\x1a\xc1\xe7\xcb05&\x8b\xa2\xa7O\xad\x99`/B\u007f\xa7\t\x90\xc0\a\xeb~\xf8\x01\u05df\xa1k\x9b\xfa\u007f\x80+0X#G\u058d\xb8\x0e\x1e\u03aa5\u04af\x9b\xad\xe8\xdb\xf6\xba$+\xddv|D\x97x\x93\x01G`\x10\x87}\x1b\xae\xad5\xc2=\xfb\xf5~\x9c\xfa\f\xb6\x8b\x01\xf6t\xd1\xc19\u028d\xf8Q\xd7\xc3\x17\x1b\x8d\xf0\u01ee\x17\xda$\x19\xe4i\xfcR\x00o\x06\xb0\x93\xcb,\xb3\x94\xd7\xfcp\xf9|\xee\xd8\xceV\x96\xc6\x1f\x01K\xb9k\xcdm\xf5\xa0\xb9\xf5b\x9f4K\xe2\xaf\x02\x1c\xd4m\xa4\u007f\xe2\x19>V\x99\xfa][\xb4\xeb\xdc\xf4\xe7\xf1Q\x05q*\x80\xc3\x17\xeb\xbc=tG\xcd\x0fw\x9c.r\xacW\xdf/4\xd3\r\u0268\xdf\xe7\x99\x1f\xbe\xa2\x1e\x8c\x9d\xed:\xc5bi\xb7'w\xb2\u00bb\b\x8b=\xd4\xc5p\r\x88\xcf\xd6\xfc\xf4\x9b\xfdlH\xcd\x17I\xbf\x93Fo&\xec\xdd(\xf9<\xa9.\xbc\xa7\xf6\xe3n\u00fa\xa8\x000e\x14\v\x00y\xda:\x82\xb4\xf3{}\xdc^1\xe2{\xd5nq\x8a\x8d\x8f\xdf\xef:\xcb\xda\xda\xed\x89\xed\xad\xa8\xbe\x1b\xe0\x89\xe8}G8%\xedU\x8d0\xfc\xaf\x1e\x1fw\xc1HZ\x9e\u0197b\xc0\x87\x9b\x1a\xf1}\xc2\u03a8\x87\u154b}\xeev{rg\x8f\xde?\x928n\xb1\u03fd@-z\u077d\x1a\x8d%\xbf\xeb\xd7\t\xd8jm\x92W\xec\"\x00;\xf6\xeb\x1c3\xb8\xcd\xc8\xff\xa8\x16\xf8Z\xbfG\x18\xcd\aI/O\xe3\x93\t\x9c1\xbdn@iy\x86\xa3\xab~\xf3\xc7\xfd:\xbe\n\x00\x8f\xc8\xe2\xf8\x190\xfe\x12\x03WP\xb4\x8bP\xf0\xb4^\xdd\xed_\x88<\x8e\xf7\xa3\xe1\x03\x00\x0fu\x9deNho\xad\x87\xe1\xc7\x1e\xefie[\xccH\xfa\xa8\xd1\x18\xbf\x81^q0\xa7\x86$\xf6\x1f\xf1\u007f\xf4p\\\xad\x11>\xbd\x1e4?_\xc6\xce?05\x1c\xa8\x16\x8c\x9dYXew\x00W\xb8\u03b3>\x15\x14e\x1dM#\u00e4\xc0\xee\xae#\u0304\xc0?U\x83\xf0\xb82v\xfe\x01\xa0\xd1X\xf2\xbbz\x10\xbe\xbc\xb0\u028e\x80]\xdc\xc3C\xff\x05\xb4\x83\xcb\xd8\xf9\a\x80,I\x8e\xc7`w\xfe/7x\a\xd4\xc2\xe6s]t\xfe\x01\xa0\xd1\x18\xbf\xbe\xe67\x9fo\xf0\x0e\x00p\xbd\x8b\fs\x94\x81\xf8T\xadSl\xd5\xcf\xce?\x00\xd8\xd8\u061fk\x9d\xe2`,\xde\xff\x97\xbb\x00\x9cR\xf3\xc3\xedk\xe1\xd8G\xcb\xd8\xf9\a\x003+\xeaA\xf3\x8b\xf5\xbc\xbb\x8b\x19f5\xf4\u05d5.\xec \xd7\x19F\x86\x15\xff\x8a\xc1\xea\xfc\xdf\xe9\x19\x9eS\x0f\xc2\xc3\xca\xd0\xf9\a\x80Z\x18^V\x0f\xc2\xc3H{\xa1\x01\xf7\xba\xce3k\xc6w\x92\xf7\x8f?\xde\xd3T\x00\x181\x8d\xc6\xf8M\xf0\xba\a\x1b\xfazG\xf3&\xd2^T\v\xc2=\x1a\x8d\xe6w\xcb6Lu&\xbe\xef\xdfV\xf3\u00c3\x00\x9e\xe3:\xcb\xcct\x01\x95\xfe\xa3y\xbb\xba\u03b0.4\xfb\x97F\xd0|\xf7 |\xa6\xf8\xbe\u007fs\xcd\x0f\x0e\x03\xf0\x1a\x00\xab\x17x\xb8\xdfv\xe1=\xa3\x1e\x86\xa5,P\x92l\x98\xb14[\x10\xce\t\xb1\x8a\xe0\xcb\xeaAs\xbfZ\x10\xfc\xc2u\x1c\x00\xa8\x05\xc1/j~\xb8'\x81\x0f\x00\x98\xf7Br}T\x00\xf6\xd5.\xbc\xed\xeaa\xf3T\x1b\x1f\xbfo1Nj\xe3\xe3\xf7\xd5:\xc5! \xfa\xb6\xe3\x85\x01\xf7\xc2\xf0\x86\x9a\x1fn[\x0f\x9a_0\xb3N\xbf\xce\xd5K\xb6d\xc9\x03\xd5F\xf8\x02\x9a\x95\xf6\xf7\xd0\u0203\\g\x18\x05\xed(:\x0e\xb0\x03\\\xe7\x98%\x028\xab\xe6\u01fbV\xfd\xe6\x8f\\\x87Y\x97F\x18\xfeo\xd5Ow\x04\xf0%\xd7Yfi\xa3N\x1a\xbe\xf9\xf1\x9e\xa4\x02\xc0\bj4\x96\xfc\xaek\x95\x83\xfbP\u044aA{k\xcd\x0fwi\x84\xe19fV\xf4\xf8\xf8}gf\xed\x9a\xdf<\xd1\f\xdfr\x9de\x9d\x8c;\xbb\x8e \xa3\x80\xbb\xb9N\xf0X\xbc\xb4\xde\b\xde\xe5:\xc5\\\x98\x19\xebA\xf3?;\xb4\x9d\b\xcck\xe8+\x81\x1f\xd5\xfcx\xbf2o\xa1\x95\xb7\xe3W\x03\xd8\xd2u\x8e\xb9\xb3\x8b;\xb0]\x1b\xc1\xd8\xd7]'Y\x9b\x99e\x8d\xa0\xf9~Cq\x18K\xb2V\x110=E\xc2+v\xab\a\xe1IA\x10\u0739\xe8\xe7\x1f\x1f\xbf\xbf\xd6\xe9\x1e\n\xc3oz|\xe8.\xcd>R\xf5\xc3m\xea~\xf33f\x96\xf5\xf8\xf8}gfl\xf8\xe1;J\\\x04\u0619\x1c\x90\xa5e\a\x14I3\xc3\a\\\u7625\x16i'\u0503\xe6\u07d8m4\xe9:\xcc\xfa\x98\xad\x98\xa8\a\xcdW\x01|\x05\x80\x92Nk\u007f\x04\x817\x93\\\xef\x94f\x15\x00F\x94\xef\xfb7w\xadr\x90\x01\v\xdaj\xef\x11\xbc\xb4\xb0\xcan\xf50\xfc\xd8B\xb6\xbe)\x033+\xaa\x8d\xf0\xe5\x98Z}\xb7\\\x88mt\x01\x95~\"Y\x03P\xa6\x15\xb7\x01\x80\xf4\xf0\x86A\xfdl\t\xc3\xf0\u07ba\x1f\x1e3\u71b9\xf1\xe3u?|n\x99\x1bG$\x1bF\xbc\xd3u\x8e9\xa2\x01\xa7\xd7\xfc\xe0\xf00\f\xefq\x1df}j\xc1\xf8\u03fa\xb4g\xc0\xf9\x94\x00\xfe\xdch\xfb\xd5\xc2\xe6s\x1b\x8dq\xa7Yl\u0252\ajY\xf70\x18\xae\xe9\xd1!o\x04m\xbf\x86\x1f\xbe\xbdl\xbbj\xccG\xbd\x11\xbck\xbe\x05\xc7>\v\x93$\x19\xc8\x15\xd6\aE\x96$\u03c7\xa1\x94#\xf8\xd6r;\xbdb\x9fF\x18\xfe\x8f\xeb sQ\x0f\xc6\xceF\x81\x83\x00\x94r\n\xe2\x1a\x96\xe7I\xf2\x9a\xf5=A\x05\x80\x11\xe6\xfb\xfe\xad]\xab\x1c\x04\xe0\xee\x05\x1c&\x82\u06695\xbfy\x90\xef\xfb\xb7\xf6(\x9asf\x16\x83\xf6jL\rO*\x931\xc4q\xa9\x17\xfa\x91\x01\xd7j-C\xe9\xf6(\xb7\x8b\x1b\x8d\xb1\u07faN\xb1\x10fV4\xfc\xf0\x1d\xd3w\x10\x1eo\u05c2\x0e\f\u007fS\xf7\xc7\xdeR\xf6\xa2G\u078e_M\f\u0536\u007fm\x82/\xab\x05\xcd3\x06e\x94Z\x18\x86\xf7\xd4\xfc\xf6\xfe\x00\x16\u007f\x8a\x02q\xdd\xd4\xdc\u0731\x03kax\xf9\xa2\x9f\u007f\x06\xb6d\xc9_ki~\x18\f\v\x99/\xdc!\xec\u031a\x1f\xee\xe9j\u0747~0\xb3\xa2K{-`\xa5+\x1c\u05ac\xbb\x8d\xeb\f\u00ca\xa4\x99\xc7\xd3]\u7605\x9b\xf2\x02\a\xb8.$\xceW\xbd\u067c\xaa\xb0\xca\xfe\x00\xeet\x9de\xbd\x8co\x99\xbe\xa1\xb3N*\x00\x8c8\xdf\u05d6R\xb5\x00\x00 \x00IDAT\xf7o\xebN-8t\xfb<^~\x0f\n\x1cP\xf7\xc3O\rJCj.\xeaax\x85qj\xbf\xef2\xe9x\u07a2o'#\xa3\xa3]\xab-s\x9d\xe11\x88\x1f\xba\x8e\xd0+\xf5`\xecl\xa3\x1d\x02\xc3\xcau>\x81Xe\u01a3\xea~\xf3\xacE\x8e6g$+ \u02b8\xea\xf6\xba\x11\xab\f\u0791\x8d`\xec\x1b\xae\xa3\u0315\xd9\xf2\xd55?>\x1a\xc0bu\xc2o#\xf8\xd2Z\x10>\xad\xacssm\u0672\x95\xb5F\xfbPL\xed\xe7=W\x0f\x9a\xf1\xa8F\x10\xbes6[f\r\x9a0\f\xff@C\xe9>C\b\xb5_\xfa\xa5\u04ce\x0e\a\xb1\x87\xeb\x1c\xebE\xfc_\xadS\x1c\xd4l6K\xb9\xb3\xd2l\xf9\xbe\u007fs\x17\xde!e\x9a\x9e\xb5\x0e\x9bgI\U0008267e\xa9\x02\x80 \b\x82\xbb\xbb\xf0\x0e\x010\x87\xed\xe5xI-\xef>\xad\xdel^\u06f7`e\xe0\xf1\u04ee#\xac\x8d(\xb6u\x9dA\x86\x97\xd7\xed.u\x9damfE\xdf\x16\xfdr\xa1\x16\x86\x97\xa3\xb0\xa3\xd6q\x87\xeeVV\xba\xfb\xd4\xfc\xb1\x9f8\t6GY\x92<\x0f\xc0S]\u7625\xd8`\xc7\u0502\xe0\x12\xd7A\xe6\xcbl\xa3\xc9Z\x9a=\a}\x9c\x9eF\xe0O\u04cb\xe0\xed\xd0\b\u01beQ\xf6\xe2\xfeTa\xa4}$\xe6V\x04\xb8\xa9\xb0\xca3\x06\xe5\xf7l\xbe\n\u06a7Q\xb2Q\x8c4S\xfb\xa5O\n\xda\xe3.\xfc\xe6\x92\x01\xf7v`\xcfY\xacEC\xfb-\b\x82;\xe0\x15G\x00x\xd0u\x96\x99\x98\x15\xaf\x9f\xe9{*\x00\b\x00 \b\x82\xbb\xba\xf0\x0e\xc2\xecF\x02\x9cU\xf3\x9b\x87\u06d2%\x0f\xf45T\tT\x1b\u035f\x82X\xe5:\u01da\fx\xa2\xeb\f2\xbc\xccc\xe9\n\x00,\xac\x94[\x88.D=\f\xaf4\u0631\x00\xe2\xa9G\xf8\xf3Z\xde}f\xbf\xb7S\xeb%3\xbe\xc5u\x86Y\xca=\xc3\t\xb50\xbc\xccu\x90\x85\xb2\r6X\u0545\xf7\x1c\x00\xbd\u0756\x8eXe\xe0\xbb\xea\x8f,\x82\x97\xf7\xf4\xf8}4U\x04H\x8f\xc0,FGL-\xaa\xd9\xdeg\x98\xa6,\xce$\b\x82\xbb`(\xd5M\x1a\xa3\xda/\xfd\x90\xa6\xe96\x06\x1c\xe9:\xc7zL\x14\x1e\x8f\x0e\u00f0G\ub395C\xa31~\xbd\x81'\xa0\x9c\xbb\xb5\x00\xb0\x03\xdb\xed\xd6.\xeb\xfa\x8e\n\x00\xf2\xb0 \b\xee\xee\xd0\x0e\x020\xe3\x85\xd1\xc8\u007f\x98Z\xb1sp\x1a\a\vaf9\xccJ\xb1'\xe9C\n\xb3\xf5\xae\xec)\xb2 \x86\x8a\xeb\bk\xf3*x\x82\xeb\f\xfdP\v\x82K\xcc\xf8\x02\x00\x9f\x9b.\xaa\xfe\xd5u\xa6\xd9j\xb7[\xbb\x02\xd8\xdfu\x8e\xd9\xe1k\xab~sh\xa6\x91\x04Ap\xa7\x19OFo\xee\xee&4\xfb\x97Z\xde\u066a\x16\x8c\xfd\xb3\x99\x95~\x85\xebu1[1Q\xf3\xe3gc\xfd\xeb$\x9c5\xb5\xa8\xe6\xf2\x85n\xcb98\n\x94j\xebP{\x9c\x95\xc9e~\xbc\xa2\xf3\x06\x94\xb7OGz8\xa9\xd1\x18\x1b\xaa\x91|\x0f\xa9\x05c\x17\x118\xc3u\x8e\x99\x18\xf1\xcau=^\xd67\x8b8\x12\x86\xe1=SE\x00\u07bc\xf6\xf7\x8c\xfc\x87Z8\xf6\xaf\x0eb\xb9E\x96\ua39c\x15\xba\x80J\xff\xb0\xf0J\xd78\xee\x12{\xbb\xce\xd0/5\u007f\xec\xfcz\xd0|\u0760m;f];\xc5u\x86Y\xfal=\x18\xfb\xb2\xeb\x10\xbdV\xf3\xc7\xce\x03\xb1\x90)j\x1d\xc0\xbe\u0685\xb7c\xc3\x0fO\xb3\xa5KK;\x8cu\xb6\xcc6\x9a\xac\xf9\xe1Q\x00\u007f\xbe\x8eo\u007f\xbe\u61ef/\xfb\xa2\x9a=\xe7Y\xa9\xda/\xd4\r\x8c\x9e#Y\x87\xd9K]\xe7\x98\x11\xf1\xe9F\xa3\xf9]\xd71\xfa\xa9\xee\x87\x1f\x00P\xca\x11f\xa4\x9dH\xf217vT\x00\x90\xc7\b\xc3\xf0\xdeZ\x17\xcf\x02p\xc3C\x8f\x19p\xfaHv\xfe\x01p\xa6\u017a\\14]G\x90\xe1\xc5J\xb7t\xc3\xed\rx)\u026a\xeb\x1c2\x85d\x03\x86\x13]\u7605\xdf\xd6\xfc\xf0\xad\xaeC\xf4K-\b\xdf\x0eb\xaew\xd5h\x86s\v\xab\xecT\x0f\u0093\x82 \xb8\xb3\x1f\xd9\\1\xb3V\xcdo\x1e\x05\xd8\xc5k<\xfc\xe5\x9a\x1f\xfe\x8d\x99\x95j>\xfcb \x8br\xb5_@\xb5_z,K\x92\xe7\x02\xd8\xd0u\x8e\x19\xdcP\v\u00b7\xbb\x0e\xd1ofV\xd0+^\x83\xc7\xdf\xe1g\xd1\x19\xb0I\xa7\x1d\x1d\xb6\xf6\xe3*\x00\xc8:\xd9\xd8\xd8_j]\x1e\x06\xe0&\x03\xdeS\v\x9a\xa5\x1d\xde\xd2o\x1eP\xaa\xe9\x0efP\x05]\xfa\xa6\xd3)\xdf\b\x00\x00[\xe5I\xf2F\xd7!dJ\xc9\x1b\x9c\x0f\x89\v\xab\xbcp\x18\xf6u\x9f\x89\x99\xb5Q\xe5I\x98\xe55\x8a\xc0\x05(\xb0W\xcdo\x9e\xe0\xfb\xfecF\xf9\r\v3\x8bk~p\xect\x11\xe0\xec\x9a\x1f\xbe\xba\xec\x8b\x19\xf6\r\xbd\x8e\xeb\bkQ\xfb\xa5\u05e6\xa6\x03\x95Qa\xb4\u05d9Y\xe9:\xc5\xfd\xd0h\x8c\xdfd\xc0?\xbb\u03b1.\xa4\xbdd\xed\xc7T\x00\x90\x19\xd9\xd8\u061fk~\xb8W-h~\xc8u\x16\x97h\xe5Z\x14\xad\xa0.\xa0\xd2?a\x18\x96\xb1\x00\x00\x18\xcf\xc8\xe3x\x1f\xd71\x04\xf0<\xbe\xd8u\x86\xc7c\xe0\x87\x86\xb9\x93\xfb\x90z}\xec:\xf0q\xb7{\xfb\x95\x81\x875\x82\xe6\x91\xf5f\xb3Tk\xda\xf4\xcbt\x11\xe0\x98\x9a\x1f\xbejd;\xff\x00\xcc\xe3\x12\xd7\x19\u05a2\xf6K\x0fq\xe5\xcae\x06\x1c\xee:\xc7\f>?\f\v\xaf\xceE\xd5\x0f\xff\u01402.tx\xcc\u06a3(U\x00\x90\xf5\x1a\xd4\x05\x81z\xc9\n\xdb\xc6u\x865\x19\u02b7H\x9b\f\x0f3\x8b\b\xfc\xd9u\x8eu\bh\xfc^\x16E{\xba\x0e2\xca\xc8\xfb\xc7I\x1c\xe5:\xc7\u3e35\xea7\xff\xcdu\x88\xc5R\xeb\x16\x1f\x04\xb0\x8e\xa9;\xf6;\xd2N\xa8\xf9\xe13k\xc1\xd8E\x8b\x1e\xcc13KFn\xce\xffZ\b\xb5_\x86Y\xee\u05de\x0f\xa0\xee:\xc7:L\xd4\xf2\xee\xe9\xaeC,63Kh\xa5\\\x10py'm\x1d\xb0\xe6\x03*\x00\x88\xac\a\xc9\n\r\xba\xeb(\xa3\xe6:\xd7\x01f\xb0!<\\\u048e\xe3\xe3]\a\x19UY\xd2<\x06@\xe0:\xc7\xfa\x98\xf1\r\xa32\xec\x14\x00l|\xfc~\x03>\xb2\xc6Cw\x03|U\xcd\x0fvn\x84\u1e638\xf7]\xa6\x18\xf9,\xd7\x19\xa4\u007f\b+\xe5\xb5\u0400\u007f\x1b\x85\xad\xc2\u05e5\xd6\b\xbf`\xc0\xbd\xaes\xac\x8d\xb4\xe7\xad\xf9w\x15\x00D\u05a3\u06ce\x8fD\xf9\u7e8a\xf4\x96Y\x99\xb7\xebi\x9a\xf1\x9c,\x89\xcf\xe6\u0295\xcb\\\x87\x195f\u0171\xae3\xac\x9f]T\xf3\xc7.p\x9db\xb1U\xfd\xf0# \xae3\xf2\x1d5?\u072e\x1e\x8c}i\xd4\xef~\x8f\xba4M\xb7\x01\xb0\x97\xeb\x1c\xd2\x1f$\x9b\x06\x1c\xe2:\xc7:lf\xa9\xeb<\xe2\x9e\xc7\xe2\xbd\x00\xccu\x0e\xe9\x8fn;>\x18@\xc3u\x8e\xb5\x11\xf8w\xb3\x15\xa5\xdbMh1U\xb3\xee\xe7\x00\u012es\xace\x878\x8e\x9f\xf4\xd0_T\x00\x10\x99A'\x8d\xdf\x05\xe0\x99\xaes\x88,6Z\xf5J\xd7\x19fi\x05\xcd\xce\xcc\xd3\xf8\x86,\x8d^K\xb2t\x8d\xa1a\xd2I\x92g\x00X\xe1:\xc7z\\Q\v\xc6\u007f\xea:\x84+\x1a\xea/\x0fi\xc7\xf1\t\x00_\xe6:\x87\xf4OQ\x94r-\x96v\xbd\xcb\u03fa\x0e\xe1\x9a-]\xfa \xc0\xef\xba\u03b1\xb6\xaa\x15\x87>\xf4g\x15\x00D\xd6!K\xe37\x12\xf8\xa0\xeb\x1c\".\xf8\xbe\u007f+\x80\x1b\\\u7603\xadA\x9c\x95\xa5\xf1\x1d\xed$\xfa\xc7\u986f\xd2k\xc6C\x1f\xffI\xee\x14V\xce-\x98D\x16S'\x8d\x8e1\xe3\u066esH\x9f\x19\u02f8\xfa\xff\u007f\xd9\xd8X\x19\x17\x11^t\x9e\xd9\xd7]gx,\xdb\xff\xa1?\xa9\x00 \xb2\x06\xf2\xfe\xf1,\x89\xbe\x04\xf2\x93\xd0\xd09\x19a\x04\xbe\xed:\xc3\\\x19\xb0\xa9\x01\xa7{\xec\u079c\xa5\xd1UY\x1a\xbf\x89\x13\x13Z\u00e3G\b\x94yA\xb1\xbf4\x1a\xe1\x8f\\\x87\x10q\x85d\xad\x9dD\xffX\x10\xdfA\t\x87\x86K\xef0\x8a6E\xc9vx\x00\x00\xa3}\xceu\x86\xb2\xa84\xc2\v\x00\xfc\xd5u\x8eG1<\xbc\x8b\x92\n\x00\"\x00H\xfaY\x1a\xfdm\x9e\x86\xb7\x008\xd9u\x1e\x11\u05ec\x18\xbc\x02\xc0\xa3\x10{\x82\xfcx^\xab\u0713%\xad\xffn\xc7\U00049718(\xf3\xf0\xf5R\x9b\xdeC\xb8\xb4S\xa2hv\xb6\x99u\\\xe7\x10Yl$+\xed8>!O\xa3\x1b\f8\x1d\xdajo\xe8e\xf6\u021d\xdc\x12\xb9\xad\x1a\x04W\xb8\x0eQ\x16\u04cb\x01^\xe8:\u01e3\x10;\x93\xf4\x01\xa0\xea:\x8b\x88+$-\x8f\xe3=Q\xe1K\xf24>\t\xe5\x9e\xdb*\xb2\xa8jaxm\x9eF7\x03\xb6\xad\xeb,\v\xe4\x03\xf6\"3\xbe(\xafU\xbaY\x12]i\xc0\x8fX\xe0G\xb50\xfc\x8d\xe6M\xcfN\x1e\xc7{\xc0\u00d8\xeb\x1c3\xb2\xae\x86<\xcbHi\xb7'\xb6\xf7\x8a\u028b\xf24~\x95\x19\x9e\xacA\x8b\xa3\xc3P\xec_\xb6\u007fo\x02_\xd3\xf5\xf41\xce\x03\xf0b\xd7!\xd6P\xcb\xe3x\x17\x00\xbfV\x01@FJ\x9aNl\xe7\xd1{&`\xfbw\xd2\xf8(x\xd8\f,\u05c7\xa8H\x19\x98\x19\xb34\xfa(\x88\xb3\\g\xe9\xa1\n\x80}\t\xec\v\x0f\x1f\xca\xd2\xf8OY\x12\x9d\a\xf0\xe7\x85U/\xf7}\xfff\xd7\x01K\xab\x82\xa7\xa1\xbcM\xbb\xdf6\x1a\xe3\u05fb\x0e!\xd2Oq\x1co^\x01\xf65\x14\xfb\xc2p\x14\n\u06e6\xbc\xbf\x92\xd2WfOw\x1dam\x06\x1e\x94\xa7\xd19\xaes\x94\t\x89\xf2mU\\\xc1\x9eP\x01@\x86\rI/\x8e\xe3Mjf\x9b\x13x\x92\alA\xe3\x0e\x00v\x04\xb1#\xd6\xf8e\u0505Sd\xfdj\x8d\xf0+\x9d4~\x1f\x81'\xba\xce\xd2\x0f\x06l\n\xe0\x95\x80\xbd\xd2c\x17Y\x12\xddG\xe2W0\\\xed\x19\u007fQm4\u007f\xa1-\u0566\U00051e43eC3\xcd\xfd\x97\xa1\xc0\xc9\xc9'\xe4\x9e\xf7\xa4\xa2\x82'y\xb0-Pp{\x98\xed\x00p'\x80O\x98z\x96nZ\x8c2\x92^\x9e\u01bb\xba\xce\xf1Xv \u0570.\xbf\xe9k\xb9\n\x00\xb2\xe8H\xd6\x10\xc7\x1bfUn\xe8\x15\u0730`eC\x000+\x02\x98\xf9\x00`\x05\x97\x02\xf0`V+\xcc\u01a6\x1fk\xc2P\x9fz.6\x00\x80\xa2@`\x86\u502d\x00\xb8\xb5\x82\u03b6\x84m\x05pk\x16\xb6\xb5\x19\x9e\n\xe2\x89y\x1a/\x83\aXa \f\x8fL\x19\xb2\x87\xafs\xb4Gz\xeb\xf6PIq\x8d\x0e\xfc\xc3\x0f=\xfc\x98.\x90\"\xfdP\r\xda\xff\xd1I\xfdS\x87u\x14\xc0\xe3\b\x00;\x00\x86\x03\x00\xc0\n O\xe34K\xa2\xdf\x02SE\x01tqM-\f\u007f;\xcc#\x05HZ\x9e\xc6;\xb8\xce1\x83\xa8\xea\x8f]\xee:\x84\f\x8f8\x8e7\xabY\xb1=\u0376\"lk\x0f\u070a\x05\xb6\x86a\xd3<\x8d7D\xd53+\x00\xa2X\xa3\r\xf2x\xed\x975\xef@\xd8T\x1bF7%d>\xba\u055d\xa0\xa9\xf62_\xc4v\x80\n\x00\xd2\x03Q\x14=\xb1Z\xc5^(\xb0\x17\x80\xbd\u0330\x17\xd8\u0740\x0f_\xdd\xec\x91k\x9f.x\"\x03\xc5l\xc5D;\x8e\xdfd\xc6s]g)\t\x1f\x98\xfa\xac\x03\x01x@\x9e\u019d,\x89n\x06\xecj\x18\xae6\xda\xd5U\u07ffjX\x8a\x02I\x92<\xa9j\xe5\\\x00\x90\xc0\xa5f\xd6v\x9dC\x06\x13W\xaf^\xdeiT\xf6\x06\xed\xe9 \xf6*\f{\x19\xb8)\xa7;\xf4\x06N\xf5\xeb\xd5v\x91\x92\xf0P<\x95zC\xca\xfc\x85\x9c\x98\xd8P\x05\x00\x993\x92~\xa7\x1d\xed_\xc0;\xcc\xc0\xc3@<\r\xc5\x1a\x9fF*L\x8a\f\x95F\x18\xfeO\x1eG\u07e7\xe1X\xd7YJ\xaa\n`G\x80;\x82x9\xc1\x87F\n\\K\xe0g\x1exQ\xd5o^nf\x89\xeb\xa0\xf3Q\xf3\x8a\xedX\xde\xc5R\xafv\x1d@\x06\a\xc9J\x1e\u01fb\x9b\xf10\x9a\x1d\x96\x03\a\x81\xd37\xc3L\xfd|)?\u00b6t\x1cA\x06\\^\xa9\x06\xecC\xd8;\xa7\n\x02\xf1\xe5\x06^\xc4\x02\xe7\u05db\u0341\xe9\xb8\x12\xb6\xb5\xeb\f3\xa2\xfd\xc6u\x04)7\x92\xb5v;~\xb6G\xbe4O\xe2#\xe1a\x99\xee\xa0\u02a0\xa2\xe1)z\xf7\xcaB\x10P\x01@fF\xd2\xeb\xa4\xe9\xbeD\xf1\xf2\xd9\x036\xd6-~\x19\x06\x06{\x8a\x86\xda\xcaBX\u015e\xacF\x9c<\x06\xc9z\x96\xb4N\xca\xd3\xe4F\xa2\xb8\x14\xc0k\x01\xaa\xf3/2\xe2|\xbf\xf9=\x03\xde\xef:\u01d0x2\xccN%\x8aK\xf34\xbe+K[\x1fm\xb7'\xb6w\x1dj]\xac\xbc\v@\xb6\x1a\x8d\xc6\x1d\xaeCHy\x90\xf4\xd24:6K\xa2+\xac\xf0\xae7\xf24\x00\x1b\xbb\xce%\xd2\v$\r\xe0\x93]\xe7\x90\xc1F`s\x15\x00\xe4a\xe4\xfd\xe3Y\x1a\xbf\xa9\x93\u01b7\x03\xf6\x15\x80\u06f9\xce$\"\xe5R\xf5\xc3\x0f\x01<\xc7u\x8e!\xb39ho\xb5\xa2rS\x96FWei\xf4Z\x92\x81\xebP\x8f\xb0\xcd]'\x98\xc1\xdde\x1e9!\x8bg\x8d\x1b\x177x\xc4\xf7\x00<\xc3u&\x91\x9e\x8b\xe3M\x00\x84\xaec\xc8`3\x16\x1a\x01 S\x17\xce\x97\x9e\xf06R\x01`\xc4\xe5I\xeb\xd0<\x8d\xaf\xa1\u067fB\x8b{\x89\xc8,\x98YR\xf3\xc3cI\xfc\xc0u\x96!\xb61\x81\xf7\xe7~\xe3\xeev\x1a\x9f\xc9U\xab6p\x96\xc4\xe0\xbe\b\xb1\x0e\x06\xdc\xe3:\x83\xb8\x93E\xd1\xd3\xf24\xbe\x14\xb0\xaf\xb0\xbc\xd3TDz\xc6*\\\xee:\x83\f\x03\x06*\x00\x8c\xa88\x8e7\xcb\xe3\u8ec4\xfd\x04\xc0N\xae\xf3\x88\xc8`1\xb3v=\b\x8f'\xf0c\xd7Y\x86\x1b\u01cd<-\xaf\xd7n\u03d3\xe8]$\x1b\x0eB,up\xce\xc7E\xe0^\xd7\x19d\xf1\x91\u007f]\x92%\xd1Y\xf0\xf0k\x00\xfb\xb9\xce#\xb2X\x8a\xc2sW\b\x96\xe1A\x84*\x00\x8c\xa0Q\xad\xcf\u01df?R\x05\x80\x11@\xb2\xd9I\xe2\xef\x82\xfc8\x80\xba\xeb<\"\xaeXQ\x94\xf7\xf3X\x06\x065\x05`4$I\xb2E^\xc1\xcf\x01<\xddu\x16\x11\x19^\xb50\xbc\xbc\xe6\xa7;\x03\xf8\x1c\x00m\xcf\xd6g\x046#\x8a\x8b\xa7Fv\xb1?\xd7\xf3\u056bK\xdb\xe0$=\x15\x00\x86\x1cW\xae\\\x96\xa7\xf1\xf94\x1c\xeb:\x8b\x88sV\u20ac\f\x0e\x83\x16\x01\x1cv\xed\xf6\xe4\x0eU\x14\xbf\x00l\x1b\xd7YDd\xf8\x99\xad\x98\xa8\a\xcd\xd7y\x86\xe7\x98\x16i[\fU\x03\xde\xd7i\xc7\xffC\xd2\xef\xf9\xd1\xcdJ9\xfc\u007fZ\xe1:\x80\xf4\x0f[\xad\x8d\xf3\xa0\xfeSh\xa1?\x91i\xa6~\x9b\xf4BCo\xa4!\x96E\u045eVx\x97\x12x\x92\xeb,\"2Z\xaa~\xf3\xc7U?\xddqz\x81\xc0\xd4u\x9eaG\xe2\xf9y\x9a\xfc\x90\xe4XO\x0f\xbcdIi\xd7u0+z_\xf0\x90R\x88\xe3x\xf3\xbc\x82KA\xec\xee:\x8bHi\x90\x1d\xd7\x11d8\xa8\x000\xa4\xd24\xdd\n\x1e~\b`\x85\xeb,\"2\x9a\xccVL4\xfc\xf0\x1d]x;\x00\xfc&4-\xa0\xcfxH\x9e\xc6\x17q\xf5\xea^\xee\x15\x9d\xf7\xf0X\xbde\x16\xb8\x8e \xbdG>\xb8\xb4\n\xfe@#\x17E\x1e\x8d\xf0J[\x90\x95\xc1\xa2\x02\xc0\x10\xe2\xc4\xc4\n\x8f\xdd\v\x00l\xec:\x8b\x88H\x10\x04w\u0583\xb1\x17\x83\xb6\x8f\x11\u07c7\n\x01\xfd\xb4w^\xaf\xfe\x80d\xaf:\xc7\xe5mp\x16*\x00\f\x1b\x92\xf5\xbb\x17\v\x03\x9a\x19\x01\xb4z\x90\xa9\xe7\xcc\xd8t\x9dAz+O\xe3\x8f\x03\xd8\xdfu\x0e\x91Rb\x89\v\xb22PT\x00\x182\x9d4~\x8f\x01\xcfv\x9dCDd&\x8d\xc6\xf8\xf5\xf5 <\xa9\vo\x1b\xc2\xce$\xf0g\u05d9\x86\r\x89\x17fi\xfc\xa1\x1e\x1d\xee\xc1\x1e\x1d\xa7\xa7Hl\xea:\x83\xf4N;\x8e_\f\xe0\xf5\xaes\x88\x94\x15\xa1\xadO\xa57T\x00\x18\"Y\x14\xedE\xe0t\xd79\x86L\x17\xc4u\xaeC\x88\f\xa3 \b\xeel\x04\xe1;\xeb~\xf8d\xd2^H\xe0\x02he\xf7\x9e1\xe0\x1dy\xd2:\xb4\a\a*e\x01\xc0z\x1e0A\xd2V\x01\xe8z^1\x01Vr\x16E\x8b\u0562]\xcf\xed\x014\x9b\u007fU\a_d\xf8M\x8f\x10\xb8l\xfa\v\xc0\xd4\xe2\xa8Y\xd6\xda\xd6\n\xdb\x13\u011e0\xdb\x13\xc0\xee\x18\x8e\xcf\xcc9+\xe0\xbd\r\xc0\x9c\v\x00y\xe1\xddT\xb5r\x0e\x01\x00\xb1\x9b\xeb\b2?Y\x92<\xcf\fOq\x9d\xa3\a\xba\x00\xee$p\x8b\x01\u007f\xa1\xd9} \x13\x8f|\xb8sNxmx|Lg\x9d\x85\xad\x06Px^\xb1\x12d\xc1\xc2[\x8d\x1a;\x9d\x8e\xf7@\x10\x04\x0f\x98\x99\xd6>\x91\xb5\u061d\x00U\x00\x90\x05Q\x01`\x80MW\xcf\au\xcf\xdc\u0508\v\xe8\xd9E\xf0\x8aKj\xb5\xe6\x8d\uaa0bH/M\u007f\xa6\xdc0\xfdu6\x00\x90\xacdYk;\x14\xb6\x87\xd1\xf6\x81\x87\xfd@\xec\x82\x11\x98>`\xc0\x91I\x92l\x19\x04\xc1\x9dsy]\x18\x86\u007f\xc8\xe2h\x15\fe\x9co\xffL\xd7\x01d~\xcc\xf0\x06\xd7\x19\xe6\xa9\v\xd8\u03cc\u0145\x80\xf7\xf3j\x10\\kf\xa9\xebP2*x\xa7\xeb\x04\x8fB\xac\xa2gg\xb9\x8e!s\xa3\x02\xc0\x00\ubd23\xc3\x00\xdb\xdcu\x8e91\\\r\xf2S5?\xf9\x96\xd9F\x93\xae\xe3\x88\xc8h1\xb3.\x80\x1b\xa7\xbf\xbe\x0e\x00\xe4\xfd\xe3\x9dv\xf0L\xd0\xf6-\x80}\r\xb6\x0f\xc0q\xa7A\xfb\xc3\xf3P\x9c\x02`\xee\u00ee\r7\x01\u0627\xe7\x89\x16ngF\u0466\xd3SBd@$I\xf2\x14\xa08\xc8u\x8e9\xba\x15f\x9f\xae\xe5\xddo\xd8\xf8\xf8\xfd\xae\xc3\xc8h\xb2\xa9\xd1&\xe5a\x18\xab7\x82\x0fj:\xca`Q\x01`\x80\x91\xf6b\xd7\x19f\xcd\xf0\x1b\x03O\xab\xf9c\x17\xb8\x8e\"\"\xb2\xa6\xe9b\xe4\x85\xd3_ Y\uf92d\xfdi\x95\xa3A<\a\xe0\xf6n\x13\xf6\x8e\x01'\x91|\x8f\u065c\xc7\xf4_\x87r\x16\x00,\xf3x(\x80\xaf\xb9\x0e\"\xb3WEq\"Q\u0485%\x1e\xebN\x82\xa7\xd7\xfd\xe6\u007f\x99Y\xe1:\x8c\x8c\xb6\x82v\xd3\xdc?\xbe\xfb\xaa\xdaI\u04e7\x01\xf8\x85\xeb 2{\xda\x06p@\x91\xac\x01x\xbe\xeb\x1c\xb3\x90\x19\xf8\xceZ#|\xba:\xff\"2\b\xcc,\xab\x05\xe3\x17\xd7\xfd\xf0m\xf5 \u0721\xb0\xcaV0{#\xc0\x9f\x03%]\x0f\u007f\xf66\u03f2h\x97\xb9\xbf\x8cW\xf6>Jo\x18\xecP\xd7\x19dnh8\xdeu\x86Y \x88O\xd7\xfcp\xa7F0\xf6uu\xfe\xa5\f\xe8u~\xeb:\xc3c\xb0\xfb\f\xd7\x11dnT\x00\x18P\x9d4\xdd\x17\xc0\x12\xd79\x1e\xc7_\r\xde\x11\xb5`\xec\xcc\xe9a\xb7\"\"\x03\xc7\xf7\xfd\xdb\xeb~\xf8\xe9z0v`a\x95\xedi\xf6a\x00\xf7\xb9\xce5_^\x17G\xcd\xf55\xf4\xca[\x00\x00\xf0\x9c\u98b8\f\x00\xb6Z\x9b\f\xc0\xe2\x8dm\x82/\xaf\x87\xcd7jh\xb3\x94I\xa31~+\x80\xc4u\x8eG\xf1l?\xd7\x11dnT\x00\x18P\x05\x8a\xc3]gx\x1c\xf7\x15\xd6\u076f\x16\x04\x97\xb8\x0e\xd2\x03\x9a*#\"\x00\x00\xdf\xf7on\xf8\xe1;j~\xb89i'\x00\xb8\xcau\xa6\xb9\xa2y\u03de\xebk\xea\xf5\xb1\u07c3X\u054f<=\xb0Q\xb7\x1d\x1f\xe1:\x84\xccN^\xc1\xe1(\xf7\xf0\xff\xd4P<\xbb\x11\x8c}\xddu\x90\x1eP\xfbe\u0218Y\x17\x86\x1b]\xe7X\x13\x89\xc3I6\\\xe7\x90\xd9S\x01`@\x19x\x80\xeb\f\ub462\xc0\u047e\xbf\xe4\xf7\xae\x83\xf4Ba6\x8c\x8b\x81\x89\xc8\x02\x98Y\xd6\b\xc3sk~\xb87=\x1c\a\xe0V\u05d9f\x8f{\x91\x9c\u04ee\afV\x18pi\xbf\x12-TA\xbe\xd4u\x06\x99-+s\xfb\x85\xa4\xbd\xac\x16\x8c\xff\xccu\x90^0\x1b\xca\xc5L\x85\xb8\xc6u\x84\xb5\x8cu\xda\u0473\\\x87\x90\xd9S\x01`\x00M5\xdclO\xd79fd\xf6\xf6z\xb3y\xb5\xeb\x18\xbdbd\u0667Z\x88\x88#f\xc6F\xa3\xf9\u075a\x1f\xeeJ\u0619\x00\x06a\x9ep3\xcbZ\xdb\xce\xf5E\xf4\xec\xc2~\x84\xe9\r{\x1ey\xbf:;\x83\x80\xd8\xdbu\x84\x19\x11\xff\xde\b\xc3\xffu\x1d\xa3W\x8c\xa6\xf6\xcbP\xe2e\xae\x13\xac\x8d\x05\x8eq\x9dAfO\x05\x80\x01\x94e\xad\x1d\x004]\xe7X'\u00f5\xb5F\xf0\x19\xd71z\u0248M]g\x10\x91r3\xb3\xa4\x11\x84\xef\xf4\f\xc7\x02X\xed:\xcf\xe3*l\x8f\xb9\xbe\x84\u05bd\xa8\x1fQz$\xcc\xdb\xcdW\xb9\x0e!\xebG2\x80a'\xd79f\xf0\x97Z\x90\xbe\xdbu\x88^*<\xb5_\x86Qa\xd5\xd2\x15\x00`\xf6\"\xad\xc528T\x00\x18D\xddJi\xb7\xa4\xf2\x80\xf7\x0e\xdbJ\xb94\xec\xe0:\x83\x88\f\x86\xaa\xdf\xfc\x11hG\x02\x98p\x9de\xfdl\u7e7e\xa2\xd1\x18\xbf\x11\xc0=}\b\xd3\x1b\xe4[Hj\xces\x89eY\xb45J:/\xdd\xc8\u007f5[Q\xf2\xdf\xdb9\"\xd5~\x19B\xbe\xef\xdfJ\xe0O\xaes\xace\xe3,\x8b\x8fv\x1dBfG\x05\x80\x01\xe4Y\xb1\x8d\xeb\f3\xb8\xa3\xd2\b\u007f\xe4:D/\x91\xf4\x01<\xc5u\x0e\x11\x19\x1c\xf50\xbc\xb20\xbc\f%\xde2\xd0`O\x9a\xd7\v\xc9o\xf78J/m\x91\xa5\u044b\\\x87\x90\xf5\xe8zem\xbf$\u056c\xf3E\xd7!z\u0360\x1b\x18\xc3\xca3\xfc\xc2u\x86\xb5y]\xbc\xdau\x06\x99\x9dQ/\x00\x94y\x15\xda\x19\x11V\xce\x0e\xa9\xf1;\xc3v\xf7\xbf\x93\xa6{\x03\x98\xd3bY\"\"\xbe\xdf\xfc>\x80\xaf\xb8\u03b1\x1e\x9b\xcd\xe7Ef\xa5.\x00\xc0`\xa7\xcdu\x81\xc3aA\xde?\xdeN\xe3\u007f\x89\xa2\u826e\xb3\xcc\xc4C\xf1T\xd7\x19\u0585\xc0Om\u0672\x95\xaes\xf4\x12[\xadM\xa0\x1b\x18C\x8b\xc4y\xae3\xac\x8d\x86\xa3\xd3tb;\xd79\xe4\xf1\x8dv\x01\xc0\xac\x9c\xf3\xe8\x1f\x87\x11\x1b\xbb\u03b0.\x1e\xecb\xd7\x19z\xad@\xa1\xad\xa5Dz\x88d3K\xe3S99\xf9\x04\xd7Y\xfa\xad\xb0\u0287\x00t]\xe7\x98\xc1\xbc\n\x00U\u007f\xecR\x00\xf7\xf78K/\ud4b7\xe3S\\\x87p!K\xc3w\x18\xf9\xf6\x9a\x87\u06f2\xb4\xf51\xb6Z\xa5k+\x14\x9eW\xca\xdf{\x8fV\xe6\xf5-\xe6%\xaf\xe0\b\f\xe8\x8d.y|\xb5.\u007f\x84\xf2\x8d2\xabx\xac\xbc\xd3u\x88\xb2H\xd3t\x1b\x92\xa5\xeck\x972\xd4b\x19\xd4\xd5\xddi(\xe5\x054\xa7w\xbd\xeb\f\xbdf\x869\xef\x97-\"\x8f\u0155+\x97\xe5Itz\x9e\xc6w\x80\xfcD^\xf5>\xe8:S\xbf\xf9\xbe\u007f\x1b\x80+\\\xe7X7n8\x9fW\x99Y\x17\xc49\xbdN\xd3S\xc4?qbb\x85\xeb\x18\x8b)\x8e\xe3\xcd\rx\xf3\xf4_}\xd0\u079cW\xec\xf6,n}b\xfaNp)\x18Y\xca\xf6\v\xbc\xe2\x06\xd7\x11z\xcf;\xd2u\x02\xe9\x1f\x1b\x1b\xfb3\x802\xee\xb8\xf5\xd24MK9\xd2g11\x8a6\xf5\u063d\xefW\u04fe\u043b(}\xe1\x01\xdeW\x87}*\x00W\xad\u0680(\xbe\x8a\xd9\xcd\xf5^b\xc0{\xf3\xa0~{\x9eD\xa7\x93\xf7/\xfa(H\x83\x95\xb1\xfd2THz\xf8\xff\xed\xddi\xa0\x1cU\x9d6\xf0\xe7\xa9\xee\xda\xfb\x86\x84}\x13P0\b\x01\x14Y\a\xd9\x15\xc4u@\x05A\x11ePTF\x84\xc1\x8dyQ\x84\x81\xd7\x11\xb7\x17Gp\xc1\x19\x10\x18eXD\xd4q\x14Y\x05q\x04A!a\x93\xb0G\t\b![wUuUw=\xef\x87{\xc1\x80I\xb8Kw\x9f\xea\x9b\xf3\xfb\x06t\x9f\xf3\u0710\xdb}\xea,\xff#|\xcct\x0e\xab\xff\x82 \x98\x0f\xe0v\xd39V\xa6\x94\u039e\xee\x13\xfc+3\xba{X_\\\xc5\u007f\xdeJp\xae\u0353\xd69&>\u007fW4\xa8#\x00\xed\x01\xf53!\x12\x86\xb2R%\xabytcZ\xfd\x92\xe7\x99\xffITt\xab\xa2eUQ\x9e$\xbb\x16Y\xebG,\x9d\xb9\x80\u0787\xf1\xde\xf5M\x1c\xdfN\x9bG\xf67\x9d9\x14\xaa\xfc\x00:\xe9\xc9y\xb7\xdd\xfe\x1e\x80f\xef\xa2\xf4\x9e\x80M:^\xed\xbb\x93\xdd\xe90\f:\x81{\x1e\x80\x97M\xe8M\xc2,\x01g\x14Y\xf4H\x916O\x964\xc0\x82\xc8e\x15\xc7/p\x1cg\u068ca\x8a\xac\xf5^\x00sL\xe7\xb0\x06\x83\xe2%\xa63\xac\x1cg\x17Y\xf25\xd3)\x06IZ4\x83\xa5s\x19\x80`5/s@\xfcc\x9eE\u007fl'\xc9!\x83\xca\xf6\xb7!\x06\xa3\xaa+ [Kj\x98\x0e1\t-\xd3\x01V\xa26]VZ\xd4ln\xb8B1%\u02f2V\xa3H\x9b\xaf\xcf\xd3\xe4ZP\xb7J8\x18\x93\xf8^!x^\x91\xa6{\xf5!\x9eq\"\xb77\x9da\x15\x12\x92\xc5d\xdf\xccY\xb3\x96@\xb8\xa8\x97\x81\xfaA\xc2!y\x96\x9cn:G?\xe4i\xebC\x12\xde5\x85&\xd6\x11\xf8\xafE\x96\xd2N\x92CM\x87\x18\x04I\xf5\"\v\xae\x00\xb0\xedx^O`#RW\xe6i\xf3\x12\x13\xb7\"\rd\x02\x80\u055d\x00\xa8w\u06ad\xddM\x87\x98\x84J~\x81\x16\xb5\u06b4\xb8o\xb6S\xe79\x00\x86qb\u0232\x06B\x12\u06ed\xd6\xc1y\u06baU\u0d40^?\xc5&C\xa9\xfcI\x9e7_\u0753\x80\x15!\xc9!0\xd5?\x9b\xbe \xb0d\xaam\xa8Go\xb3\x12\x00\x00 \x00IDAT\xd6\xfd\x06*z\xc4oE\x04>\x97g\xad\x0f\x9b\xce\xd1Ky\xab\xb5\v\x80\xb3{\xd4\u073a\"\xbf\x98g\u0243y\x96|\\\xd2\xeaV\xaf\xa6\xc4a5\xc7/%\xcbi1~\u0273\xe4T\x00k|\x05\xf65\t\xe3x!\xa0\x1f\x99\u03b1*\xa4\xfe\xbd\xddn\xee`:G?Ib\x91\xa5\xe7\x038`\xe2\xef\xe6\xe1E\u07797O\x9bG\xf5<\xd8j\fd\x02@\u055d\x00\x80\x80\xb7\x98\xce0\t\x95\xfc\x02\x85\x83\xa1\x1f\xbc\xb7\x93\xe4p\t\xef4\x9d\u00f2\xaaHR=O\x9b\xef+\xb2d\x1e\x1d\xfc\b\xc0\xae=k\x9c\x98\x89.\xaf\x9bN7\x03t\u06ad\x03\x05lb:\xc7\xca\bX:\xd56|\u007f\xc6\xfd$\xae\xeaE\x9e\xbe\x13\xcem'\xc9;L\xc7\xe8\x85,\xcb^\x01\a\xff\x8d\x1e\x17y#\xb0\x11\xa4\xafw\xb2d~\x9e\xb5>*i\xf25\"VA\xaa\xe8\xf8\x85\xce\xd0?\xa0\xe4\xad\u058e\x04>e:\x875xD\xed\\\xd3\x19Vc\x86S\xf2\xe7i\x9ana:H?Hb\x91&_\x1f;\xfa8Y\xeb\x00\xbc\xb0\x9d\xb6\xaeN\xd3t \x93\x91\x03:\x02\xa0\x85\x83\xe9g\xe2(\xbeKR\xcdt\x8e\t\xaa\xea\xb9\xcb=L\a\x98\x8a,\xcb^IG\xdf4\x9d\u00f2\xaaFR\x90g\xad\x8f\x16Y\xf2\x00\xc0\x8b\u043f\xf3\xa5\xeb\xc0\xc1uE\u059c\xc4,z\xb5H\xa2\xc4\n_E\xa7\xa7{\xd2JGg`8\x8a\xc0\xd6H]\x96\xa7\xad\x0f\x99\x0e2\x15i\x9an\xe6\xa8{\r\x80\xbem\x19\x15\xb0)\x84o\x16\xa3;\x02N\xe8\xe9\xd5U\xaa\xe6\xf8\x85\xd2\xebLg\x98\n-]\xba6\x1c]\n\xc05\x9d\xc5\x1a<7\fo\x020\xcft\x8eU\x11\xb0q\r\u076b\x93$\xa9\xe4\x84\xf8dIr\x8a,\xf96\x88\xe3{\xd1\x1e\x81\x03k(\xe7\xe5I\xf2O\xfd~6\x1dT\r\x80\xaa^\x83\x04\x01\x9b\xe6i:T+\xbed5\xbf@\x01\xbce\b'S\x00\x00Z\xbcx\xa6\xa3\xf2'\xb6\xf0\x9fe\xfd\x95\xa4F\x9e%'t\xb2\xe4A\b\xdf\x040\x88\x99\xe9\x19\x12\u007f^$\xcd\xcf\f\xa0\xaf\xbe)\xda\xc9q\x00\xfe\xcet\x8eU\xe3=\xbdh\xc5k4\xee\xa4*y\x17\xf5\xca\xd4\x00|\xa7H\x9b\xffl:\xc8ddY6\xbb\x86\xf2&\fn\x8b\xf7\xcb \x9d]d\u027dy\xda\xfc\x80\xa4\xf1\x15\xf6\\\r9\xac\xea\xf8ew5\x9b\x1b\x98\x0e1\x19\x92\xea\x85\xe7^\x06\U000159b3X&\xa9\xe2\x05\xf78\xbbN\u0752e\u02c6\xb2\x00\xfb\x8bI\x8a:\xed\xe4R\x00\xc7\xf6\xb8\xe9\x18\xd4\u05ca,\xf9\xdf~\x1e\x9d\x18\xcc\x11\x00:\u007f\x1aD?\x93E\xeas\xbd\xf8b\x1b\x14\x95X`:\xc3*l\xd0m'\a\x9a\x0e1Q\x92\xe2\"\xf0\u007f\x04\xe8U\xa6\xb3XV\x15h\u0672u\xdbi\xeb\x8c\"M\x16@:\xdb\xc06\xf6\x9a\xc8/\x16Y\xebJ-[\xb6\xee\x80\xfb\x9e\xb2\"I^\a\xe1\u02e6s\xac\x16qw\xaf\x9aR]\x9f\xc3\x10\xd4\x02\x18C\x81_\xc8\xd3\xd6\xf9\xc3T\x04\xb8H\xd3}\x1cu\xff\x17\xc0\xe6\x06\xba\u007f\x05\xc0\v\x8a\xacuO;m\x1e)i\xd2cGBU\x1d\xbf\xd4\n\xc79\xc2t\x88\x89\x92T+\xb2\xe4?zP\x87\xc5\x1arn\x10\u007f\x1f\xc0#\xa6s\xbc\x84\xcd\x1d\xd5n.\xd2tO\xd3A\xa6\"I\x92M\x8bvr\xd3\x14\x8b\xb0\xbe\x94]X\xf2\xf6v\xda:\xb3\x1fuY\x06S\x04\xb0\xac\xee\x0e\x801\xdbu\xd2\xd6I\xa6C\x8c\x9b\xc3\aMGX\x95R\x1c\xaa\xf3g\x92\xe2\"K\u007f\nh_\xd3Y,\u02f4$I^\x96'\u0373\v\xb7\xf6(\x81\u03c2\x98i2\x8f\x84Cr\xb76\xb7\x9d$C\xb3K+O\x92\xddE\xfd\x04\x15\xbf\x1a\x95rz\xb6]\xd4\xf3\x1aw\x01\u057f\x11\xe0E\x8e.\xb2dn\x91$\x95>\xba&\x89y\x96\x9c \x94\xbf\x04\xb0\xb6\xd94\x9cM\xf0\xe2\"K\xee\xce\xd3\xe6Q\x93\xd9\xf1G\xa8\xb2\xe3\x17P'\xf5\xa3\xeeA\xbf\x8c=\xfc\x9f\x0f`\xa0\xc5\u00ecj\"Y\x808\xcbt\x8eqXO(oh\xa7\xad\u04e62\x99hJ\xbb\xd5:\xb8N\xdd\ta\xa7\x01t\xe7\x128\xa5\u0212\xbb\x8bt\xf9\xfe\xbdlxPE\x00+\xbd\x03\x00\x00D\x9eY\xa4\xe9\u07a6s\x8c\x87\x03\xcd7\x9da\u0574_\x96\xb5\xdef:\xc5x$I\xb2I\x91%\xd7\x01\xda\xcft\x16\xcb2)\u02f2\xd9y\xda\xfa\x8f:\xf5 \xc8\x13\x00\f\xf0^\xf0\xd5\x1b\xbb*\xe7\x8av\xda\xfaE\xbb\xbd|\x1b\xd3yV\xa7\x9d6\x8f\x04u=\x8c?\xa8\xbd\xa4\xb2\x9ee==/\xda\x11?\a \xe9e\x9b\x03\xf0rQ7\xb6\xd3\xd6\xe9\x92*\xf3w\xfe9Y\x96\xbd\"\u03d2_@:\x1b@\x95\x1eL\xb7\x01xa\x91%\u007fh'\xc9;$q\xbco\xec\xa2^\xe1\xf1\v^\xd6I[\x1f7\x1db<\xa4\xa7G:\xed\xe4\n\u0607\u007fk\x05\xae\x1f}\x0f\xc0\xe3\xa6s\x8cC\x9d\xc0\xe7\x8b,\xb9:\u02f2\xadL\x87\x19\x0f-[\xb6n\x9e\xb6.\x18+\x80<\xe8k\u03f7\x14\x9ck\xf3\xb4\xf5-\xe9\u0675z\xd1\xe0`f^j\u075e\x9c5\xec3W(\u007fR\xf5\xd5\x00\x00\xe8\xa0V\xe5/P8\xc29Z\xb6l\u043f\x1c\x13R\xa4\xe9\x9e5\xeav\x00\xbb\x99\xcebY\xa6\xe4\xad\u058ey\u06bc\xd4Q\xf7>\x00\xff\x80j=d\xbc\x00\x817\xb2t\xe6\xe5irQ\x96e\xb3M\xe7YQ\xab\xd5\xda8O\x9b? x1*\xbe\xf2?\xe66\u039a5\xe5k\x00W\x14E\u045f\x88\xa1X}z1\x97\xc0\xa9y\x96\xcc\xcf\xd3\u0587\xaaP\xc7FR\xa3H[\xa7:\xea\xdeM\xa0\xca\xc7\xea\xb6'\xf5\u00e2\x9d\xdc\xd1\xc9Z\xe3\xbaQ\xc9\xf7\xfd\xc7\x00\xe4}\xce5i\"O\xab\xfa\x19\xe5,\xcbf\x17Yt\xab\x84\x83Mg\xb1\xaa\x85d[\xd0)\xa6sL\xc0\x1b\x1cu\xe7\x8d\xed\x06\xa8\xe4w\xa7$/\xcfZ\x1f)\xdc\xda\xfd\x00>`0\n\x01|\xa4\x93\xf9\xf7\xb4\u06ed\xbf\x9fjc\x03\x99\x00\xf0\xbc\xc6\x03\xa8\xea\xd5u/\xb4\x96\xa8\xeb\xf2,9\xc1t\x90\xd5\xf1}\xffQ\x00\x85\xe1\x18\xab\xb3Y\xe1\xd6/\xefi\xe5\xe0\x1e\x91\xe4\xb7\xd3\u0599By=\x81\rM\xe7\xb1,\x13\xb2,{e;m\xfd\x0f\x1c\xdc\x01\xf00\f\xae \xecT\xd5\x00\xbd\xcfQ\xf7\xbev\xda\xfa\xef\"k\xbe\xd1\xe4\x16B-_\xbe~;m\x9d\xe1:\xf8#\xc0\xa19?L\xf4\xa7h_=\x88\xce\x02\xf4@?\xda\xee7\x02\x1b\x018\xaf\u0212yy\xd6\xfa\x88\xf4\xf4\u02203h\xf1\xe2\x99E\xd2\xfcd\x91%\x0f\v8\x1d\xc31\x99\x04\b;v5\xbe[\x80Hv\x01>\xdc\xefHS\x10;r~\xa2\xa5K+\xb7\x8bg\xf48H\xeb8G\xe5\xed\x00*\xbd\x1b\xca2\xc7\x1b\xad\x05\xf0;\xd39& \xf0\xf9\x8f\xc0F\"\xbfRd\u0263y\xd6\xfcj\xbb\xdd\xdc\xdeD\x8ev{\xf96\xed\xb4\xf5\x85\"K\x16\x00\xf8.\x06s\xfb\u0444I8\xb4\xa8\xf3\xde\xe3\xbbJ{@\u0623N!O[\x0f\x93\xb8\xb3\x14\xee'\xb9P%\x9e\xaa9J\x04\xb5\x01\xa0$ct\u9065O:kK\u0690\xc0\xc6\x02\xd6'\xb4U\x91%[\x82pz1'W\x83n(\x81a\xa8\xb8\xbf\rK\xde\xd6N[\xff\xcf\v\x92\u007f%\xd7[>\x88N%\xd5\xf2$y\x1b\x1c|\x94%\x0e\xd0\xf0\xaetZV_\x94\xac}\xc5Q\xf7\x83\x18\xbd\x1b}\xbaX\a\xe0\xe1\x90\x0e\x87\x03\x14YR\xe4i\xf3\x11\x8a\u007f\x14\xf4\b\u027f\bX(qy\xcdQ*(\x03\x00\x82n\xb7d\x83,c\n\xeb\xc9q6 \xb4\x85\x80-\x8b,\x99M0\x1am~\xf8?F\b\\\xd0\xef>\xdc ;\xa1\u0202\xfd`\xe6\u02ba~Xo\xec\x88\xc7\x115\x94(\xb2\xa4\x99g\xad?B\xbc\x8f\xd0\x03\"\x97@eSr\x9a\x8eS.\x06\xfe:\x1e\xa0\xa3\xf5$l\xc0\u046b4\xb7\x86\xb0\x1dP\xce|\xee\xef\xd2\xf0\xff\x8d\xc2\x05n82\xa1\a\xfa\x92\xb5\x1b\x1cu\xfb\x95\xa7\x976\x90\xf8\x8b{l\xa7\xf8j\r\xecGM\xd3t\xb3\x1a\xca\xc7\x06\xd5\xdf\xd0)\xb1\x8b\x17\u01f7\x8f\xf7\xe5\x92\x1aE\x96<\x8b\xe1\xfabX*\xf2\xbb`\xf7|\xdf\x1f\xb9\xaf\u05cdK\xaaw\xb2\xe6\x9e\"\xdfF\xf10\x01\x9b\xf6\xba\x8f\x8a\xb8\xd6\v\u3fafJ\x14i\xeb\x14\x01g\xf6\xbb\x9fIx\xd6\v\u305d\xc5R\xab\xb5Q\xe1\xe0\x89A\xf57\x11rp\xb0\xef\xc7?\x9e\xec\xfb\xf3\xb4u!l\x15\xe95I\xdb\xedjs6\x1aO\xf5\xbb\xa3\"]\xbe\x9f\xe0\\\x8b\xe1\xa9/aM\x10\x81?\xd7\xf3\xce\x0e\\k\xadg'\xfa\xdep\xb0\xf1\u8a9c\x1d\xc1X\xbd\u11cd\x1f\x14Y\xeb\x9d\x12\xdea:K\xffh\x04\xc0\xb6\xa3\xbf6+_\xd7\x1e\u0685\xfd\x89\x12\xe6\xbaA\xf8\x9d\xf1\xbct\x90G\x00\x00\xf2\u007f \xd9\t\x80^!/\x854L\x13\x00+\x9a\x03q\x0e\x85\x93F\x8fW$\xcbA=$\xe1\t\x02OCh\xcaas\ucd644\x13\x80Oam\x01\x9b\x83\u063c\x00\xfez\x17\xa6\xfd\xbe\xb4\xac\tc\xa3\xf1T\x9e%\x9f\x87\xf4u\xd3Y\xac\x01(q\xee \xbb\xf3\xfc\xf0\xb3E\xd6\xfa;{vy\xfa\x11\xf95/\x88\xaf\x9b\xec\xfbI]*q\x98&\x00V\xb49\x88\xe3\b\x1eGuQdI\x96\xa7\xad\a\x05\xf7bJk\x01\xf0I\u0312\xb0)\x80-\x8a,Y\xf7\xafO%\xb4C\x18\xabo\xeai~L\x11x;a\xb8v\xdcX\x13W@\xf8\a\x92\xed\xf1\xbcx\xa0\x13\x00T\xf9s\x81U\u071e3\x94\u073c\xf3\xfd\u00ad}\t@\xe5\xae\u06db8\x8d@x\r\x81\xd7\x00\x00\bP\u007f\xfb\x958\xb5\xd2K\x96e\xbd\x98\xeb\x87\xe7\x16\xed\xe4\xfd\x10^k:\x8b\xd5?\x14~\xea\xc6\xf1@\xaf\x86\"\xd9Q\xb3yX^\xc3\x1f\u01ae\u0673\xa6\x87\xbb=?\xfc\xdcT\x1a\xa8\xfb\xf15cU\xb6\xfb\xb2\x1d|\xc0\x02\x00\xdb\x11\xd8\xee\xb9\u0548\x95\x8e_\xecS\xbee\x00g\xcdZR\xa4\xe9QBy=\xa6W\xcd\x1fk\x05\x04Nw\xe3x\xdc\xf5\xf6\x06z6\xaf\x1e\xc47\x03xz\x90}Ng\x9c1c\x11\u065f\xfb\x9c-\xcbZ3\x90\uc5a8\x1d1z\x8e\u039a\xa6\xf2\xaeS\xfb\xa4\x89\x8e\xd9h<\xe5\xc09\f\xc0\xb8V%\xac\xcak\xca)\x0f\x9bX\xd5\xff\xbfE\xb2\x14\xf0\x9f\xbd\neY\u05aa\xb9ax\x13\xa1\u03da\xcea\xf5\xcd5\xf5 \xfa\xe2D\xde0\xd0\t\x00\x92\xb9\xc8iq\xf5TUt\xa7\xc9U^\xd6Dh\xfa\x171\xb1\x06*\b\x82\a$|\xd8t\x0e\xab?D\x9e\x1d\x04\xc1\x03\xa6\xfaw\xc3\xf0\u05c0\x8e5\u057f\xd53\x92xL\xaf\x8a\xf8\x8a\xb5\v`\x0f\xf0\xadQ\xb4&\x14a\xab\xa8z\x10\x9f\x05\xe8\x12\xd39\xac\x9e{\xdc-\xba\xef!9\xa1\xabU\x06^\x9dWp\xbe\r\xfb\x81\xdf3\xbe\x1f\xfd\x1c\xc0C\xa6sX\x03D\x0e\xe3]\xd1V\xc5\xf9Qt\t\xa6\xc5\xfd\xed\u058b<\xe5\xf9\xe9\xff5\x1d\xc2\v\x1b\x17\t\xf8\x82\xe9\x1c\xd6\xe4\t\xf8W?\x8a.\xebU{A\x10\xcc\x17pM\xaf\u06b3\x86Bd:\xc0\x9a\x8a\xa4\xdc \xfe \x88\u07db\xceb\xf5L\x86\x12\x87p\u018cg&\xfa\u0181O\x00\x04A\xf0\x10\xc0\x1b\a\xdd\xeft5z\u05e3\xfe\xc5t\x0ek\x80d\xbf@\xad\xfep\x83\xe8\x1f\x01\f\xf4\x9c\xb8\xd5Wr\x88\x0f\x92\xeb,3\x1d\x04\x00\xbc \xfa,\x80\xf3L\xe7\xb0&N\xc0/\xbd :\xb5\xd7\xed\xb2\xc4)\xb0\x8bBk\x92H\xb2\u055cL!\x99\xb8]\xbc\x15\xc0\xa3\xa6\xb3XS&A\x1f\xf4\xe2xR\x13:F\xee\xe7\x95\x06[\x89x\xbas\x83\xf8\xfb\x00z\xb2%\xcf\x1a\nv\a\x80\xd5\x17$\x13\xb7\xe8\xbe\x19\xe0\xfd\xa6\xb3X=@\x9d]\x0f\xe2\xca\u0509\x19]\x81\x8a\x8e#q\xb9\xe9,\u0584\xdc\xe3e\xf9\xbb'\xba\xc5t<\xbc8\xbe\x9d\xb2\xb5\x8c\xd6 \x0eF\x8b&Z\x860\x8e\x17\x96\xac\xbd\x01\xc0@\xae\x84\xb5\xfa\x83\u04a7\xfc\xb0\xf1\xfd\u027e\xdf\xc8\x04\x80\x17\x86W\x82\x18w\xa5Bk\xf5Hv%\x9ef:\x8750v\a\x80\xd57\x9c1\u364ep \x80\x05\xa6\xb3XS@\xdc\xe1\xfa\xf1?\x9b\x8e\xf1b$\xbbu?:R\xc0\xcfLg\xb1\xc6\xe5\xf1\x8ex\x10g\xcdZ\u04af\x0e\u029aN\x01P\xf6\xab}\xabb\x96/\xb7\x8b\x18\x86\x05A\xf0\x10J\xbc\x15\xc0\u0497|\xb1U9\"\xbf\xe4F\x8d\xafN\xa5\r#\x13\x00$E\xe8\x14\x13}OW^\x18^\x0e\xe07\xa6sX\x03\xd10\x1d\xc0\x9a\u07a2(Z Go\x050\xe1seV\x05\bKJ\u050e\x18\xef}\xc0\x83F2\xf7\x82\xe8\x1d$\xae4\x9d\xc5Z\xadEr\u0283\xa2(\xfaS?;\xf1\xfd\xc6<\x00\x17\xf5\xb3\x0f\xab:2\u05f5c\x98\n\xf0\xe2\xf8v\x88\aB\xe8\xdb\xe4\x9e\xd5\x17\xe7{~x\xf2T\x1b12\x01\x00\x00n\u0438\x1a\xe0u\xa6\xfa\x9fnH\xaad\xed}\x00\x9a\xa6\xb3X}\x17h\xf1\u2666CX\u04db\xef7\xe6\xca\xe9\xee\x05\xbb\x13`\u0624\xa4\xf3\xf7A\x10\xcc7\x1dduH\xe6u?z7\xa0KMg\xb1V*\xa1\xf8\xb6^U\xfc\u007f)n\xd0>\x11\xc0\xe3\x83\xe8\xcb2\xab&mh:\x835\u028b\xa2\xdb \xec\x0f`\x91\xe9,\u05b8|\xc7\r\xa2\x0f\x91\x9cr\xdd\x14c\x13\x00\x00\x80R\x9f\x06\xd01\x9aa\x1a\t\x82\xe0a\x90\xff\xc7t\x0e\xab\xff\U000a8fa9\xe9\f\xd6\xf4\xe7\xfb3\xee\xef\xc2\xd9\v\x90\xb1+\xe4\xac\t\xe9J<\xd2\r\u00dbL\a\x19\x0f\x92\x1d7\x88\x8f\x10\xf9%\xd3Y\xac\x17h\x11\xe5\xdb\xdc(\xfa\xdfAuH\xae\xbd\x94\xd41\xb0\x05\x01\xa7=\x01v\xfcR!^\x1c\xffAN\xb9\x0f\xecd\u007f\xb5\t\xe7\xbaA\xf4Q\x92=9.et\x02\xc0\x8b\xe3\xdf\v0~=\xd1t\xe2\xfa\xe19\x02~i:\x87\xd5_\x8e\xb8\x89\xe9\f\u059a!\f\xc3\xc7\xdc.\xf6\x06p\xbb\xe9,\xd6j\t\xd0\xd1~\x14\r\u0576z\x92\xf2\x83\xe83 O\x84=\a^\x05K)\x1e\xe0\x86#\xd7\x0f\xbac7h\\\v\u0ec3\xee\xd7\x1a,:\xb0\u35ca\xf1\xfd\x91{:\xe2\xeb\x00\xdcm:\x8b\xf57$\xe0t/\x8a?\u058b\x95\xff\xe7\x98\xdd\x01\x00\xc0\v\xa23\x01\xdcj:\xc7tAR^\x89\x0f\x00x\xcct\x96i\xe4\x1a@\x95\xdaN+\xd1\u03a0[\x03\xc3F\xe3)7\x88\xf6\x02\xf0=\xd3Y\xac\x95\xea\x008\xd6\v\x1b\x17\x9b\x0e2Y^\x10}]\xe2\xa1\x00\x97\x9b\u03b2\x06[\x84\x12\xfb\x0fr\xe5\xff\xc5\xdc :\x11\xc0oM\xf5?\r=\b\xf0\x06\xd3!V$\xd8\t\x80*\x8a\xa2h\x81\x9b\xe5{\xd9E\xc4J\xc9\x04\x1d\xe9\x87\xf1i\xbdn\xd8\xf8\x04\x00\u024e\x9c\xee\a\x00\xa4\xa6\xb3L\x17\x8c\xe3\x85r\xca7\xdb\xc2\x1e= ,\xe9\x88\u01d0\xbc\xc7t\x94\x15\xd1~\x81Z\x03F2\xf3\xc2\xf8h\x10\x1f\x06\x90\x9b\xcec=\xaf\xe5\x10\x87xa\xfc\uf983L\x95\x1fEW\xca\xe9\xeen\x8f\x9c\x18\xf1\x90\x9cr\xaf\xc9\xde)\xdd+$S\xb7\xe8\xbe\r\xc0\x83&sL\x13\x1d\x88\xef\x15q\x9b\xe9 +\xa2J\xbb\x80QQ\x9c5k\x89\x17D\aQ:\x19\xf68\x8eQ\x02\x16B\xdc\xd7\x0f\x1b?\xe8G\xfb\xc6'\x00\x80\xd1s\xa6%q8\x80\x9e\xdf1\xbb\xa6\xf2\xfd\x91{\xc9\xf2\x10\u0601\xfaT\x94\x8e\x83#\xa3(ZP\n\x03)\x844^v\x06\xdd2\xc5\v\xe2\xf3(\xee\x0f\xe0Q\xd3Y,<\x85\x12\xfb\u0583x\xda\u0723\xee\xfb#\xf7\xbaA\xbe\xab\xbd!`\x90t\xb3[tw\x1fT\xc1\xbf\x97\xc2\x193\x9e\x91S\xbe\x1d\xc4b\xd3Y\x86\x1aq\xa2\x17E\xb7Qe%\xfe\xbf\xae\xc0\x8e_*\x8c\xa4\u0728q\x96\xc4\xc3`\xaf\t4\u55ae\xb8\x8b\x17E}\xdb!_\x89\t\x00\x00\b\x82\xf8' \x8e7\x9dc:q\u00d1\x1b\x05\x1d\r\xa00\x9de\x18Q\xfat=\x88\xc7\xee\xaa\u05bdf\u04fc\x18\xb74\x9d\xc0Zs\xb9Qt\x8b\x1b$;\x00\x18\xfaU\xe7!6\xafdm\x0f/\x8e\xa7]m\x06r\xed\xa5n\x10\xbf\x13\xd0\xfbao\xb6\xe93]\xe2\x06\xf1\x81\x9c1\xa3RW~\xfa\xfe\xc8}\x94\xf3\xf7\x00\x96\x99\xce2\xa4\xbe\xeb\x05\xf1\xb9\x00\x80\x92\x95\x1a\xbf\u040e_\x86\x82\x1fEWt\xe1\xec\x00h(\x8a\xcaN\x13]\x91g\xb9A\xb4_\x14E\u007f\xeegG\x95\x99\x00\x00\x00/\x88\xbf\x05\xeak\xa6sL'~\xd8\xf8\x01\xa97\xc3\x0e\xa2&F\xfa\xba\x1b5\xbe\xfa\xfc?\xb2^\xa93\x89\x82\xb65\x9d\xc1Z\xb3\x91\xeb-\xf7\xc2\xf8C\xa4\x0e\"\xd0\xd7{\u00ad\x17\x10\x80\xf3\xdc \xda=\b\x82\x87M\x87\xe9'/l\\$\xa7\xbb\vl\x01\xca~HA|\xd4\v\x1b\xef!\x99\x99\x0e\xb32n\x18\xde,\xa7|\x1d\x81'Lg\x19&$\xaer\x83\xe8\xb8\xe7\xfe\u064d\xa2\xbb\x00$\x06#\xbd\x80\x80M\xb4d\xc9,\xd39\xac\x97\x16\x86\xe1\xe3n\x10\xefO\xe0T\xd8\x1d\xc5\xfd\xf6\x18\xe1\xec\xeb\a\xd1\xc9$\xfb\xbep[\xa9\t\x00\x00p\xfd\xf8S\x10\xce1\x9dc:q\x83\u01b5\x14\xdf\b\xe0Y\xd3Y\x86\x82\xf0\r7\x8c\xffi\xc5\u007f\x15\x04\xc1\x83\x04\xfa:\x1b7\x11\x046\xd2\u04a5k\x9b\xceaYn\u0438\xba\xde.v\x80\xf0\r\xd8k]\xfbJ\xc0BRo\xf2\xc2\xf8\xc3$+3\xa0\xef'\u07dfq\xbf\x1bD\xbb\x8d\u055e\xb0\x13\u067dq\xaf\x1c\xed\xee\x05\xf1\xb7M\ay)\xbe?rw\x97\xb5\xbd\x01L\xeb\u026e^\x11\xf0\xb3\xba\x1f\xbd\x9b\xe4\xf3\x9f\xc5$s\x80\x95*\xb6\xdd\xf1\xbcmLg\xb0\u0187d\xd7\r\xe33J\u05b6\x03\xf4+\xd3y\xa6\xa1\x12\xc0yn\x90\xed\xe0\x86\xe1\xaf\a\xd5i\xe5&\x00H\x96^\x14\x1fo\xaf\x04\xea-7\x8a~#\xa7\xdc\v\xa8\xd6Y\xf6\xaa!p\x9a\x17\xc5\x1f_\xd9U\x1b\xaa\xd86\xa8\x8e\xe7\xd9]\x00V%p\xe6\xcc\xc5^\x14\u007f\\N\xb9#\xc0\xebL\u765et\x99\xd7)_\xed\x06\x8d\xabM'\x194\x92\xa5\x17\xc4\u756c\xbdZ\xc0\xcfM\xe7\x19b%\x84s\xdc \xda\xd9\xf7\x1bsM\x87\x19\xaf \b\x1er\xbbz\x9d\u074a\xfc\x92.\xf2\x82\xe8\x90\xd1\a\xfe\x17\xaa\xda\xf8E\xb4\xbb\x18\x87M\x10\x04\xf3\xdd \xde\x1f\xe4\xf1\xb0\v\x8a\xbdA\u0701\x12\xbb\x8eN\xea\xaf3\xd0\xe3N\x95\x9b\x00x\xce\u0615@\x87\x01\xa8\xe4\u05b4a4Z\\)\xda\x19\xf6\x9e\u0755I\x01}\xc0\r\xe3\xd3W\xf9\n\xb2R3\x9fb9\xc7t\x06\xcbZ\x91\xef\x8f\xdc\xed\x85\xd1\x1b$\xbe\x13\xe0\xfd\xa6\xf3L\v\u011dD\xb9\x9f\x176\xde\u0351\x91\xa7M\xc71)\b\x82\x87\xfd0~3\xa9\x03`\ufade\xa8y\x14\xf7\xf2\xa2\xf8x\x92Cw\xeb\x12\x1b\x8d'\u01f6\"\u007f\x1ev\xa7\u044b\x95\x04Ns\x83\xe8\x03\xab\xda:\uc82c\xd4\xf8\x05\x94\x1d\xbf\f\xa1\xd1\xc9\xd8\xe8\x1c\xb7\xe8\u0386\xf0M\xd8\xdf\xc5I\x11\xf0$\x88\xe3\\?\xda\u034b\xe3;Ld\xa8\xec\x04\x00\x00\xf8Q\xf4C9\xda\r\xc2\xd0\xccTW\x1d\xc9\xc4\v\xe3c%\x1ef\xaf\t|\xdeC\xe8j\x0f/l\\\xb8\xba\x17\x15]\xfc\x14U\u0695R\xda\x19t\xab\x9a\xfc(\xba\xd2\r\xc29%\xf1v\x10w\x9a\xce3\xa4\x16\x81<\xd1\xf5\xa3\x9d\xddp\xe4F\xd3a\xaa\xc4\r\x1a\u05faA\xf4Z\x90\x1f\x17\xf0\xa4\xe9<\x15\x97P:\xd9\r\xa2\x9d\xdc(\xfa\x8d\xe90S1\xb6\x15\xf9_\bg?\x00\x8f\x9b\xceS\x11\u03d0z\x8b\x1b\u01a7\xafl\xe7\xe2s\xeaA\xe3\xd7\x00\x16\r0\xd7jI\xb4\xe3\x97!\xc6\x193\x16yQ\xfc\x8fr\xcaW\x93\xb8\x02\xf6\xca\xc0\xf1ZF\xe0T/\x88\xb6\xf2\x82\xf8[$\x8d\xdd~W\xe9\t\x00\x00\xf0\xfd\xc6\\7\x8cv\x13y\x16\xaa\xf4\xf05\xe4\xfc(\xba\xdc\x15\xb6\x05\xf0=\xac\xb9\u007f\xae\x82p\xae\x1bD\xaf\xf1\x1a\x8d\x97|H\x89\xe3\xf8\t@\xb7\f\"\u0638\x10\xaf6\x1d\xc1\xb2V\x85d\x19\x04\xf1O]?\xdaI\xe2\x11\x00\xe6\x99\xce4$\x9e\x11p\xba\x1b\xb4\xb7\xf4\x82\xe8\xeb&\a\bUF\xb2\xf0\x82\xe8\x1b^\x10m\x01\xe2\xc3\x02\x16\x9a\xceT1\x05\xc0\x8b\xbbp\xb6s\xa3\xc6Y\x83(*5(n\x18\xfe\xda\r\x92\xed\xc6\u0185m\xd3yL!q\xa5\xdb\xd5vn\xd0\xf8\xc5K\xbf\x96\x05\x80\xab\x06\x10k\xbcv0\x1d\xc0\x9a\xba\u045d\xc5\xf1\xa1\xe8\xea\xb5\x14~\f;\x11\xb0*KE~\xc9-\xba[\xbaa|\x06\u0256\xe9@\x95\x9f\x00\x00\x00\x92\x99\x1fD'\x13\xe5\x01\x00*u\x9d\xc90c\x1c/\xf4\xc2\xf8h\x94\xd8\x1d\xc0P\xaf\fL\x18\xf1\a\xc2\xd9\u01cb\u23d1\x1c\u007fa):\x97\xf71\xd5\x04qWI\x9e\xe9\x14\x96\xb5:$K?\x8a\xfe\xcb\v\xe3\x1dPbg\x80\x17\xc3^M\xba2\x8f\x80<\xd1\r\xa2\xcd\xfd0>\x8d\\\xdb\u07bf<\x0e$\xdb^\x10\x9f\xe7\x05\xd1+A|\f\xc0\x83\xa63\x19V\x02\xfc\u03d2\xb5m\xbc0:*\f\xc3GL\a\xea\ar\xbd\xe5~\x10\x9d\\\xb26g\xec\xc1cM\xf2\x88\xc4w\xb9A\xfcN6\x1aO\x8d\xf7M\xa4*3~!\xb0a\x96e\xaf4\x9d\xc3\xea\r\xaf\u0478\u04cd\xe2\x83K\xd6fC\xfa7\xd8\xe3\xdb\x00F\v\xf7\n8\xdd\xcd\xf2-\xfc \xfaL\x95\xae[\x1d\x8a\t\x80\xe7\xb8\xe1\xc8\xf5n\x10m?V\x1b\xc0V\x84\xed\x11/\x8e\u007f\xe7\x06\u045e\x12\x0f\x05p\x9b\xe9<}\xf6\x18\x80cF\xb7\u05467O\xf4\xcdEW?Du\x1e^\xc2N\x9a\xeel:\x84e\x8d\x97\x17\xc7wxatTG|\xb9\x803\xec\xf5\x81\x10\xa0\x9b%\x1e\xea\x06\xd1Vc+\xfekDu\xff^#\xd9\xf2\x82\xf8\\7\x88\xb6V\x89C\x00^\x8f5j5\x8a\xcb!\x9cS\xb2\xf6*/\x8c\xde\x17\x04\xc1C\xa6\x13\rB\x10\x04\x0f\xb9Q|0Q\xee'\xe0jL\xef\xff\xe7\x8b\u018esl\xebG\xd1\x0f'\xfa\xe6\xba\x1f_\x0f`\xdc\x13\x06\xfd\u6a3b\x97\xe9\fVo\x05A\xf0\xa0\x175Np\xbbz9\xa5Oc\xcd,<^\n\xb8Z\xe2a^\x10m\xe6\x87\xf1i\x9c5\xabrG\xae\x87j\x02\x00x~5\xe9r7\x88\xe6@<\t\xc0\x02\u04d9\xa6\x03\x92\xf2\xa3\xe8\n/\x8cw#\x9c\xbdI\\\x85iu4@\xf3\x01|\xd0\r\xa2\xd9^\x18\x9fOrR?\xdb\xe81\x00\\\xd2\xdblSQ\xda/Pk\xe8DQ\xf4g?\x8cO\xad\a\xd1\u6133\xd7\u060aAe\x06\xa6\x03p\xaf\x80\xd3K\xd6f{aco?\x8a\xae\x98\xecg\x92\xf5B$K?\x8e\xaf\xf2\xc2\xe8\xf5%k[\t8szO4i>\xc4\u007fr\x83\xece^\x14\x1f\x1f\x04\xc1|\u04c9Lp\u00d1\x1b\xfd0>HN\xb9\x03\x80\v0\x8d\x8e\x06\bx\x92\xd2g\xdc y\xf9\xd8q\x8eI\xad\xae\x92,\b|\xa3\xd7\xf9\xa6\xc0\x8e_\xa6)6\x1aO\xbaQ\xe3\xcb^\x18oKq\x0f\x8c\x16\x1f\x1fh\x95{\x03\x1e$\xf0\u064e\xb8\xb9\x1f\xc6\a\xf9Qt\xf9\x8a\xd7qV\rM\a\x98*IN\xa7\xdd\xda\x1f\xe0\xb1\x12\x0e\x01P7\x9diRJ\xec\xe2\xc5\xf1\xed\xa6c\xac(\u02f2\xadj\xea\xbeW\xe0\x11\x80\xb66\x9dg\x12\n\x12?\x05\xf4\xed\xba\x1f_\xbb\xba\x029\x13\xd1n/\x9f\xc3\u0499\x87\n\xfc\xfe\b\xf8\x99\x1f\xc6o\xedG\xdbE\xda:E\xc0\x99\xfdh{\x8a\x9e\xf5\xc2x\x9dAu\xa6Vk\xa3\xc2\xc1\x13\x83\xeao\"\xe4\xe0`\u07cf\xa7\xc5\xf6WI\xf5n;9\xa0\x14\x0e\x06p\x10\x80\xcdLg\xea-\xcd\x17\x9d\x1f\xd3)\xff\xd3\xf3\x1aw\x99N\xb3&\x91\xe4t\xb2l\x0f\xa9{(\xc9w\n\xd8\xc4t\xa6)Z\x04\xe0\x87\x84sq=\bn\xe9\xd5w\xdbt\xa2fs\u00ce\xe3\xbcG\xd4\xe1\x00v1\x9dg\x12J\x807H\xf8\x8e\x17\x86W\xf5\xaa\x86\x83\x16/\x9eY\x04\xfe\xe3\x80Fz\xd1\xde\x14=\xe4\x85\xf1V\xbdj,\u03d2\xaf@\xfaD\xaf\xda\ub85e\xfe\x9c\xc3JRTd\xadw\x91f:\xd0dU\xf5Cp\u02b4x\xf1\xcc\xdc\xf7\x0f \xf5&\x00\xfb\x00x\x85\xe9L\xcf#\x16C\x9a\a\xf1n8\x98G9w\u05c3\xe0w$\x87b\xcbZ\x92$\x9b\xd6Y\xee\ap?\x00\xfb\x02x\xb9\xc18\x1d\x10w\xa3\xc4\u034e\x83_\xd6\xfc\xe8\xc6\t\x15\xf5\xb3,\xab\xf2$\xb9E\x92\xec\x80\x1av\x83\xb0\x1b\xc0\xdd\x00\xcdFu\xbe\u00d6a\xf4\x96\x83y \xee\x14\u02db}\u007f\xc4\x16\xac\x1d\x02Z\xbcxf7\xf4\xf6\xec\n\xbb\x13|\x1d\xa0\x9d\x014\f\xc7\xca\x01\xcc\x05p\xbb\xa0[\xbc.\xae\x99H\xb17k\u0574l\u067ay\xbd\xbe\x0f\xa1}A\xec\a`[\x98\xfb\x1c\x11\x80\xfb\x01\xfcF\xe25^\xa7sm\xaf\x1e\x86-k\x98\xa4i\xbaY\r\xdd}!\xee\fb'\x00\xaf\x01\x10\x19\x8e\x95\x83\xb8\x1b\xc2] n\x13\xcb_\xf9\xfe\u0234\xa9iP\x95\xc1S\xdfi\xf1\u265d\xa0\xfe\x1a\xa9\xb6#\x88\x1dA\u0351\xb01\x81\r\xfb\xd2\x1f\xf0$\x81G\x00>\"\xe8\x11\x02\x8f\x10\xe5\u00c5j\x0fDQ\xf4\xe7~\xf4i\x8a\x96/_\xafS\xc7\xf6bm;H\xdb\x01\xd8\x1e\xc0\x96\x00\xd6\xebe7\xa3\u007f\xa6\xfc#\xa0\xfbA\xdeG\xf1\xcez\x10\xdcQ\x85\xeb4,\xcb\x1a,\xe9\u0675\x8a4\xd8\x1a,_%pk\x87\xd8Z\xc2\xd6\x00\xb6@\u007f\x1e\xe0\x96a\xf4,\xf9\x13\x00\x9e 0\xbft0\xaf,\x9d\xb9\u04f5\xd2\xfa\x9aHR\xbd\xdd^\xbe%\xcb\xfa\xf6\x0e5\a\xc4\x1c\t/\a\xb09z\xfb\x9d\x06\x00)\x80\aI\xd3%\x9f\xf0}\u007f\xc1d\v\xf7Y\x96\xf5B\u04a2\x19y\xeemV\x93\xb3EW\x9aA\xb2\x81\x921Qz\xa5\xe3\xccz\xc1w;\x00GZ\x06\xa9+\xc7I\xa4r\x91C,R\x97Ow\x1d\xe7\x99 \b\x9e&\x99\x9a\xfe\x99L\xf8\xff\x80$\x8b\xb0\xf8\x87\aI\x00\x00\x00\x00IEND\xaeB`\x82") + +func tailscalePngBytes() ([]byte, error) { + return _tailscalePng, nil +} + +func tailscalePng() (*asset, error) { + bytes, err := tailscalePngBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "tailscale.png", size: 24866, mode: os.FileMode(436), modTime: time.Unix(1589933683, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "tailscale.png": tailscalePng, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "tailscale.png": &bintree{tailscalePng, map[string]*bintree{}}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/cmd/tailscale/main.go b/cmd/tailscale/main.go new file mode 100644 index 0000000..9669b25 --- /dev/null +++ b/cmd/tailscale/main.go @@ -0,0 +1,526 @@ +// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "log" + "sort" + "strings" + "sync" + "time" + + "gioui.org/app" + "gioui.org/io/system" + "gioui.org/layout" + "gioui.org/op" + + "gioui.org/font/gofont" + + "tailscale.com/control/controlclient" + "tailscale.com/ipn" + "tailscale.com/tailcfg" + "tailscale.com/tailscale-android/jni" + "tailscale.com/wgengine/router" +) + +//go:generate go run github.com/go-bindata/go-bindata/go-bindata -nocompress -o logo.go tailscale.png + +type App struct { + jvm jni.JVM + appCtx jni.Object + appDir string + store *stateStore + + // updates is notifies whenever netState or browseURL changes. + updates chan struct{} + // vpnClosed is notified when the VPNService is closed while + // logged in. + vpnClosed chan struct{} + + // mu protects the following fields. + mu sync.Mutex + // netState is the most recent network state. + netState NetworkState + // browseURL is set whenever the backend wants to + // browse. + browseURL *string +} + +type clientState struct { + browseURL string + net NetworkState + // query is the search query, in lowercase. + query string + + Peers []UIPeer + // WantsEnabled is the desired state of the VPN: enabled or + // disabled. + WantsEnabled bool +} + +type NetworkState struct { + State ipn.State + NetworkMap *controlclient.NetworkMap + HasInternet bool +} + +// UIEvent is an event flowing from the UI to the backend. +type UIEvent interface{} + +type ConnectEvent struct { + Enable bool +} + +type CopyEvent struct { + Text string +} + +type SearchEvent struct { + Query string +} + +type ReauthEvent struct{} + +type LogoutEvent struct{} + +const enabledKey = "ipn_enabled" + +func main() { + a := &App{ + jvm: jni.JVMFor(app.JavaVM()), + appCtx: jni.Object(app.AppContext()), + updates: make(chan struct{}, 1), + vpnClosed: make(chan struct{}, 1), + } + appDir, err := app.DataDir() + if err != nil { + fatalErr(err) + } + a.appDir = appDir + a.store = newStateStore(a.appDir, a.jvm, a.appCtx) + events := make(chan UIEvent) + go func() { + if err := a.runBackend(events); err != nil { + fatalErr(err) + } + }() + go func() { + if err := a.runUI(events); err != nil { + fatalErr(err) + } + }() + app.Main() +} + +func (a *App) runBackend(events <-chan UIEvent) error { + var cfg *router.Config + var state NetworkState + var service jni.Object + var b *backend + b, err := newBackend(a.appDir, a.jvm, a.store, func(s *router.Config) error { + cfg = s + if b == nil || service == 0 || cfg == nil { + return nil + } + return b.updateTUN(service, cfg) + }) + if err != nil { + return err + } + defer b.CloseTUNs() + var timer *time.Timer + var alarmChan <-chan time.Time + alarm := func(t *time.Timer) { + if timer != nil { + timer.Stop() + } + timer = t + if timer != nil { + alarmChan = timer.C + } + } + err = b.Start(func(n ipn.Notify) { + if s := n.State; s != nil { + oldState := state.State + state.State = *s + if service != 0 { + a.updateNotification(service, state.State) + } + if service != 0 { + if cfg != nil && state.State >= ipn.Starting { + if err := b.updateTUN(service, cfg); err != nil { + a.notifyVPNClosed() + } + } else { + b.CloseTUNs() + } + } + // Stop VPN if we logged out. + if oldState > ipn.NeedsLogin && state.State <= ipn.NeedsLogin { + if err := a.callVoidMethod(a.appCtx, "stopVPN", "()V"); err != nil { + fatalErr(err) + } + } + a.notify(state) + } + if u := n.BrowseToURL; u != nil { + a.setURL(*u) + } + if m := n.NetMap; m != nil { + state.NetworkMap = m + a.notify(state) + if service != 0 { + alarm(a.notifyExpiry(service, m.Expiry)) + } + } + }) + if err != nil { + return err + } + for { + select { + case <-alarmChan: + if m := state.NetworkMap; m != nil && service != 0 { + alarm(a.notifyExpiry(service, m.Expiry)) + } + case e := <-events: + switch e.(type) { + case ReauthEvent: + b.backend.StartLoginInteractive() + case LogoutEvent: + b.backend.Logout() + } + case s := <-onConnect: + jni.Do(a.jvm, func(env jni.Env) error { + if jni.IsSameObject(env, s, service) { + // We already have a reference. + jni.DeleteGlobalRef(env, s) + return nil + } + if service != 0 { + jni.DeleteGlobalRef(env, service) + } + service = s + return nil + }) + a.updateNotification(service, state.State) + if m := state.NetworkMap; m != nil { + alarm(a.notifyExpiry(service, m.Expiry)) + } + if cfg != nil && state.State >= ipn.Starting { + if err := b.updateTUN(service, cfg); err != nil { + a.notifyVPNClosed() + } + } + case <-onConnectivityChange: + state.HasInternet = connected.Load().(bool) + if b != nil { + b.LinkChange() + } + a.notify(state) + case s := <-onDisconnect: + b.CloseTUNs() + jni.Do(a.jvm, func(env jni.Env) error { + defer jni.DeleteGlobalRef(env, s) + if jni.IsSameObject(env, service, s) { + jni.DeleteGlobalRef(env, service) + service = 0 + } + return nil + }) + if state.State >= ipn.Starting { + a.notifyVPNClosed() + } + } + } +} + +// updateNotification updates the foreground persistent status notification. +func (a *App) updateNotification(service jni.Object, state ipn.State) error { + var msg, title string + switch state { + case ipn.Starting: + title, msg = "Connecting...", "" + case ipn.Running: + title, msg = "Connected", "" + default: + return nil + } + return jni.Do(a.jvm, func(env jni.Env) error { + cls := jni.GetObjectClass(env, service) + update := jni.GetMethodID(env, cls, "updateStatusNotification", "(Ljava/lang/String;Ljava/lang/String;)V") + jtitle := jni.JavaString(env, title) + jmessage := jni.JavaString(env, msg) + return jni.CallVoidMethod(env, service, update, jni.Value(jtitle), jni.Value(jmessage)) + }) +} + +// notifyExpiry notifies the user of imminent session expiry and +// returns a new timer that triggers when the user should be notified +// again. +func (a *App) notifyExpiry(service jni.Object, expiry time.Time) *time.Timer { + d := time.Until(expiry) + var title string + const msg = "Reauthenticate to maintain the connection to your network." + var t *time.Timer + const ( + aday = 24 * time.Hour + soon = 5 * time.Minute + ) + switch { + case d <= 0: + title = "Your authentication has expired!" + case d <= soon: + title = "Your authentication expires soon!" + t = time.NewTimer(d) + case d <= aday: + title = "Your authentication expires in a day." + t = time.NewTimer(d - soon) + default: + return time.NewTimer(d - aday) + } + err := jni.Do(a.jvm, func(env jni.Env) error { + cls := jni.GetObjectClass(env, service) + notify := jni.GetMethodID(env, cls, "notify", "(Ljava/lang/String;Ljava/lang/String;)V") + jtitle := jni.JavaString(env, title) + jmessage := jni.JavaString(env, msg) + return jni.CallVoidMethod(env, service, notify, jni.Value(jtitle), jni.Value(jmessage)) + }) + if err != nil { + fatalErr(err) + } + return t +} + +func (a *App) notifyVPNClosed() { + select { + case a.vpnClosed <- struct{}{}: + default: + } +} + +func (a *App) notify(state NetworkState) { + a.mu.Lock() + a.netState = state + a.mu.Unlock() + select { + case a.updates <- struct{}{}: + default: + } +} + +func (a *App) setURL(url string) { + a.mu.Lock() + a.browseURL = &url + a.mu.Unlock() + select { + case a.updates <- struct{}{}: + default: + } +} + +func (a *App) runUI(backend chan<- UIEvent) error { + w := app.NewWindow() + gofont.Register() + ui, err := newUI(a.store) + if err != nil { + return err + } + // Register an Android Fragment instance for lifecycle tracking + // of our Activity. + w.RegisterFragment("com.tailscale.ipn.Peer") + var ops op.Ops + state := new(clientState) + var peer jni.Object + state.WantsEnabled, _ = a.store.ReadBool(enabledKey, true) + ui.enabled.Value = state.WantsEnabled + for { + select { + case <-a.vpnClosed: + state.WantsEnabled = false + w.Invalidate() + case <-a.updates: + a.mu.Lock() + oldState := state.net.State + state.net = a.netState + if a.browseURL != nil { + state.browseURL = *a.browseURL + a.browseURL = nil + } + a.mu.Unlock() + a.updateState(peer, state) + w.Invalidate() + if peer != 0 { + newState := state.net.State + // Start VPN if we just logged in. + if state.WantsEnabled && oldState <= ipn.NeedsLogin && newState > ipn.NeedsLogin { + if err := a.callVoidMethod(peer, "prepareVPN", "()V"); err != nil { + fatalErr(err) + } + } + } + case peer = <-onPeerCreated: + w.Invalidate() + a.setVPNState(peer, state) + case p := <-onPeerDestroyed: + jni.Do(a.jvm, func(env jni.Env) error { + defer jni.DeleteGlobalRef(env, p) + if jni.IsSameObject(env, peer, p) { + jni.DeleteGlobalRef(env, peer) + peer = 0 + } + return nil + }) + case <-vpnPrepared: + if err := a.callVoidMethod(a.appCtx, "startVPN", "()V"); err != nil { + return err + } + case e := <-w.Events(): + switch e := e.(type) { + case system.DestroyEvent: + return e.Err + case system.FrameEvent: + gtx := layout.NewContext(&ops, e.Queue, e.Config, e.Size) + events := ui.layout(gtx, e.Insets, state) + e.Frame(gtx.Ops) + a.processUIEvents(backend, w, events, peer, state) + } + } + } +} + +func (a *App) updateState(javaPeer jni.Object, state *clientState) { + if javaPeer != 0 && state.browseURL != "" { + a.browseToURL(javaPeer, state.browseURL) + state.browseURL = "" + } + + state.Peers = nil + netMap := state.net.NetworkMap + if netMap == nil { + return + } + // Split into sections. + users := make(map[tailcfg.UserID]struct{}) + var peers []UIPeer + for _, p := range netMap.Peers { + if q := state.query; q != "" { + // Filter peers according to search query. + host := strings.ToLower(p.Hostinfo.Hostname) + name := strings.ToLower(p.Name) + var addr string + if len(p.Addresses) > 0 { + addr = p.Addresses[0].IP.String() + } + if !strings.Contains(host, q) && !strings.Contains(name, q) && !strings.Contains(addr, q) { + continue + } + } + users[p.User] = struct{}{} + peers = append(peers, UIPeer{ + Owner: p.User, + Peer: p, + }) + } + // Add section (user) headers. + for u := range users { + name := netMap.UserProfiles[u].DisplayName + name = strings.ToUpper(name) + peers = append(peers, UIPeer{Owner: u, Name: name}) + } + myID := state.net.NetworkMap.User + sort.Slice(peers, func(i, j int) bool { + lhs, rhs := peers[i], peers[j] + if lu, ru := lhs.Owner, rhs.Owner; ru != lu { + // Sort own peers first. + if lu == myID { + return true + } + if ru == myID { + return false + } + return lu < ru + } + lp, rp := lhs.Peer, rhs.Peer + // Sort headers first. + if lp == nil { + return true + } + if rp == nil { + return false + } + return lp.Hostinfo.Hostname < rp.Hostinfo.Hostname || + lp.Hostinfo.Hostname == rp.Hostinfo.Hostname && lp.ID < rp.ID + }) + state.Peers = peers +} + +func (a *App) processUIEvents(backend chan<- UIEvent, w *app.Window, events []UIEvent, peer jni.Object, state *clientState) { + for _, e := range events { + switch e := e.(type) { + case ReauthEvent: + go func() { + backend <- e + }() + case LogoutEvent: + go func() { + backend <- e + }() + case CopyEvent: + w.WriteClipboard(e.Text) + case SearchEvent: + state.query = strings.ToLower(e.Query) + a.updateState(peer, state) + case ConnectEvent: + if e.Enable == state.WantsEnabled { + return + } + if e.Enable && peer == 0 { + return + } + state.WantsEnabled = e.Enable + a.store.WriteBool(enabledKey, e.Enable) + a.updateState(peer, state) + a.setVPNState(peer, state) + } + } +} + +func (a *App) setVPNState(peer jni.Object, state *clientState) { + var err error + if state.WantsEnabled && state.net.State > ipn.NeedsLogin { + err = a.callVoidMethod(peer, "prepareVPN", "()V") + } else { + err = a.callVoidMethod(a.appCtx, "stopVPN", "()V") + } + if err != nil { + fatalErr(err) + } +} + +func (a *App) browseToURL(peer jni.Object, url string) { + err := jni.Do(a.jvm, func(env jni.Env) error { + jurl := jni.JavaString(env, url) + return a.callVoidMethod(peer, "showURLCustomTabs", "(Ljava/lang/String;)V", jni.Value(jurl)) + }) + if err != nil { + fatalErr(err) + } +} + +func (a *App) callVoidMethod(obj jni.Object, name, sig string, args ...jni.Value) error { + if obj == 0 { + panic("invalid object") + } + return jni.Do(a.jvm, func(env jni.Env) error { + cls := jni.GetObjectClass(env, obj) + m := jni.GetMethodID(env, cls, name, sig) + return jni.CallVoidMethod(env, obj, m, args...) + }) +} + +func fatalErr(err error) { + log.Print(err) +} diff --git a/cmd/tailscale/multitun.go b/cmd/tailscale/multitun.go new file mode 100644 index 0000000..6db00e7 --- /dev/null +++ b/cmd/tailscale/multitun.go @@ -0,0 +1,287 @@ +// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "os" + + "github.com/tailscale/wireguard-go/tun" +) + +// multiTUN implements a tun.Device that supports multiple +// underlying devices. This is necessary because Android VPN devices +// have static configurations and wgengine.NewUserspaceEngineAdvanced +// assumes a single static tun.Device. +type multiTUN struct { + // devices is for adding new devices. + devices chan tun.Device + // event is the combined event channel from all active devices. + events chan tun.Event + + close chan struct{} + closeErr chan error + + reads chan ioRequest + writes chan ioRequest + flushes chan chan error + mtus chan chan mtuReply + names chan chan nameReply + shutdowns chan struct{} +} + +// tunDevice wraps and drives a single run.Device. +type tunDevice struct { + dev tun.Device + // close closes the device. + close chan struct{} + closeDone chan error + // readDone is notified when the read goroutine is done. + readDone chan struct{} +} + +type ioRequest struct { + data []byte + offset int + reply chan<- ioReply +} + +type ioReply struct { + bytes int + err error +} + +type mtuReply struct { + mtu int + err error +} + +type nameReply struct { + name string + err error +} + +func newTUNDevices() *multiTUN { + d := &multiTUN{ + devices: make(chan tun.Device), + events: make(chan tun.Event), + close: make(chan struct{}), + closeErr: make(chan error), + reads: make(chan ioRequest), + writes: make(chan ioRequest), + flushes: make(chan chan error), + mtus: make(chan chan mtuReply), + names: make(chan chan nameReply), + shutdowns: make(chan struct{}), + } + go d.run() + return d +} + +func (d *multiTUN) run() { + var devices []*tunDevice + // readDone is the readDone channel of the device being read from. + var readDone chan struct{} + // runDone is the closeDone channel of the device being written to. + var runDone chan error + for { + select { + case <-readDone: + // The oldest device has reached EOF, replace it. + n := copy(devices, devices[1:]) + devices = devices[:n] + if len(devices) > 0 { + // Start reading from the next device. + dev := devices[0] + readDone = dev.readDone + go d.readFrom(dev) + } + case <-runDone: + // A device completed runDevice, replace it. + if len(devices) > 0 { + dev := devices[len(devices)-1] + runDone = dev.closeDone + go d.runDevice(dev) + } + case <-d.shutdowns: + // Shut down all devices. + for _, dev := range devices { + close(dev.close) + <-dev.closeDone + <-dev.readDone + } + devices = nil + case <-d.close: + var derr error + for _, dev := range devices { + if err := <-dev.closeDone; err != nil { + derr = err + } + } + d.closeErr <- derr + return + case dev := <-d.devices: + if len(devices) > 0 { + // Ask the most recent device to stop. + prev := devices[len(devices)-1] + close(prev.close) + } + wrap := &tunDevice{ + dev: dev, + close: make(chan struct{}), + closeDone: make(chan error), + readDone: make(chan struct{}, 1), + } + if len(devices) == 0 { + // Start using this first device. + readDone = wrap.readDone + go d.readFrom(wrap) + runDone = wrap.closeDone + go d.runDevice(wrap) + } + devices = append(devices, wrap) + case f := <-d.flushes: + var err error + if len(devices) > 0 { + dev := devices[len(devices)-1] + err = dev.dev.Flush() + } + f <- err + case m := <-d.mtus: + r := mtuReply{mtu: defaultMTU} + if len(devices) > 0 { + dev := devices[len(devices)-1] + r.mtu, r.err = dev.dev.MTU() + } + m <- r + case n := <-d.names: + var r nameReply + if len(devices) > 0 { + dev := devices[len(devices)-1] + r.name, r.err = dev.dev.Name() + } + n <- r + } + } +} + +func (d *multiTUN) readFrom(dev *tunDevice) { + defer func() { + dev.readDone <- struct{}{} + }() + for { + select { + case r := <-d.reads: + n, err := dev.dev.Read(r.data, r.offset) + stop := false + if err != nil { + select { + case <-dev.close: + stop = true + err = nil + default: + } + } + r.reply <- ioReply{n, err} + if stop { + return + } + case <-d.close: + return + } + } +} + +func (d *multiTUN) runDevice(dev *tunDevice) { + defer func() { + // The documentation for https://developer.android.com/reference/android/net/VpnService.Builder#establish() + // states that "Therefore, after draining the old file + // descriptor...", but pending Reads are never unblocked + // when a new descriptor is created. + // + // Close it instead and hope that no packets are lost. + dev.closeDone <- dev.dev.Close() + }() + // Pump device events. + go func() { + for { + select { + case e := <-dev.dev.Events(): + d.events <- e + case <-dev.close: + return + } + } + }() + for { + select { + case w := <-d.writes: + n, err := dev.dev.Write(w.data, w.offset) + w.reply <- ioReply{n, err} + case <-dev.close: + // Device closed. + return + case <-d.close: + // Multi-device closed. + return + } + } +} + +func (d *multiTUN) add(dev tun.Device) { + d.devices <- dev +} + +func (d *multiTUN) File() *os.File { + // The underlying file descriptor is not constant on Android. + // Let's hope no-one uses it. + panic("not available on Android") +} + +func (d *multiTUN) Read(data []byte, offset int) (int, error) { + r := make(chan ioReply) + d.reads <- ioRequest{data, offset, r} + rep := <-r + return rep.bytes, rep.err +} + +func (d *multiTUN) Write(data []byte, offset int) (int, error) { + r := make(chan ioReply) + d.writes <- ioRequest{data, offset, r} + rep := <-r + return rep.bytes, rep.err +} + +func (d *multiTUN) Flush() error { + r := make(chan error) + d.flushes <- r + return <-r +} + +func (d *multiTUN) MTU() (int, error) { + r := make(chan mtuReply) + d.mtus <- r + rep := <-r + return rep.mtu, rep.err +} + +func (d *multiTUN) Name() (string, error) { + r := make(chan nameReply) + d.names <- r + rep := <-r + return rep.name, rep.err +} + +func (d *multiTUN) Events() chan tun.Event { + return d.events +} + +func (d *multiTUN) Shutdown() { + d.shutdowns <- struct{}{} +} + +func (d *multiTUN) Close() error { + close(d.close) + return <-d.closeErr +} diff --git a/cmd/tailscale/pprof.go b/cmd/tailscale/pprof.go new file mode 100644 index 0000000..1c5ead8 --- /dev/null +++ b/cmd/tailscale/pprof.go @@ -0,0 +1,18 @@ +// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build pprof + +package main + +import ( + "net/http" + _ "net/http/pprof" +) + +func init() { + go func() { + http.ListenAndServe(":6060", nil) + }() +} diff --git a/cmd/tailscale/store.go b/cmd/tailscale/store.go new file mode 100644 index 0000000..f3acc01 --- /dev/null +++ b/cmd/tailscale/store.go @@ -0,0 +1,121 @@ +// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "encoding/base64" + + "tailscale.com/ipn" + "tailscale.com/tailscale-android/jni" +) + +// stateStore is the Go interface for a persistent storage +// backend by androidx.security.crypto.EncryptedSharedPreferences (see +// App.java). +type stateStore struct { + dataDir string + + jvm jni.JVM + // appCtx is the global Android app context. + appCtx jni.Object + + // Cached method ids on appCtx. + encrypt jni.MethodID + decrypt jni.MethodID +} + +func newStateStore(dataDir string, jvm jni.JVM, appCtx jni.Object) *stateStore { + s := &stateStore{ + dataDir: dataDir, + jvm: jvm, + appCtx: appCtx, + } + jni.Do(jvm, func(env jni.Env) error { + appCls := jni.GetObjectClass(env, appCtx) + s.encrypt = jni.GetMethodID( + env, appCls, + "encryptToPref", "(Ljava/lang/String;Ljava/lang/String;)V", + ) + s.decrypt = jni.GetMethodID( + env, appCls, + "decryptFromPref", "(Ljava/lang/String;)Ljava/lang/String;", + ) + return nil + }) + return s +} + +func prefKeyFor(id ipn.StateKey) string { + return "statestore-" + string(id) +} + +func (s *stateStore) ReadBool(key string, def bool) (bool, error) { + data, err := s.read(key) + if err != nil { + return def, err + } + if data == nil { + return def, nil + } + return string(data) == "true", nil +} + +func (s *stateStore) WriteBool(key string, val bool) error { + data := []byte("false") + if val { + data = []byte("true") + } + return s.write(key, data) +} + +func (s *stateStore) ReadState(id ipn.StateKey) ([]byte, error) { + state, err := s.read(prefKeyFor(id)) + if err != nil { + return nil, err + } + if state == nil { + return nil, ipn.ErrStateNotExist + } + return state, nil +} + +func (s *stateStore) WriteState(id ipn.StateKey, bs []byte) error { + prefKey := prefKeyFor(id) + return s.write(prefKey, bs) +} + +func (s *stateStore) read(key string) ([]byte, error) { + var data []byte + err := jni.Do(s.jvm, func(env jni.Env) error { + jfile := jni.JavaString(env, key) + plain, err := jni.CallObjectMethod(env, s.appCtx, s.decrypt, + jni.Value(jfile)) + if err != nil { + return err + } + b64 := jni.GoString(env, jni.String(plain)) + if b64 == "" { + return nil + } + data, err = base64.RawStdEncoding.DecodeString(b64) + return err + }) + return data, err +} + +func (s *stateStore) write(key string, value []byte) error { + bs64 := base64.RawStdEncoding.EncodeToString(value) + err := jni.Do(s.jvm, func(env jni.Env) error { + jfile := jni.JavaString(env, key) + jplain := jni.JavaString(env, bs64) + err := jni.CallVoidMethod(env, s.appCtx, s.encrypt, + jni.Value(jfile), jni.Value(jplain)) + if err != nil { + return err + } + return nil + }) + return err +} diff --git a/cmd/tailscale/tailscale.png b/cmd/tailscale/tailscale.png new file mode 100644 index 0000000000000000000000000000000000000000..c97856055ffdbf1aad8790f9605835c5b6df07cb GIT binary patch literal 24866 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%0D_B5g=@<7->i7vZD zJ~AJzwPjoz;D}>9dVC}>fV=k=!#1JSyX;8=wCOmp+@Rdt6z<{w#rv#ok+lFle2nhXAouKGsu+Vn+L-o7D#9RU3 z=fX)n2Tbr&aP~}excYt-u-LY1<#_Xo0?0f$lh9RUDNrw^xlAQO&MZeevAKdxet;ASMz8 z1+2V-f%JeU9-vY8W~?|t#cXP&HuR}i;XAd4G$LR`#X4Q4CTO7cy*<8@Ep=@TT{h9u z2QPZQU;;f;R+89fbX8&HuHRL>u_sz;&e3F-XmaVxRNgrDD=pILn_;!9S7C^|sAWPx z5(vcwP(-Yn%fjk;^Ej`RAa2gjc}M~z`|jcYLnb8a2Lyt@ZpIq!z}}O@ipPi*!z-ox zYuW8=$$v-S*M^#of_gN?aUm`sPcNVJz;ioAWLIwTHG{I)eKVQH@vPjU6G7vj?x3c0 z1oy>V=}P?$qlXnV$d z<^CgPbAWEy(3Xi#k897j+2}>!s3k}h*{m7>ai}jK=A5Mfy#un!bJnj(EXITvngYrKby0-;17w zM9*Y%BQh!~#w$Qq-kBA7zpR>skOd_J-BOs8EF{9&Uxga|#97B=^apO#->$8}k_hEp z{X*b95=*FYm-MeyX%*I7y0>VWwv*eFo45GL`?Ti?#Xpsb@(A|xMyulffz)#i;mLaJ zGxjBA3OtWO>m!%gGf`j=kqueFm3oh2+jCM*R`dwIjDfHI{Fw?;R8Q}ru*?*$=md{H9Te&l5jx%TM6V;eL^)Fm+U=eEU884oMLDnjF3J}2 z?T}A!$+zuX8h36N)*0t1*r#znLLC&*aH+pxu?I7j2a}CqNi(rrEr=d7l_{ut#T|_Z z!$j5dxJvfQ#6TqkL({L~g+!1@`=M;&N(HQ#u3RmH3BM@uR~_yN6>_FwfP;M% z#0SVBQk{qxwrUA0$C^BsSINq{=GI6034vIx*ouBb&eR{X=FAdok(SX6G-94VPXQ@3 z;z4|N~>eQfr=gtPJmOE{BL$^_y`PKm&ddD`iH9z>En&M#${5n_e5Vp zOn$DaVTYum%Rf!EJ&E-B(8Zk!2QjO6YL_TPGFz^Vk^#1kOUs|iS^!^GDrBQYm-en?C z?Ji9i%enUs0}o~BjF#dl$2bfo{xRfWAbY}%a2n`TS}+1Bul@J{!-V_8@Vz}-;G$vR zUX@-%yQ?l?@}m5EaM)ZadnO|RBPBGr=_uoWm|IxSlIN&blQ#_r9+C7CX2uupAA^AA z+e!`f5d}4sFt3&OSdyyxs)y4;npee;X6or^Mdc_u^>a8k?k^Bad&FV8&EYL;y-rv0 z0V~BWc-B`kx`*}vJV}v#h-}IV5$knJwM!8V4c=eBFX^8)deKX(8(7A5$p1$TA!R^j zVvF%o%;X=%K~|YSLHq{#rt~@Jli$cwd2Lt9jY{vKOU-;HlKx&J4qxlSO~VY%Zit`E zi_*c)9NCv3G9p(srM9#ibSaK(1m`c)d-3t~P!9?f!8Z}+09AfQKL#OEvj}QRIwP?E zY+fsr#64pK><1?-@kH-ML>4N$SIS}z$BWfx7C5A-fKW#8-6t3Bp9?c$!BgB-XDO(J zge;gE!sz}_SEzlr4X|Utz!lBT(*A=$VZ1`uQ>m@rkZ9x1fqe0e!pQFVaQ{<@%K-gF z81jhxO=D(**GHyjrlf2nX%^HK?=khk*i+dRk3Jsfs)aAE!V3DfUaZDIWGjR}s{tWWj zM9lt#CL#X@OYhTp_7CeZ^ppfH9|-g04tlC)|Dtg|-Za{w$~xWCYcZ#;k6~?5k*WVq zbS-y}Mu|Ck@9CSkq#qy$L$UPpCsFJyF<`d^+O7&Fl8N9-n&8@4%K0!N$klfbqw;H{ zSvjn8)!vC3Bq^hL3v48=T3YWSExFFIkoi>qI`E*sI z;^iFyDqHkkqXvWYCNEx3jD<{P=uOHtkg>PCy1RPGo%|yobmbq8ZU)HK3aoRlB4?QE z#6~!M9+9PJ_Hh!#W5%x5)njHwoHj)AVfLdq}EzEsTo@?FzXhK)o@rWZ*CF%Cj0gZ%swbwvdc+;fel7 z(YYRXeh+?s{}JfwphX*?a4cwV11xR7V8us#qPa&2fsI?FG%PsqmcOF+QW^&Ya@m0t zhP~=C?SW%IVC0#BHuy~Z`+2&9Zj8`J^kzq1zXYx5>YAu z%J`41?rw9<%3smJZ6>cE0Geh|Z;1A&xwh6o&cM>50gGf86q~TSzJ-z)HD;aK;^^Kv zs^IJ@giPK+oeUw!0236Ym!Ov_4{e+0PWdX+`{R2PLBkP-pKwre?C}0kJz|=2V`9`5 zu!HMKV_HY=89Ch4K#$iZP(6u|gG*WHfT}kFt71nut4I{opwOlepbc$_a|P-s>e0vx zEB73gU#u+Ir|N@|5E*Y~e)$m{$RBSb0f>$ZwNm7Gp5fp&L^vZro50xY?0GCjz1?48 z)Y#Hj_{8)C(afEn+59tiP&>3SgMAWQ3oWFmOpu^joPAy6LIwdUGq8k$vLK!~NTTVS zl~2$JfVT!BApxJJ{8;bA`qsN@c-njVKC{dUDTQiz8dcsl`_cX;nqD$1=2VUXk32PP zLMFauG7A7f1pF5e6XbKdT2voU<)?KT7r)~3$b{yPfGGEEgNFkT*2J|V87?1ftlYRIxk>Adhkj_ z_B?q?Ik9Xxyvs_Unit7X*w#u0fHg&y``)vm6CR`=X)QU*xlsNBeW;a*W3q!TBNc;8 z7OsDwcCb_)E*O3F#7vGu?ci>%co#TkBb7x?+3Kw0U$5e=!nrpBbwWREW7+3rK@6!lI&TgWN}d%eG#8 zn^qewgq($dVeT^xb&`uOfq1rJ8LQ*y&Ia`F`8L9C*aZpuxQp?ZX)srN_Q$NhKUMVT z@cZ0D<>1~oBo8f11_V`s+&#Sk-K-rVr!cQ-Lj z+O|G11x_0VM2wASRQiuaj(Xkzz+UD?UOfp=tDixFT8ai4hVrm}F&nGuk7{6I;X?id zd-Hue+5epgKLQQH0*t3r6SL*icq#Q{Be?00@38~G{Hdb@NC<)SnS?bbP~U?nXvp&# z%*NVo9#_r>>y5`sNmsl8S@lKO`#ue$ABzu9_io0tq?#zB{ALkx%vu-bU8!)IPzLZW z$ej;pHBnHZH1!H%B1h+m#FAj+^H9UBZ7Zi`!ADO_MWZ4EKXl=w!Y2sPt{_Y&Ce28& zpo2-Xi1mrj94#ZT(4lp*ZoAF%TE2A*0ZrrKa=i%o+)_dvbpyiMM*Ivt9nV7Qe<9x2 zL?Nb!t3kQazlnh7BERi4F%lMLCnun$rv^*g^44ssP(M8Up2aT^U!4V6l&6zv0MsqZrv^lB}cm)$9e#s?L| z@)nx-NXSR<$_yY3+Q^BnsZrje!w7hHhd(#8q=ni*0Cq zKhg4)<%Ks#-%P)50~s4uMG$EUUOTkdOVN*Ook4^fJ(dEYycee9BUFIN343XWpg0%} zinC9x>pmYKPswJUHVAJmz`&y}^xOO;rIiX!s#BKvmEC$nYaYn#Qlg~&2uB%K-l*CP zxPCB)e;0WQj8@$O^m?B#?ya z^G65+R$z*J@kbD;4)D$+9pf>7a}|Fx$^ALOArsAX3~{&PsrXYq`}i-zk)WrK|9G3* zw{eV@94cYhy!&$*Xwf}FAom(t<7L=94Zf_b7kt1+FRE!eN}U0+qJ2rU`)ONZfe&u# z=vz2Dd+YqA46?j_pprSGe_hGq3on2&DeOlCqD|%JWaq%E3Lo5#`>C-18bnz` zP@4ZJBTz7M8!T4A$w0xB7YHOqhvtvEy_LjBtn5d-Lr^7|hksbYD8WXjf|q#8Ex$4db7E6R zd(fVrq=(H^eLohc)&FA4bvIkLXWl1PXYH70?SA@D5c_^kEARea$>j}|ORi$$o!ZVC^3Y)2AT%Bq^1clIw2RU61=F(5%%v!0lPcn&C#q4_D%qA~jFr>yhaw;@>C$VV~D{iL3UN5+0bbD6qZ zC)^HxZ~tmIJ)(v8oDerJK{1rxgOVc%oDCKRh6^F2;7@w@iSmX~$9smrL;kN9O*2q1oN@i;`F5AI4*w}K@$#Bycq0CjJ-&~gp&N|bB2lt9 zlU9G<6q>y_a!Z+_#tj79h*Ww0UESNpJBCrMdfB=yr;TKlso!*bY31rC&}@Ag{ao(q zk{<>ZHphDn&E6zZn%lMI^3QF<6!_xFdGS3nK}gpa3U+Csh_56-8!)CCXF$`%`1XY!kI|W6jMoi zz#&0VK~ui|=pD3~t6X>2igTEt-et8)iMTGgUF+8gapP={R_S$49Ruf5B|aOSpkc8u zco7-Fw%-n3npuT~ad}Bfj3Y%<7RE?D9kYL7QdS$sPH~WFHIR=krs9WM(;+SsVc@I( zZg&_*ZT8LEq1-7;!EEUJOrj)syTu*9qm*Bg3fnf?tdRW^?N^9=W}uQ9NRTVDt2^2{ z)b!AA5i+M6=Jyx?>sI8$)`+S8W23hypTk^#pKQg##8bY%4^@McDz5}zt9qZ^Y|mQf zGHPdu?yVQ?Okae)_q(ITPYAgSCzzu8iIBsWr!?1kt^EE+wAYLGff&j<8WpD>bQHAa zdWvJtcj5TXc=Bwfi4`ih2-)6vXd|>eq<6!7ejwHA)je`HGY&7HZaIg)<7WIexo__I z_PLQ2-vqIyk}tTAO6U}P9LV0ebIB#t=%Z(B&=D~A)TyjLaYEvOOn|QN*L%P=v@AR({*3)j(Ub_|NnQOnu=4hgZV^z4b8jy2g`*X+78Rs=JR8GXQB<_B@ z1YjH8UUjqA%t(vfyrXR7bC}U~Q{wCfKM5?*hZ&jj{Lk}tZiwYw_>pS7sAjS-DyYkx zs*}%&(Q-PnXo&|jMm@b`t9+vw4sed4K&Gh$r z$J$rx5YLZ1}YzazHXUy*f9ZJp!PQY%Q~*O$impZ_IE9nv^B={3cb6w(!)2&_MEOga3)tAzm8M|Cn zX3R{Ngs3uU+sxDtyyY1hVz_S8rMUQZZ(*H1gnF=XQQv@HR~%)VO4+S<2JAVzC7*Tv z3E}QFf)Lz9Gt+q8tDyW`?onmtpIsyK*!n<(T}S@gpR1yU)_o%Q<$o(>f87S#w?P5#o<_>xgx8!Ok>oIH8CC+hLal-ykWWYuvPtK zzgx_$Z<`Ih($5G|Bfu%uRObJ)bmfWxX(qymwkqr z195F1u7gag=9RxF(`!=XH=|%YNXD8q>@`=bnMj))q}iO1^A!N-H+vT3A8^+0<(OY3 zeOAuC&*@gRB2PGv#~+@yL3caA2#i{i-162()7{R%^#C~IvUH18hpq6==f_?&$30_! zZ=q_&jUBAZ%nUBt6ngN0#3Ayumo>}Kth>c)`V#qhpX$VbRH9__%-lmHg8|%SbP1aw z>qgMMq=IU_2SrQxr{YZ-vkB(Cp;f>|q*?@Qd*vn2c~ZYYJB9(xnfGVTqV1yuU;*@s zvWZHYt}SP88SW1MpGA5hVysNqgo;)+6s!o@g_*jS+Q9w7Z3WNO;XvwIb`S71lxT;y@9= zg1T4W+WfwsY21N##7%QlzJOgV;d!LH%jn(6iq?;YdIu-&)39n51RVMbucBm!3@I>! z7@1HjP>9Mv6FgVZOM1!p?a&f5MLmGX%6Jsc-TR$G%_y0(znU0S9R&^srCJNdzE^Om z6RpeQP^ebt(oC3Dy27Jsqfc`2t~DGxr1yY~w^1%A#qd^{ImB}$$uvIr045{Wk8OAr zwNt{G&-cKwcLqk+UL;QKt9-3mrqSX&&fk%5i;}*~AvekGK$qCC!;#{>ZZXb!nhzbV z3QI=|1kymQXX-N{BQ9g-l% zm5o?Mp%zlP1&W|o-ILvOrO4TA5$U*OL%BXov{}3s) zVLw<)lV%V0T|C;Hs`edTH2V)>Hf-Sk`Q{26eIw3D`K0)j;=-2bfEx@sj_SE{cYXcdFq@0zJ_ zHg7@RmLvEdk%1K9HG4pxMt(Rm^2_T0U%@2ISD(aRgQMdSMK8M*v~!e<3M97X)w6oL zw`#afJF?SfhkFcH8nk-Oue*WOfB|7!4$a~VhBdyv|L6?di{FK++k7tyvoadu$#+x3 zFfn_q$Ltamu6h-~_y-MHd1j}tfoEm{cOd?`AOD_%Ex)aqc9yuwz(G?NZsFFL2Y*#! z;r0=qc$<6N*kQn}77(^XUtDRhG|s_{W~9Z1)ra_q~kR? z^DG3suUE#lqdNvP4{DvafTrE&ux}Y&rG5U$v?Wl|F?~q_dmr;f9Ikd!@Wxa+ascN< z20pzfio*mEEB}f1@fp8}JURK9CG_TSIaz+>$||0doJ0)TA()IuBarqjjpDm;%cyBd;OZ&6PP0O<(%3e5Wz-Bj#M#&6XuWIJ9C$jxnzD~S%s}nk z0S$;Ap-waLK4mI+Qny#_>GwB{!+wrv$yf$AGp!<=P?>UoOMrQz@>wiKfumL1swc;1 z{K~FzZg&0!3Vc{(x9T*ELzNc5J|=Lx9Db)PR#kXBFXhN09dG%1kYTmAhm~MbpZrab zSe>+{QSGY1_9Tc&B5SmHVj%h)mv}gUdxpEhioI}wO009!lS|h@b(K`7fAlTh{A;V8 zeYI;Uc)=W^#U#G^F?FvgWOCe!wyy}M>+m^1mohL+f+G^{jV@fEF*wrA5a9>22}>~P zh|cBFJW(#Hp6TB`uJTX=|KO=u<#|70cCxeUTr$)$l+&{Cd8WK;?wbn~xqn)G-8M{w zj72t7|3q^gSN#o@a%_RCk3M=JG-;>>c2KX{9v4bEUi)Qm2C-Z^T~P4q`dQ+<*yw;& z5;x@?tIWW+q+6oLgT1L#2l^|= zq4Lug4sb3D&ar6NR8D%02G|^I!k6wxd?ke3T9ASL!toA_&zrC^s9Ae4FY&W@pZD2H zql%x*WR3>ArV;tax=NZouKJgp8AakMc-4?Bn5Fw>aGs`wz3OxvrVD4BtLjxer%{Nr zuOOFxs1tXvd0|~Esp|Z=hSBXH2|9>#!suC~2Itrj%!i5D{}U(K&_S8Ip`Pidl7LRF z^HBO`rhtamgo{gYWD&SD2HN1_DWigDPKbJ1iC%NN`1EV>a^nIaPPJB{e3o~%dt5}= zs=|!vP~)cc~k5V zE=Q7#wT^2FO6M`bjRZ?p&MC|RGhF<%HvAj(<$(X*{>Z^?Ogp}l*pn}W7wBpbeJ&FU zl0@RL(Nc~ki;39T$se{0$`)Mqd-o4=WPFHrQ1bRvv)O*yOXKtJzRYM<;Vf0-AV{`8 zfUa3RI{p?iOMIyDyW!jyQDeq2c+XBmbVF<)(W3s|#tvX!z@dsDu^k!}E#)dSw%ario3qADWpD6@;Pg)I;%cp>#rLwO zqLi-A-}bxV89SGtr?NZT+Z0xw*|l>MVbnZr%;7L;$y_v!Ui!*!u1*mQo_P(B8QYiI za9w~KOgd^Qg{>FxXI=JjqQ5~|Y1ZniTExR7d)j7*S?+ASYIbPlCA#V%UE$d;G)b0H zZNb^3zJB8u#d6d>sg!r=Iqgs0wx7D;=Um4;ghRoTON+S|{Q(6;;+6Cb3tc5Va-S7i zB}PzO&!{##m`MWd0{&8(M(1s`k2i_Y{ormOqc>ejk9r+F!o|M+5u^%)zsESg^jmOifO!$V1Z! zmg%tT_f&rxWU=XoP401u0B{twsuE($oI~9V&di7tk5PjX2)D}~TjTN7L8bio zg`}US&jsaQVgAVS)SXLZ6JD3k4*W;Ca3noDw@|T% z94P-nf8#+uisCakFW2O(lA|wvyJZ`wM(HhSUgtUcnp$55ONib*Z1T>c26X?r1;3ij z5c)LRbbQ@j8bBY6KW|5@)9$WbQy}amqQ~Gg zfm>aNGUeeMQ(BciuMr)rU1d|1`4NrM@T*x}#=^@(Var!FmlaTd3=S|uIk{Iq7MXxD z-O*{W25kBb!9+z14BPqo{jB!*cp6?S-m|A?1im8WEI&kXy?x^XG;GoYEh(omFVi0N z84AViBo;yieNh7``A20sm$~mzQ*Wf!FyePHb$Xm7z4pC4ImXbv))?^qj* z7uB14Q-2vu88AQX7d~aXSbi}tFhmTX>wnt1oa(-EFX(xN7=Q8Rf==)|0WVPqAH&>;aiK3oCjJK1sCY?+ z-|VA?eRlCL#jgku>H5wsq?f@9LM^P<%ow?Rx7WBY$W}~-^*aA*xfADiUhj@aORfFg zycLGFlQ7W{V?#j7y-JMLheti$e&r`i@r%w`y?nYd{JE6`CM7C&mhFZuav^oV;#4i1 zD#E$zgUy4Bu3$|7PxgQU!$df@?=I{+k#p1OPG*m^YLzLyaSq*Jh1@+!s~gjI1)Gew z`GlZ&Koi>qAMzM1Mm*5K@HewbR8Q zDAawI`c1y^ce5+je;c_PI^Ct3#9GoTsy~dgktsw!Fbo$!(Iu9EZE7-Q@2W3CM+&aK z9bWgeEd0bn(uM1X(0k=Qw?9?#EaNciaNA_ zHG04$v@wHfHs8C}4pH6|pgWC}ll7)(Kwh2|2NYW*^4CVwhvS1vQUTXBlH~vWl{iQ1 zszOY;Mjq*XY5*p`K|>v&sgIyXkS&V-v(m5t6q7Qa&27l0_!eJa$<101pGZ~ZH;R5g z028Y4-f37W@7f!h&3&N*mpr`gk^<;XE6Ix`o=j9*e!g?CjP;Bpe7-TW znlVPV?ic8Nq{}4u1Ofm~Lv@Uc9{CrUPD({qy8%E7xSjyIe|crT-0RWQebGO?n|t_; z)Mk^pxyR?A7l=ZwJe2-;zVbffP{@dL*<5~0Gq z(b+R>JLG2Zpz7=VyGgUj+HL17n*=51t@HXAIHJ<_2!Y)EN;SF4^>NGmDdMt?-ZLxe;AkMTHZ6yGxrdt1MVT*2P zdwMo!@ACe6gKSH2GrL)wd!>=P7prbtYf?LdP)58?3-pJ@s6jZROE#T+t(G@cecDKgG z7w*!L-Frpj&Hs%y(bqmr#~8ZRYq>`=!6X6ti&yLHBIQ<&qm1Cwye#TC2) z@m1)3NR4oMn_*@A_M`K5tXwV`$Iygddnp|S@_3eQTAC;%LOo)Wi{HT*R?tY|0O<`> zlJ);h!nDtxoJ>~v#EE{MufQJ~%%x_-@Bmik8oE)pelr!5-3Y)4?l&Wm>Qz=fd|=c_ zq77eKaiZAQT-2R}c3z*+FYRm-4)?$=Tbzx)g4%Pw#_CWE2>#PvXje7O0@0!YsQ!=x zQqd2$ww*!u@Y+K0E+m*lDe*)`M)K@a2h0sXkZG8I?1?-eowPT(RKYygetXo8?SMTL z%G&2z$aHCCdeIm&mhp{xs@bKSd3O*0uvVSWho=SZ>XlU83{l(eDML^mR5q|Sr>-7n zcEa3{3A{CPhfR)ZHs87;tR_fTgjB|Ba8DkN`s9D1!uUAF?JkBdl@pHHt~~&h5)m}4 zZ_Dwv9*IT;-Y=LXDI7OAD`Iy}q3dKdoqEMoG$~SuTAwlj^f;aW{OUx|1Q~18-^XmL zttV%=Cr|L0?h?clt8+0tMd#7|SWhTvHpC37uQOP1zH*qbY)ck@0|*5p-c<$Zg+w{!}$H!+1;>VCRhtK z803!CNPeWhsL!MmneUH}FHr9mq20W5OG7(U$} zy&|b*Rk(u(09dUPIq_-I_Mu<8`p}*qBrBGjEdP}g`_Id5*pY)?SJyyy&*X~c)pUaP zG=qC_$`yCR2x+@G=bmF0F`EK9f;IR4niAQ-f!Ndm9m>Ht-)N?;f^vuTWw$Nal?i~BRA9nRxoRbe zy^BGJ)<^3q*0opvV;#;}FXqrtVNsVqvgRlRYXpm#3)J5PefHqG%UJY-C$$f4(aC}E zDk$0Py&C)j>5}@OvJmGorWfUhj4?_6O7B;@#aIVS5U%0-}U6?$P-40wl{Ch%$H zWlG>r^1xGA2BmWYQ&sIr$j0^qLZVj+6$c?3Ob7}`$Z`h`ZOVYIAU-C#(YeMgr^_Ie zn^%|{WG>UB=-sZaFvn3JHFlT0nK4hNA#A5=Ya%|fn1I5*$@5=;Zx~MRJp8h;RZSCk zSCaA@uc~}t&!YyT26KOcp2SU=giH`1(8;VXxTx140Ix@SkANjJ{|SiPpC+N0m*scW z=no0or@Et;W8;~F%y}e|&IQNtT=bPQHfa*8C19%XsGB~L73fO~8*l;wLcQThEK+Ki zG`s&=;8~3E%zUd98EghYk-3gP{7}~aE+#Zzh(QnMY7kxR*d!pqd$&VTjc|+5wRtU& zBHg$`#Ac_>QvE3MhgZGql?F)UV$Ribd4&SmznLdmmxDF_Ezc&m@s&Z(PH z0cZ3`ONH98a8b>ZetCWP3lA1VyGF{MgTy=Qm?XMxFK=^qT}A(Tq|nZ3Fhy1>C(9PW zu%6|^8~Ya?w}|^wpa&R>M%L)Pmje*7!gj(@ee7vE6=%HsALi-s+T`-7NuPtahw8Qb z1+@0K7VXsbZ`Y%{P;L&}io@hw7k?U9P07t>sR^$C6gDPp-qm{xCT&@C!WzzvzT$bB zmi>HEh&y$L%jTf%|9~MkO}N-qu`I$42k;IQ-gFg>{39bpjKLXA&c{U``VjPQRb9wG(6X|=N$|sEfgMbt>grj$2tlIoH)_H~k5rxTGq18n!Q3?K;&&=C z$V<_5TWyt{<<7(1e9IDUuvl!j)uO*hiL4Pxx1qX21;;)GeDw^4^~z2#V4G+T%*=seR`K6R25 z&!QnCaHc@^tJ!Ql>ZeO*9p$+l1xxzL8kG;?SKTWd$iMn=_juiz{NbL@V~DpH@y^Xf zn#gH$%xlIy`#-l1)Jl`$?IgS?)wg-k`WOAP|31TXg>_(!O*osZr%$ zK?Es%IehkxLKOttdRAPFls%MW=?9{A23NI7VBYd&x-EEALsF~vRq|7&+$UDIj`(f$ z^^FLyE?J{d>-kc-IX>s1{FhBNYIZaBwr%9m#bdjPF!MLXiTX%bfzqgn5)`&512jSk zlLth= zbJm4VXK>eU?DaAT`MOHV#y^E~9&I41##C`wjytgG`EI)JVYMHH&-o1esPn)}YXk22 zF1~k$%4Kef9iHX(+9vM;2pN9Hh7;_E`{*WN$j(t zxEDB?)C(42(PxN;rH&iy5jw+xOC0a|HZdrLSI&=qRH*6r)kYWbz0*p*;v-nSJbDMo z=o$Kr2{Q-uD|obYB$}TjhWfDW(e$MT1pS~bf#QINcK?ZmZ+zbjC`h?&h`N((wm zU-6OsXOOR4wC-cilsHM;Zco(mJSVd)HTd(?XbUpTa?qZf#20S}*I8iVc=_kk@=hR~DOiR?0p1Cw%1x?;-~-;GPq z(a>&#-w;}`_V5l$VUQ@yf^O&Q6Dd(;N)#>~q}rDI@P34l;gglpCl;0QHG$yYp1Chj zA0aC2*65ECtELTn87J5A_%#x(oIJh9e`qxfOl$f2syEFXRqR9Wsy-nA677Jk4>u-; zcE*r 0 { + localAddr = addrs[0].IP.String() + } + } + + if ui.signin.Clicked() { + ui.events = append(ui.events, ReauthEvent{}) + } + + if ui.menuClicked(&ui.menu.copy) && localAddr != "" { + ui.copyAddress(gtx, localAddr) + } + + if ui.menuClicked(&ui.menu.reauth) { + ui.events = append(ui.events, ReauthEvent{}) + } + + if ui.menuClicked(&ui.menu.logout) { + ui.events = append(ui.events, LogoutEvent{}) + } + + for len(ui.peers) < len(state.Peers) { + ui.peers = append(ui.peers, widget.Clickable{}) + } + if max := len(state.Peers); len(ui.peers) > max { + ui.peers = ui.peers[:max] + } + + const numHeaders = 5 + n := numHeaders + len(state.Peers) + needsLogin := state.net.State == ipn.NeedsLogin + ui.root.Layout(gtx, n, func(gtx C, idx int) D { + var in layout.Inset + if idx == n-1 { + // The last list element includes the bottom system + // inset. + in.Bottom = sysIns.Bottom + } + return in.Layout(gtx, func(gtx C) D { + switch idx { + case 0: + return ui.layoutTop(gtx, sysIns, &state.net) + case 1: + if netmap == nil { + return D{} + } + return ui.layoutLocal(gtx, sysIns, localName, localAddr) + case 2: + if state.net.State <= ipn.NeedsLogin { + return D{} + } + return ui.layoutSearchbar(gtx, sysIns) + case 3: + if !needsLogin { + return D{} + } + return ui.layoutSignIn(gtx) + case 4: + if needsLogin || state.net.HasInternet { + return D{} + } + return ui.layoutDisconnected(gtx) + default: + if needsLogin { + return D{} + } + pidx := idx - numHeaders + p := &state.Peers[pidx] + if p.Peer == nil { + name := p.Name + if p.Owner == netmap.User { + name = "MY DEVICES" + } + return ui.layoutSection(gtx, sysIns, name) + } else { + clk := &ui.peers[pidx] + return ui.layoutPeer(gtx, sysIns, p, clk) + } + } + }) + }) + + // "Copied" message. + ui.layoutMessage(gtx, sysIns) + + // 3-dots menu. + if ui.menu.show { + ui.layoutMenu(gtx, sysIns, expiry) + } + + // "Get started". + if ui.intro.show { + if ui.intro.start.Clicked() { + ui.store.WriteBool(keyShowIntro, false) + ui.intro.show = false + } + ui.layoutIntro(gtx) + } + + return ui.events +} + +// Dismiss is a widget that detects pointer presses. +type Dismiss struct { +} + +func (d *Dismiss) Add(gtx layout.Context) { + var stack op.StackOp + stack.Push(gtx.Ops) + defer stack.Pop() + pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops) + pointer.InputOp{Tag: d}.Add(gtx.Ops) +} + +func (d *Dismiss) Dismissed(gtx layout.Context) bool { + for _, e := range gtx.Events(d) { + if e, ok := e.(pointer.Event); ok { + if e.Type == pointer.Press { + return true + } + } + } + return false +} + +// layoutSignIn lays out the sign in button(s). +func (ui *UI) layoutSignIn(gtx layout.Context) layout.Dimensions { + return layout.Inset{Top: unit.Dp(48)}.Layout(gtx, func(gtx C) D { + return layout.Center.Layout(gtx, func(gtx C) D { + signin := material.Button(ui.theme, &ui.signin, "Sign In") + signin.Background = rgb(headerColor) + return signin.Layout(gtx) + }) + }) +} + +// layoutDisconnected lays out the "please connect to the internet" +// message. +func (ui *UI) layoutDisconnected(gtx layout.Context) layout.Dimensions { + return layout.UniformInset(unit.Dp(16)).Layout(gtx, func(gtx C) D { + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(func(gtx C) D { + return layout.Inset{Top: unit.Dp(8)}.Layout(gtx, func(gtx C) D { + title := material.H6(ui.theme, "No internet connection") + title.Alignment = text.Middle + return title.Layout(gtx) + }) + }), + layout.Rigid(func(gtx C) D { + return layout.Inset{Top: unit.Dp(8)}.Layout(gtx, func(gtx C) D { + msg := material.Body2(ui.theme, "Tailscale is paused while your device is offline. Please reconnect to the internet.") + msg.Alignment = text.Middle + return msg.Layout(gtx) + }) + }), + ) + }) +} + +// layoutIntro lays out the intro page with the logo and terms. +func (ui *UI) layoutIntro(gtx layout.Context) { + fill{rgb(0x232323)}.Layout(gtx, gtx.Constraints.Max) + layout.Flex{Axis: layout.Vertical}.Layout(gtx, + // 9 dot logo. + layout.Rigid(func(gtx C) D { + return layout.Inset{Top: unit.Dp(80), Bottom: unit.Dp(48)}.Layout(gtx, func(gtx C) D { + return layout.N.Layout(gtx, func(gtx C) D { + sz := gtx.Px(unit.Dp(72)) + drawLogo(gtx.Ops, sz) + return layout.Dimensions{Size: image.Pt(sz, sz)} + }) + }) + }), + // "tailscale". + layout.Rigid(func(gtx C) D { + return layout.N.Layout(gtx, func(gtx C) D { + img := ui.icons.logo + img.Add(gtx.Ops) + sz := img.Size() + aspect := float32(sz.Y) / float32(sz.X) + w := gtx.Px(unit.Dp(200)) + h := int(float32(w)*aspect + .5) + paint.PaintOp{Rect: f32.Rectangle{Max: f32.Pt(float32(w), float32(h))}}.Add(gtx.Ops) + return layout.Dimensions{Size: image.Pt(w, h)} + }) + }), + // Terms. + layout.Rigid(func(gtx C) D { + return layout.Inset{ + Top: unit.Dp(48), + Left: unit.Dp(32), + Right: unit.Dp(32), + }.Layout(gtx, func(gtx C) D { + terms := material.Body2(ui.theme, termsText) + terms.Color = rgb(0xbfbfbf) + terms.Alignment = text.Middle + return terms.Layout(gtx) + }) + }), + // "Get started". + layout.Rigid(func(gtx C) D { + return layout.UniformInset(unit.Dp(16)).Layout(gtx, func(gtx C) D { + start := material.Button(ui.theme, &ui.intro.start, "Get Started") + start.Inset = layout.UniformInset(unit.Dp(16)) + start.CornerRadius = unit.Dp(16) + start.Background = rgb(0x496495) + start.TextSize = unit.Sp(20) + return start.Layout(gtx) + }) + }), + ) +} + +// menuClicked is like btn.Clicked, but also closes the menu if true. +func (ui *UI) menuClicked(btn *widget.Clickable) bool { + cl := btn.Clicked() + if cl { + ui.menu.show = false + } + return cl +} + +// layoutMenu lays out the menu activated by the 3 dots button. +func (ui *UI) layoutMenu(gtx layout.Context, sysIns system.Insets, expiry time.Time) { + ui.menu.dismiss.Add(gtx) + if ui.menu.dismiss.Dismissed(gtx) { + ui.menu.show = false + } + layout.Inset{ + Top: unit.Add(gtx, sysIns.Top, unit.Dp(2)), + Right: unit.Add(gtx, sysIns.Right, unit.Dp(2)), + }.Layout(gtx, func(gtx C) D { + return layout.NE.Layout(gtx, func(gtx C) D { + return Background{Color: argb(0x33000000), CornerRadius: unit.Dp(2)}.Layout(gtx, func(gtx C) D { + return layout.UniformInset(unit.Px(1)).Layout(gtx, func(gtx C) D { + return Background{Color: rgb(0xfafafa), CornerRadius: unit.Px(4)}.Layout(gtx, func(gtx C) D { + menu := &ui.menu + items := []struct { + btn *widget.Clickable + title string + }{ + {title: "Copy My IP Address", btn: &menu.copy}, + {title: "Reauthenticate", btn: &menu.reauth}, + {title: "Log out", btn: &menu.logout}, + } + // Lay out menu items twice; once for + // measuring the widest item, once for actual layout. + var maxWidth int + var minWidth int + children := []layout.FlexChild{ + layout.Rigid(func(gtx C) D { + return layout.Inset{ + Top: unit.Dp(16), + Right: unit.Dp(16), + Left: unit.Dp(16), + Bottom: unit.Dp(4), + }.Layout(gtx, func(gtx C) D { + gtx.Constraints.Min.X = minWidth + var expiryStr string + const fmtStr = time.Stamp + switch { + case expiry.IsZero(): + expiryStr = "Expires: (never)" + case time.Now().After(expiry): + expiryStr = fmt.Sprintf("Expired: %s", expiry.Format(fmtStr)) + default: + expiryStr = fmt.Sprintf("Expires: %s", expiry.Format(fmtStr)) + } + l := material.Caption(ui.theme, expiryStr) + l.Color = rgb(0x8f8f8f) + dims := l.Layout(gtx) + if w := dims.Size.X; w > maxWidth { + maxWidth = w + } + return dims + }) + }), + } + for i := 0; i < len(items); i++ { + it := &items[i] + children = append(children, layout.Rigid(func(gtx C) D { + return material.Clickable(gtx, it.btn, func(gtx C) D { + return layout.UniformInset(unit.Dp(16)).Layout(gtx, func(gtx C) D { + gtx.Constraints.Min.X = minWidth + dims := material.Body1(ui.theme, it.title).Layout(gtx) + if w := dims.Size.X; w > maxWidth { + maxWidth = w + } + return dims + }) + }) + })) + } + f := layout.Flex{Axis: layout.Vertical} + // First pass: record and discard operations + // and determine widest item. + var m op.MacroOp + m.Record(gtx.Ops) + f.Layout(gtx, children...) + m.Stop() + // Second pass: layout items with equal width. + minWidth = maxWidth + return f.Layout(gtx, children...) + }) + }) + }) + }) + }) +} + +func (ui *UI) layoutMessage(gtx layout.Context, sysIns system.Insets) layout.Dimensions { + s := ui.message.text + if s == "" { + return D{} + } + now := gtx.Now() + d := now.Sub(ui.message.t0) + rem := 4*time.Second - d + if rem < 0 { + return D{} + } + op.InvalidateOp{At: now.Add(rem)}.Add(gtx.Ops) + return layout.S.Layout(gtx, func(gtx C) D { + return layout.Inset{Bottom: unit.Add(gtx, sysIns.Bottom, unit.Dp(8))}.Layout(gtx, func(gtx C) D { + return Background{Color: rgb(0x323232), CornerRadius: unit.Dp(5)}.Layout(gtx, func(gtx C) D { + return layout.UniformInset(unit.Dp(12)).Layout(gtx, func(gtx C) D { + l := material.Body2(ui.theme, s) + l.Color = rgb(0xdddddd) + return l.Layout(gtx) + }) + }) + }) + }) +} + +func (ui *UI) showMessage(gtx layout.Context, msg string) { + ui.message.text = msg + ui.message.t0 = gtx.Now() + op.InvalidateOp{}.Add(gtx.Ops) +} + +// layoutPeer lays out a peer name and IP address (e.g. +// "localhost\n100.100.100.101") +func (ui *UI) layoutPeer(gtx layout.Context, sysIns system.Insets, p *UIPeer, clk *widget.Clickable) layout.Dimensions { + for clk.Clicked() { + if addrs := p.Peer.Addresses; len(addrs) > 0 { + ui.copyAddress(gtx, addrs[0].IP.String()) + } + } + return material.Clickable(gtx, clk, func(gtx C) D { + return layout.Inset{ + Top: unit.Dp(8), + Right: unit.Max(gtx, sysIns.Right, unit.Dp(16)), + Left: unit.Max(gtx, sysIns.Left, unit.Dp(16)), + Bottom: unit.Dp(8), + }.Layout(gtx, func(gtx C) D { + gtx.Constraints.Min.X = gtx.Constraints.Max.X + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(func(gtx C) D { + return layout.Inset{Bottom: unit.Dp(4)}.Layout(gtx, func(gtx C) D { + name := p.Peer.Hostinfo.Hostname + if name == "" { + name = p.Peer.ID.String() + } + return material.H6(ui.theme, name).Layout(gtx) + }) + }), + layout.Rigid(func(gtx C) D { + var addrs []string + for _, addr := range p.Peer.Addresses { + addrs = append(addrs, addr.IP.String()) + } + l := material.Body2(ui.theme, strings.Join(addrs, ",")) + l.Color = rgb(0x434343) + return l.Layout(gtx) + }), + ) + }) + }) +} + +// layoutSection lays out a section title (e.g. "My devices"). +func (ui *UI) layoutSection(gtx layout.Context, sysIns system.Insets, title string) layout.Dimensions { + return Background{Color: rgb(0xe1e0e9)}.Layout(gtx, func(gtx C) D { + return layout.Inset{ + Top: unit.Dp(16), + Right: unit.Max(gtx, sysIns.Right, unit.Dp(16)), + Left: unit.Max(gtx, sysIns.Left, unit.Dp(16)), + Bottom: unit.Dp(16), + }.Layout(gtx, func(gtx C) D { + l := material.Body1(ui.theme, title) + l.Color = rgb(0x6f797d) + return l.Layout(gtx) + }) + }) +} + +// layoutTop lays out the top controls: toggle, status and menu dots. +func (ui *UI) layoutTop(gtx layout.Context, sysIns system.Insets, state *NetworkState) layout.Dimensions { + in := layout.Inset{ + Top: unit.Dp(16), + Bottom: unit.Dp(16), + } + return Background{Color: rgb(headerColor)}.Layout(gtx, func(gtx C) D { + return layout.Inset{ + Top: sysIns.Top, + Right: unit.Max(gtx, sysIns.Right, unit.Dp(8)), + Left: unit.Max(gtx, sysIns.Left, unit.Dp(16)), + }.Layout(gtx, func(gtx C) D { + return layout.Flex{Alignment: layout.Middle}.Layout(gtx, + layout.Rigid(func(gtx C) D { + return in.Layout(gtx, func(gtx C) D { + sw := material.Switch(ui.theme, &ui.enabled) + sw.Color = rgb(white) + return sw.Layout(gtx) + }) + }), + layout.Flexed(1, func(gtx C) D { + return in.Layout(gtx, func(gtx C) D { + return layout.Inset{Left: unit.Dp(16)}.Layout(gtx, func(gtx C) D { + lbl := material.Body1(ui.theme, statusString(state.State)) + lbl.Color = rgb(0xffffff) + return lbl.Layout(gtx) + }) + }) + }), + layout.Rigid(func(gtx C) D { + if state.State <= ipn.NeedsLogin { + return D{} + } + return material.Clickable(gtx, &ui.menu.open, func(gtx C) D { + return layout.UniformInset(unit.Dp(8)).Layout(gtx, func(gtx C) D { + return ui.icons.more.Layout(gtx, unit.Dp(24)) + }) + }) + }), + ) + }) + }) +} + +func statusString(state ipn.State) string { + switch state { + case ipn.Stopped: + return "Stopped" + case ipn.Starting: + return "Starting..." + case ipn.Running: + return "Active" + case ipn.NeedsMachineAuth: + return "Awaiting Approval" + case ipn.NeedsLogin: + return "Needs Authentication" + default: + return "Loading..." + } +} + +func (ui *UI) copyAddress(gtx layout.Context, addr string) { + ui.events = append(ui.events, CopyEvent{Text: addr}) + ui.showMessage(gtx, fmt.Sprintf("Copied %s", addr)) +} + +// layoutLocal lays out the information box about the local node's +// name and IP address. +func (ui *UI) layoutLocal(gtx layout.Context, sysIns system.Insets, host, addr string) layout.Dimensions { + for ui.self.Clicked() { + ui.copyAddress(gtx, addr) + } + return Background{Color: rgb(headerColor)}.Layout(gtx, func(gtx C) D { + return layout.Inset{ + Right: unit.Max(gtx, sysIns.Right, unit.Dp(8)), + Left: unit.Max(gtx, sysIns.Left, unit.Dp(8)), + Bottom: unit.Dp(8), + }.Layout(gtx, func(gtx C) D { + return Background{Color: rgb(infoColor), CornerRadius: unit.Dp(8)}.Layout(gtx, func(gtx C) D { + return material.Clickable(gtx, &ui.self, func(gtx C) D { + return layout.UniformInset(unit.Dp(16)).Layout(gtx, func(gtx C) D { + gtx.Constraints.Min.X = gtx.Constraints.Max.X + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(func(gtx C) D { + return layout.Inset{Bottom: unit.Dp(4)}.Layout(gtx, func(gtx C) D { + name := material.H6(ui.theme, host) + name.Color = ui.theme.Color.InvText + return name.Layout(gtx) + }) + }), + layout.Rigid(func(gtx C) D { + name := material.Body2(ui.theme, addr) + name.Color = rgb(0xc5ccd9) + return name.Layout(gtx) + }), + ) + }) + }) + }) + }) + }) +} + +func (ui *UI) layoutSearchbar(gtx layout.Context, sysIns system.Insets) layout.Dimensions { + return Background{Color: rgb(0xf0eff6)}.Layout(gtx, func(gtx C) D { + return layout.Inset{ + Top: unit.Dp(8), + Right: unit.Max(gtx, sysIns.Right, unit.Dp(8)), + Left: unit.Max(gtx, sysIns.Left, unit.Dp(8)), + Bottom: unit.Dp(8), + }.Layout(gtx, func(gtx C) D { + return Background{Color: rgb(0xe3e2ea), CornerRadius: unit.Dp(8)}.Layout(gtx, func(gtx C) D { + return layout.UniformInset(unit.Dp(8)).Layout(gtx, func(gtx C) D { + return layout.Flex{Alignment: layout.Middle}.Layout(gtx, + layout.Rigid(func(gtx C) D { + return ui.icons.search.Layout(gtx, unit.Dp(24)) + }), + layout.Flexed(1, + material.Editor(ui.theme, &ui.search, "Search by hostname...").Layout, + ), + ) + }) + }) + }) + }) +} + +// drawLogo draws the Tailscale logo using vector operations. +func drawLogo(ops *op.Ops, size int) { + scale := float32(size) / 680 + discDia := 170 * scale + off := 172 * 1.5 * scale + tx := op.TransformOp{}.Offset(f32.Pt(off, 0)) + ty := op.TransformOp{}.Offset(f32.Pt(0, off)) + + var st op.StackOp + st.Push(ops) + defer st.Pop() + + var row op.StackOp + // First row of discs. + row.Push(ops) + drawDisc(ops, discDia, rgb(0x54514d)) + tx.Add(ops) + drawDisc(ops, discDia, rgb(0x54514d)) + tx.Add(ops) + drawDisc(ops, discDia, rgb(0x54514d)) + row.Pop() + + ty.Add(ops) + // Second row. + row.Push(ops) + drawDisc(ops, discDia, rgb(0xfffdfa)) + tx.Add(ops) + drawDisc(ops, discDia, rgb(0xfffdfa)) + tx.Add(ops) + drawDisc(ops, discDia, rgb(0xfffdfa)) + row.Pop() + + ty.Add(ops) + // Third row. + row.Push(ops) + drawDisc(ops, discDia, rgb(0x54514d)) + tx.Add(ops) + drawDisc(ops, discDia, rgb(0xfffdfa)) + tx.Add(ops) + drawDisc(ops, discDia, rgb(0x54514d)) + row.Pop() +} + +func drawDisc(ops *op.Ops, radius float32, col color.RGBA) { + var st op.StackOp + st.Push(ops) + defer st.Pop() + r2 := radius * .5 + dr := f32.Rectangle{Max: f32.Pt(radius, radius)} + clip.Rect{ + Rect: dr, + NE: r2, NW: r2, SE: r2, SW: r2, + }.Op(ops).Add(ops) + paint.ColorOp{Color: col}.Add(ops) + paint.PaintOp{Rect: dr}.Add(ops) +} + +// background lays out a widget and draws a color background behind +// it. +type Background struct { + Color color.RGBA + CornerRadius unit.Value +} + +func (b Background) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions { + var m op.MacroOp + m.Record(gtx.Ops) + dims := w(gtx) + sz := dims.Size + m.Stop() + // Clip corners, if any. + if r := gtx.Px(b.CornerRadius); r > 0 { + rr := float32(r) + clip.Rect{ + Rect: f32.Rectangle{Max: f32.Point{ + X: float32(sz.X), + Y: float32(sz.Y), + }}, + NE: rr, NW: rr, SE: rr, SW: rr, + }.Op(gtx.Ops).Add(gtx.Ops) + } + fill{b.Color}.Layout(gtx, sz) + m.Add() + return dims +} + +type fill struct { + col color.RGBA +} + +func (f fill) Layout(gtx layout.Context, sz image.Point) layout.Dimensions { + var st op.StackOp + st.Push(gtx.Ops) + defer st.Pop() + dr := f32.Rectangle{Max: layout.FPt(sz)} + paint.ColorOp{Color: f.col}.Add(gtx.Ops) + paint.PaintOp{Rect: dr}.Add(gtx.Ops) + return layout.Dimensions{Size: sz} +} + +func rgb(c uint32) color.RGBA { + return argb((0xff << 24) | c) +} + +func argb(c uint32) color.RGBA { + return color.RGBA{A: uint8(c >> 24), R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c)} +} + +const termsText = `Tailscale is a mesh VPN for securely connecting your devices. All connections are device-to-device, so we never see your data. + +We collect and use your email address and name, as well as your device name, OS version, and IP address in order to help you to connect your devices and manage your settings. We log when you are connected to your network.` diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..392cd3c --- /dev/null +++ b/go.mod @@ -0,0 +1,12 @@ +module tailscale.com/tailscale-android + +go 1.14 + +require ( + gioui.org v0.0.0-20200524174833-ad93e3212824 + gioui.org/cmd v0.0.0-20200508063126-0ad8f85c05e7 // indirect + github.com/tailscale/wireguard-go v0.0.0-20200515231107-62868271d710 + golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3 + golang.org/x/sys v0.0.0-20200501052902-10377860bb8e + tailscale.com v0.98.1-0.20200524053159-e6b84f2159ba +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..c0a6f3b --- /dev/null +++ b/go.sum @@ -0,0 +1,187 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +gioui.org v0.0.0-20200503190452-8d9612f9aa46/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04= +gioui.org v0.0.0-20200524174833-ad93e3212824 h1:vQP8qwWQXun8lXmj707eZcsuem2X6aF3w0z8CnrL8PI= +gioui.org v0.0.0-20200524174833-ad93e3212824/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04= +gioui.org/cmd v0.0.0-20200502185633-fa7f9d3ba897 h1:o/P0x46brgIfnKt9QpQs51o30wxAGWgnq1kECJgJ+s4= +gioui.org/cmd v0.0.0-20200502185633-fa7f9d3ba897/go.mod h1:MA/AKwBq+dTw6ajU3Vtju89BJ6a/zWIg8JLXC2nja08= +gioui.org/cmd v0.0.0-20200508063126-0ad8f85c05e7 h1:gziosxqkR5CpjUTPWQKmkLFwpUMRGNuMcmCvurF58hg= +gioui.org/cmd v0.0.0-20200508063126-0ad8f85c05e7/go.mod h1:pSCbdDbqNf8zuUHR3zv2om4R2946FUJBOI618vt5AoE= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/apenwarr/fixconsole v0.0.0-20191012055117-5a9f6489cc29/go.mod h1:JYWahgHer+Z2xbsgHPtaDYVWzeHDminu+YIBWkxpCAY= +github.com/apenwarr/w32 v0.0.0-20190407065021-aa00fece76ab/go.mod h1:nfFtvHn2Hgs9G1u0/J6LHQv//EksNC+7G8vXmd1VTJ8= +github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= +github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A= +github.com/chromedp/cdproto v0.0.0-20191114225735-6626966fbae4/go.mod h1:PfAWWKJqjlGFYJEidUM6aVIWPr0EpobeyVWEEmplX7g= +github.com/chromedp/chromedp v0.5.2/go.mod h1:rsTo/xRo23KZZwFmWk2Ui79rBaVRRATCjLzNQlOFSiA= +github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-bindata/go-bindata v1.0.0 h1:DZ34txDXWn1DyWa+vQf7V9ANc2ILTtrEjtlsdJRF26M= +github.com/go-bindata/go-bindata v3.1.2+incompatible h1:5vjJMVhowQdPzjE1LdxyFF7YFTXg5IgGVW4gBr5IbvE= +github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= +github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg= +github.com/goreleaser/nfpm v1.1.10/go.mod h1:oOcoGRVwvKIODz57NUfiRwFWGfn00NXdgnn6MrYtO5k= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= +github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4 h1:nwOc1YaOrYJ37sEBrtWZrdqzK22hiJs3GpDmP3sR2Yw= +github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.9.8 h1:VMAMUUOh+gaxKTMk+zqbjsSjsIcUcL/LF4o63i82QyA= +github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/knq/sysutil v0.0.0-20191005231841-15668db23d08/go.mod h1:dFWs1zEqDjFtnBXsd1vPOZaLsESovai349994nHx3e0= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= +github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= +github.com/mdlayher/netlink v1.1.0 h1:mpdLgm+brq10nI9zM1BpX1kpDbh3NLl3RSnVq6ZSkfg= +github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= +github.com/peterbourgon/ff v1.7.0/go.mod h1:/KKxnU5cBj4w21jEMj4Rway/kslRP6XAOHh7CH8AyAM= +github.com/peterbourgon/ff/v2 v2.0.0/go.mod h1:xjwr+t+SjWm4L46fcj/D+Ap+6ME7+HqFzaP22pP5Ggk= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tailscale/hujson v0.0.0-20190930033718-5098e564d9b3/go.mod h1:STqf+YV0ADdzk4ejtXFsGqDpATP9JoL0OB+hiFQbkdE= +github.com/tailscale/winipcfg-go v0.0.0-20200213045944-185b07f8233f/go.mod h1:x880GWw5fvrl2DVTQ04ttXQD4DuppTt1Yz6wLibbjNE= +github.com/tailscale/winipcfg-go v0.0.0-20200413171540-609dcf2df55f h1:uFj5bslHsMzxIM8UTjAhq4VXeo6GfNW91rpoh/WMJaY= +github.com/tailscale/winipcfg-go v0.0.0-20200413171540-609dcf2df55f/go.mod h1:x880GWw5fvrl2DVTQ04ttXQD4DuppTt1Yz6wLibbjNE= +github.com/tailscale/wireguard-go v0.0.0-20200317013323-239518935266 h1:Dhtc6KmHWCBWukI47jywK+9vIxFQxFIL5qxSIgg7QdQ= +github.com/tailscale/wireguard-go v0.0.0-20200317013323-239518935266/go.mod h1:JPm5cTfu1K+qDFRbiHy0sOlHUylYQbpl356sdYFD8V4= +github.com/tailscale/wireguard-go v0.0.0-20200416194755-23aababa2084 h1:8FolyyuEIqny/MUD2VrTE8Damx0bG+UGix7OXXm0EeY= +github.com/tailscale/wireguard-go v0.0.0-20200416194755-23aababa2084/go.mod h1:JPm5cTfu1K+qDFRbiHy0sOlHUylYQbpl356sdYFD8V4= +github.com/tailscale/wireguard-go v0.0.0-20200424121617-8d10f231531a h1:HMkTFyhcvZaKf7+7T76rks4HqB83fptUemBIfLGI6TM= +github.com/tailscale/wireguard-go v0.0.0-20200424121617-8d10f231531a/go.mod h1:JPm5cTfu1K+qDFRbiHy0sOlHUylYQbpl356sdYFD8V4= +github.com/tailscale/wireguard-go v0.0.0-20200515231107-62868271d710 h1:I6aq3tOYbZob9uwhGpr7R266qTeU9PFqS6NnpfCqEzo= +github.com/tailscale/wireguard-go v0.0.0-20200515231107-62868271d710/go.mod h1:JPm5cTfu1K+qDFRbiHy0sOlHUylYQbpl356sdYFD8V4= +github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0= +github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8= +github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +go4.org/mem v0.0.0-20200411205429-f77f31c81751 h1:sgGPu7KkyLjyOYOwKFHCtnfosdSuM5q2Gud23Y/+nzw= +go4.org/mem v0.0.0-20200411205429-f77f31c81751/go.mod h1:NEYvpHWemiG/E5UWfaN5QAIGZeT1sa0Z2UNk6oeMb/k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA= +golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6 h1:TjszyFsQsyZNHwdVdZ5m7bjmreu0znc2kRYsEml9/Ww= +golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3 h1:n9HxLrNxWWtEb1cA950nuEEj3QnKbtsCJ6KjcgisNUs= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190310054646-10058d7d4faa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200316230553-a7d97aace0b0 h1:4Khi5GeNOkZS5DqSBRn4Sy7BE6GuxwOqARPqfurkdNk= +golang.org/x/sys v0.0.0-20200316230553-a7d97aace0b0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d h1:62ap6LNOjDU6uGmKXHJbSfciMoV+FeI1sRXx/pLDL44= +golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e h1:hq86ru83GdWTlfQFZGO4nZJTU4Bs2wfHl8oFHRaXsfc= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e h1:1xWUkZQQ9Z9UuZgNaIR6OQOE7rUFglXUUBZlO+dGg6I= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d h1:/iIZNFGxc/a7C3yWjGcnboV+Tkc7mxr+p6fDztwoxuM= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gortc.io/stun v1.22.1 h1:96mOdDATYRqhYB+TZdenWBg4CzL2Ye5kPyBXQ8KAB+8= +gortc.io/stun v1.22.1/go.mod h1:XD5lpONVyjvV3BgOyJFNo0iv6R2oZB4L+weMqxts+zg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +inet.af/netaddr v0.0.0-20200417213433-f9e5bcc2d6ea h1:DpXewrGVf9+vvYQFrNGj9v34bXMuTVQv+2wuULTNV8I= +inet.af/netaddr v0.0.0-20200417213433-f9e5bcc2d6ea/go.mod h1:qqYzz/2whtrbWJvt+DNWQyvekNN4ePQZcg2xc2/Yjww= +inet.af/netaddr v0.0.0-20200430175045-5aaf2097c7fc h1:We3b/z+7i9LV4Ls0yWve5vYIlnAPSPeqxKVgZseRDBs= +inet.af/netaddr v0.0.0-20200430175045-5aaf2097c7fc/go.mod h1:qqYzz/2whtrbWJvt+DNWQyvekNN4ePQZcg2xc2/Yjww= +rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w= +rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo= +tailscale.com v0.96.2-0.20200501084119-0068e574073e h1:Jaw1TwXru/ulQmsP9b51o2eYoDBYoMaZP6e/yJc0ZaI= +tailscale.com v0.96.2-0.20200501084119-0068e574073e/go.mod h1:lSEmuWEgZd+EAwk+m6d4Zmk7I5UsEBUGyBBzpf90XV8= +tailscale.com v0.96.2-0.20200501140524-7b901fdbbc51 h1:JlkWBx63N3Su6NnEu0+hlNzud+wqprlR/QxHhmySAzg= +tailscale.com v0.96.2-0.20200501140524-7b901fdbbc51/go.mod h1:lSEmuWEgZd+EAwk+m6d4Zmk7I5UsEBUGyBBzpf90XV8= +tailscale.com v0.98.1-0.20200524053159-e6b84f2159ba h1:P+BSN4UNWBuehhB9s17WDynwjVxgQqV+asPThTiMOwg= +tailscale.com v0.98.1-0.20200524053159-e6b84f2159ba/go.mod h1:qhqIOURjwBji/8sD4E3HmTou3eyp/2HfFuPLdjs7ge8= diff --git a/jni/gojni.h b/jni/gojni.h new file mode 100644 index 0000000..6895305 --- /dev/null +++ b/jni/gojni.h @@ -0,0 +1,25 @@ +__attribute__ ((visibility ("hidden"))) jint _jni_GetEnv(JavaVM *vm, JNIEnv **env, jint version); +__attribute__ ((visibility ("hidden"))) jint _jni_AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args); +__attribute__ ((visibility ("hidden"))) jint _jni_DetachCurrentThread(JavaVM *vm); +__attribute__ ((visibility ("hidden"))) jclass _jni_FindClass(JNIEnv *env, const char *name); +__attribute__ ((visibility ("hidden"))) jthrowable _jni_ExceptionOccurred(JNIEnv *env); +__attribute__ ((visibility ("hidden"))) void _jni_ExceptionClear(JNIEnv *env); +__attribute__ ((visibility ("hidden"))) jclass _jni_GetObjectClass(JNIEnv *env, jobject obj); +__attribute__ ((visibility ("hidden"))) jmethodID _jni_GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig); +__attribute__ ((visibility ("hidden"))) jmethodID _jni_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig); +__attribute__ ((visibility ("hidden"))) jsize _jni_GetStringLength(JNIEnv *env, jstring str); +__attribute__ ((visibility ("hidden"))) const jchar *_jni_GetStringChars(JNIEnv *env, jstring str); +__attribute__ ((visibility ("hidden"))) jstring _jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len); +__attribute__ ((visibility ("hidden"))) jboolean _jni_IsSameObject(JNIEnv *env, jobject ref1, jobject ref2); +__attribute__ ((visibility ("hidden"))) jobject _jni_NewGlobalRef(JNIEnv *env, jobject obj); +__attribute__ ((visibility ("hidden"))) void _jni_DeleteGlobalRef(JNIEnv *env, jobject obj); +__attribute__ ((visibility ("hidden"))) jint _jni_CallStaticIntMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args); +__attribute__ ((visibility ("hidden"))) jobject _jni_CallStaticObjectMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args); +__attribute__ ((visibility ("hidden"))) void _jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args); +__attribute__ ((visibility ("hidden"))) jobject _jni_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID method, jvalue *args); +__attribute__ ((visibility ("hidden"))) jint _jni_CallIntMethodA(JNIEnv *env, jobject obj, jmethodID method, jvalue *args); +__attribute__ ((visibility ("hidden"))) void _jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID method, jvalue *args); +__attribute__ ((visibility ("hidden"))) jbyteArray _jni_NewByteArray(JNIEnv *env, jsize length); +__attribute__ ((visibility ("hidden"))) jbyte *_jni_GetByteArrayElements(JNIEnv *env, jbyteArray arr); +__attribute__ ((visibility ("hidden"))) void _jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *elems, jint mode); +__attribute__ ((visibility ("hidden"))) jsize _jni_GetArrayLength(JNIEnv *env, jarray arr); diff --git a/jni/jni.c b/jni/jni.c new file mode 100644 index 0000000..45b1d27 --- /dev/null +++ b/jni/jni.c @@ -0,0 +1,101 @@ +#include + +jint _jni_AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args) { + return (*vm)->AttachCurrentThread(vm, p_env, thr_args); +} + +jint _jni_DetachCurrentThread(JavaVM *vm) { + return (*vm)->DetachCurrentThread(vm); +} + +jint _jni_GetEnv(JavaVM *vm, JNIEnv **env, jint version) { + return (*vm)->GetEnv(vm, (void **)env, version); +} + +jclass _jni_FindClass(JNIEnv *env, const char *name) { + return (*env)->FindClass(env, name); +} + +jthrowable _jni_ExceptionOccurred(JNIEnv *env) { + return (*env)->ExceptionOccurred(env); +} + +void _jni_ExceptionClear(JNIEnv *env) { + (*env)->ExceptionClear(env); +} + +jclass _jni_GetObjectClass(JNIEnv *env, jobject obj) { + return (*env)->GetObjectClass(env, obj); +} + +jmethodID _jni_GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) { + return (*env)->GetMethodID(env, clazz, name, sig); +} + +jmethodID _jni_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) { + return (*env)->GetStaticMethodID(env, clazz, name, sig); +} + +jsize _jni_GetStringLength(JNIEnv *env, jstring str) { + return (*env)->GetStringLength(env, str); +} + +const jchar *_jni_GetStringChars(JNIEnv *env, jstring str) { + return (*env)->GetStringChars(env, str, NULL); +} + +jstring _jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len) { + return (*env)->NewString(env, unicodeChars, len); +} + +jboolean _jni_IsSameObject(JNIEnv *env, jobject ref1, jobject ref2) { + return (*env)->IsSameObject(env, ref1, ref2); +} + +jobject _jni_NewGlobalRef(JNIEnv *env, jobject obj) { + return (*env)->NewGlobalRef(env, obj); +} + +void _jni_DeleteGlobalRef(JNIEnv *env, jobject obj) { + (*env)->DeleteGlobalRef(env, obj); +} + +void _jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args) { + (*env)->CallStaticVoidMethodA(env, cls, method, args); +} + +jint _jni_CallStaticIntMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args) { + return (*env)->CallStaticIntMethodA(env, cls, method, args); +} + +jobject _jni_CallStaticObjectMethodA(JNIEnv *env, jclass cls, jmethodID method, jvalue *args) { + return (*env)->CallStaticObjectMethodA(env, cls, method, args); +} + +jobject _jni_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID method, jvalue *args) { + return (*env)->CallObjectMethodA(env, obj, method, args); +} + +jint _jni_CallIntMethodA(JNIEnv *env, jobject obj, jmethodID method, jvalue *args) { + return (*env)->CallIntMethodA(env, obj, method, args); +} + +void _jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID method, jvalue *args) { + (*env)->CallVoidMethodA(env, obj, method, args); +} + +jbyteArray _jni_NewByteArray(JNIEnv *env, jsize length) { + return (*env)->NewByteArray(env, length); +} + +jbyte *_jni_GetByteArrayElements(JNIEnv *env, jbyteArray arr) { + return (*env)->GetByteArrayElements(env, arr, NULL); +} + +void _jni_ReleaseByteArrayElements(JNIEnv *env, jbyteArray arr, jbyte *elems, jint mode) { + (*env)->ReleaseByteArrayElements(env, arr, elems, mode); +} + +jsize _jni_GetArrayLength(JNIEnv *env, jarray arr) { + return (*env)->GetArrayLength(env, arr); +} diff --git a/jni/jni.go b/jni/jni.go new file mode 100644 index 0000000..bcc25db --- /dev/null +++ b/jni/jni.go @@ -0,0 +1,267 @@ +// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package jni + +// Package jni implements various helper functions for communicating with the Android JVM +// though JNI. + +import ( + "errors" + "fmt" + "reflect" + "runtime" + "unicode/utf16" + "unsafe" +) + +/* +#cgo CFLAGS: -Wall + +#include +#include + +#include "gojni.h" +*/ +import "C" + +type JVM struct { + jvm *C.JavaVM +} + +type Env struct { + env *C.JNIEnv +} + +type ( + Class C.jclass + Object C.jobject + MethodID C.jmethodID + String C.jstring + ByteArray C.jbyteArray + Value uint64 // All JNI types fit into 64-bits. +) + +func JVMFor(jvmPtr uintptr) JVM { + return JVM{ + jvm: (*C.JavaVM)(unsafe.Pointer(jvmPtr)), + } +} + +func EnvFor(envPtr uintptr) Env { + return Env{ + env: (*C.JNIEnv)(unsafe.Pointer(envPtr)), + } +} + +// Do invokes a function with a temporary JVM environment. The +// environment is not valid after the function returns. +func Do(vm JVM, f func(env Env) error) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + var env *C.JNIEnv + var detach bool + if res := C._jni_GetEnv(vm.jvm, &env, C.JNI_VERSION_1_6); res != C.JNI_OK { + if res != C.JNI_EDETACHED { + panic(fmt.Errorf("JNI GetEnv failed with error %d", res)) + } + if C._jni_AttachCurrentThread(vm.jvm, &env, nil) != C.JNI_OK { + panic(errors.New("runInJVM: AttachCurrentThread failed")) + } + detach = true + } + + if detach { + defer func() { + C._jni_DetachCurrentThread(vm.jvm) + }() + } + return f(Env{env}) +} + +func varArgs(args []Value) *C.jvalue { + if len(args) == 0 { + return nil + } + return (*C.jvalue)(unsafe.Pointer(&args[0])) +} + +func IsSameObject(e Env, ref1, ref2 Object) bool { + same := C._jni_IsSameObject(e.env, C.jobject(ref1), C.jobject(ref2)) + return same == C.JNI_TRUE +} + +func CallStaticIntMethod(e Env, cls Class, method MethodID, args ...Value) (int, error) { + res := C._jni_CallStaticIntMethodA(e.env, C.jclass(cls), C.jmethodID(method), varArgs(args)) + return int(res), exception(e) +} + +func CallStaticVoidMethod(e Env, cls Class, method MethodID, args ...Value) error { + C._jni_CallStaticVoidMethodA(e.env, C.jclass(cls), C.jmethodID(method), varArgs(args)) + return exception(e) +} + +func CallVoidMethod(e Env, obj Object, method MethodID, args ...Value) error { + C._jni_CallVoidMethodA(e.env, C.jobject(obj), C.jmethodID(method), varArgs(args)) + return exception(e) +} + +func CallStaticObjectMethod(e Env, cls Class, method MethodID, args ...Value) (Object, error) { + res := C._jni_CallStaticObjectMethodA(e.env, C.jclass(cls), C.jmethodID(method), varArgs(args)) + return Object(res), exception(e) +} + +func CallObjectMethod(e Env, obj Object, method MethodID, args ...Value) (Object, error) { + res := C._jni_CallObjectMethodA(e.env, C.jobject(obj), C.jmethodID(method), varArgs(args)) + return Object(res), exception(e) +} + +func CallIntMethod(e Env, obj Object, method MethodID, args ...Value) (int32, error) { + res := C._jni_CallIntMethodA(e.env, C.jobject(obj), C.jmethodID(method), varArgs(args)) + return int32(res), exception(e) +} + +// GetByteArrayElements returns the contents of the array. +func GetByteArrayElements(e Env, jarr ByteArray) []byte { + size := C._jni_GetArrayLength(e.env, C.jarray(jarr)) + elems := C._jni_GetByteArrayElements(e.env, C.jbyteArray(jarr)) + defer C._jni_ReleaseByteArrayElements(e.env, C.jbyteArray(jarr), elems, 0) + backing := (*(*[1 << 30]byte)(unsafe.Pointer(elems)))[:size:size] + s := make([]byte, len(backing)) + copy(s, backing) + return s +} + +// NewByteArray allocates a Java byte array with the content. It +// panics if the allocation fails. +func NewByteArray(e Env, content []byte) ByteArray { + jarr := C._jni_NewByteArray(e.env, C.jsize(len(content))) + if jarr == 0 { + panic(fmt.Errorf("jni: NewByteArray(%d) failed", len(content))) + } + elems := C._jni_GetByteArrayElements(e.env, jarr) + defer C._jni_ReleaseByteArrayElements(e.env, jarr, elems, 0) + backing := (*(*[1 << 30]byte)(unsafe.Pointer(elems)))[:len(content):len(content)] + copy(backing, content) + return ByteArray(jarr) +} + +// ClassLoader returns a reference to the Java ClassLoader associated +// with obj. +func ClassLoaderFor(e Env, obj Object) Object { + cls := GetObjectClass(e, obj) + getClassLoader := GetMethodID(e, cls, "getClassLoader", "()Ljava/lang/ClassLoader;") + clsLoader, err := CallObjectMethod(e, Object(obj), getClassLoader) + if err != nil { + // Class.getClassLoader should never fail. + panic(err) + } + return Object(clsLoader) +} + +// LoadClass invokes the underlying ClassLoader's loadClass method and +// returns the class. +func LoadClass(e Env, loader Object, class string) (Class, error) { + cls := GetObjectClass(e, loader) + loadClass := GetMethodID(e, cls, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;") + name := JavaString(e, class) + loaded, err := CallObjectMethod(e, loader, loadClass, Value(name)) + if err != nil { + return 0, err + } + return Class(loaded), exception(e) +} + +// exception returns an error corresponding to the pending +// exception, and clears it. exceptionError returns nil if no +// exception is pending. +func exception(e Env) error { + thr := C._jni_ExceptionOccurred(e.env) + if thr == 0 { + return nil + } + C._jni_ExceptionClear(e.env) + cls := GetObjectClass(e, Object(thr)) + toString := GetMethodID(e, cls, "toString", "()Ljava/lang/String;") + msg, err := CallObjectMethod(e, Object(thr), toString) + if err != nil { + return err + } + return errors.New(GoString(e, String(msg))) +} + +// GetObjectClass returns the Java Class for an Object. +func GetObjectClass(e Env, obj Object) Class { + if obj == 0 { + panic("null object") + } + cls := C._jni_GetObjectClass(e.env, C.jobject(obj)) + if err := exception(e); err != nil { + // GetObjectClass should never fail. + panic(err) + } + return Class(cls) +} + +// GetStaticMethodID returns the id for a static method. It panics if the method +// wasn't found. +func GetStaticMethodID(e Env, cls Class, name, signature string) MethodID { + mname := C.CString(name) + defer C.free(unsafe.Pointer(mname)) + msig := C.CString(signature) + defer C.free(unsafe.Pointer(msig)) + m := C._jni_GetStaticMethodID(e.env, C.jclass(cls), mname, msig) + if err := exception(e); err != nil { + panic(err) + } + return MethodID(m) +} + +// GetMethodID returns the id for a method. It panics if the method +// wasn't found. +func GetMethodID(e Env, cls Class, name, signature string) MethodID { + mname := C.CString(name) + defer C.free(unsafe.Pointer(mname)) + msig := C.CString(signature) + defer C.free(unsafe.Pointer(msig)) + m := C._jni_GetMethodID(e.env, C.jclass(cls), mname, msig) + if err := exception(e); err != nil { + panic(err) + } + return MethodID(m) +} + +func NewGlobalRef(e Env, obj Object) Object { + return Object(C._jni_NewGlobalRef(e.env, C.jobject(obj))) +} + +func DeleteGlobalRef(e Env, obj Object) { + C._jni_DeleteGlobalRef(e.env, C.jobject(obj)) +} + +// JavaString converts the string to a JVM jstring. +func JavaString(e Env, str string) String { + if str == "" { + return 0 + } + utf16Chars := utf16.Encode([]rune(str)) + res := C._jni_NewString(e.env, (*C.jchar)(unsafe.Pointer(&utf16Chars[0])), C.int(len(utf16Chars))) + return String(res) +} + +// GoString converts the JVM jstring to a Go string. +func GoString(e Env, str String) string { + if str == 0 { + return "" + } + strlen := C._jni_GetStringLength(e.env, C.jstring(str)) + chars := C._jni_GetStringChars(e.env, C.jstring(str)) + var utf16Chars []uint16 + hdr := (*reflect.SliceHeader)(unsafe.Pointer(&utf16Chars)) + hdr.Data = uintptr(unsafe.Pointer(chars)) + hdr.Cap = int(strlen) + hdr.Len = int(strlen) + utf8 := utf16.Decode(utf16Chars) + return string(utf8) +}