├── .dockerignore
├── src
├── translate
│ ├── __init__.py
│ ├── languages
│ │ ├── en.json
│ │ ├── it.json
│ │ ├── fa.json
│ │ ├── de.json
│ │ ├── pt-br.json
│ │ ├── zh-tw.json
│ │ └── zh.json
│ └── Translate.py
├── bug.png
├── icon.png
├── Roboto.ttf
├── splash.png
├── TextMeOne.ttf
├── Roboto-Regular.otf
├── DroidSansFallback.ttf
├── watchdog_1.py
├── watchdog_2.py
├── os_platform.py
├── light_colors.py
├── env_json.py
├── main.py
├── watchdog.py
├── bug.svg
├── zeronet_config.py
├── service.py
├── platform_linux.py
├── platform_android.py
├── zeronet.kv
└── platform_service.py
├── .version.sh
├── .travis
└── wait.sh
├── img
└── splash.xcf
├── icons
├── icon.512.png
└── icon.svg
├── screenshots
├── ui.png
├── loading.png
├── startup.png
└── zerohello.png
├── .ci
├── download-signed-stable.sh
├── push-fdroid.sh
├── release-nightly.sh
├── bind-cache.sh
├── package.sh
├── update-cron.sh
└── build.sh
├── .gitignore
├── getvagrant.sh
├── .gitmodules
├── vendor
└── update-vendor.sh
├── maint
└── RELEASE_CHECKLIST.md
├── Tutorial-of-packaging-APK-zh-cn.md
├── .gitlab-ci.yml
├── Dockerfile
├── Tutorial-of-packaging-APK.md
├── README-zh-cn.md
├── Vagrantfile
├── Makefile
├── tool.sh
├── README.md
└── LICENSE
/.dockerignore:
--------------------------------------------------------------------------------
1 | *
2 | !Makefile
3 | !tool.sh
4 |
--------------------------------------------------------------------------------
/src/translate/__init__.py:
--------------------------------------------------------------------------------
1 | from .Translate import *
2 |
--------------------------------------------------------------------------------
/.version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | CUR_VERSION="0.7.0"
4 |
5 | VER_SUFFIX=1
6 |
--------------------------------------------------------------------------------
/.travis/wait.sh:
--------------------------------------------------------------------------------
1 | wait() {
2 | echo -n .
3 | sleep 1m
4 | wait
5 | }
6 | wait &
7 |
--------------------------------------------------------------------------------
/src/bug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/src/bug.png
--------------------------------------------------------------------------------
/src/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/src/icon.png
--------------------------------------------------------------------------------
/img/splash.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/img/splash.xcf
--------------------------------------------------------------------------------
/src/Roboto.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/src/Roboto.ttf
--------------------------------------------------------------------------------
/src/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/src/splash.png
--------------------------------------------------------------------------------
/src/TextMeOne.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/src/TextMeOne.ttf
--------------------------------------------------------------------------------
/icons/icon.512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/icons/icon.512.png
--------------------------------------------------------------------------------
/screenshots/ui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/screenshots/ui.png
--------------------------------------------------------------------------------
/src/Roboto-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/src/Roboto-Regular.otf
--------------------------------------------------------------------------------
/screenshots/loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/screenshots/loading.png
--------------------------------------------------------------------------------
/screenshots/startup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/screenshots/startup.png
--------------------------------------------------------------------------------
/screenshots/zerohello.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/screenshots/zerohello.png
--------------------------------------------------------------------------------
/src/DroidSansFallback.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ZeroNet-kivy/master/src/DroidSansFallback.ttf
--------------------------------------------------------------------------------
/.ci/download-signed-stable.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | wget https://tmp.i.mkg20001.io/zn-last-sign.zip -O signed.zip
4 | unzip signed.zip
5 |
--------------------------------------------------------------------------------
/src/watchdog_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import os
4 |
5 | os.environ["watchdog_id"] = "1"
6 |
7 | if True:
8 | import watchdog
9 |
--------------------------------------------------------------------------------
/src/watchdog_2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import os
4 |
5 | os.environ["watchdog_id"] = "2"
6 |
7 | if True:
8 | import watchdog
9 |
--------------------------------------------------------------------------------
/.ci/push-fdroid.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | cd release
6 |
7 | CMD=$(echo "$FDROID_UPLOAD" | base64 -d)
8 |
9 | eval $CMD
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .buildozer
2 | dist
3 | bin
4 | .vagrant
5 | *.log
6 | *.pyc
7 | _OLD
8 | screenshots.orig
9 | .pre
10 | *.bak
11 | .env
12 | .deps
13 |
--------------------------------------------------------------------------------
/src/translate/languages/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "_translators": "IMPORTANT: If you want to start translating, copy another language that is up-to-date (like de.json) and start translating that one"
3 | }
4 |
--------------------------------------------------------------------------------
/getvagrant.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | file="https://releases.hashicorp.com/vagrant/1.9.1/vagrant_1.9.1_x86_64.deb"
4 |
5 | o="vagrant.deb"
6 |
7 | set -x
8 |
9 | wget $file -O $o
10 | dpkg -i --force-all $o
11 | apt-get -f install
12 |
--------------------------------------------------------------------------------
/src/os_platform.py:
--------------------------------------------------------------------------------
1 | from kivy.utils import platform
2 |
3 | if platform=="android":
4 | from platform_android import *
5 | elif platform=="linux":
6 | from platform_linux import *
7 | else:
8 | raise Exception("Unsupported platform: %s" % platform)
9 |
--------------------------------------------------------------------------------
/src/light_colors.py:
--------------------------------------------------------------------------------
1 | def format(s):
2 | return float("0."+str(int("0x"+s[0]+s[1],16)))
3 |
4 | def hex(s): #converts the colors into light colors (not really how it should be done - but it works)
5 | return format(s[1]+s[2]),format(s[3]+s[4]),format(s[5]+s[6])
6 |
--------------------------------------------------------------------------------
/src/env_json.py:
--------------------------------------------------------------------------------
1 | import os, json
2 |
3 | def loadEnv():
4 | env=None
5 | if 'ENV_JSON' in os.environ:
6 | with open(os.environ['ENV_JSON'], 'r') as f:
7 | env = json.load(f)
8 | else:
9 | with open('env.json', 'r') as f:
10 | env = json.load(f)
11 | return env
12 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/zero"]
2 | path = src/zero
3 | url = https://github.com/HelloZeroNet/ZeroNet
4 | [submodule "vendor/buildozer"]
5 | path = vendor/buildozer
6 | url = https://github.com/mkg20001/buildozer
7 | [submodule "vendor/python-for-android"]
8 | path = vendor/python-for-android
9 | url = https://github.com/mkg20001/python-for-android
10 |
--------------------------------------------------------------------------------
/.ci/release-nightly.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | mkdir release
4 |
5 | UPCMD=$(echo "$NIGHTLY_UPCMD" | base64 -d)
6 |
7 | for f in package/unsigned/*.apk; do
8 | OUT=${f/"package/unsigned/"/"release/"}
9 | OUT=${OUT/"-unsigned"/"-nightly"}
10 |
11 | rm -f /tmp/zn-release.apk
12 | zipalign -v -p 4 "$f" /tmp/zn-release.apk
13 |
14 | curl 172.17.0.1:6234 --header "Token: $NIGHTLY_SIGNING_TOKEN" -F "apk=@/tmp/zn-release.apk" -o "$OUT"
15 |
16 | if [ ! -s "$OUT" ]; then
17 | echo "ERR: Signing failed" >&2
18 | exit 2
19 | fi
20 | done
21 |
--------------------------------------------------------------------------------
/.ci/bind-cache.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | chmod 777 "$HOME"
6 |
7 | create_and_chmod() {
8 | mkdir -p "$1"
9 | sudo chmod 777 "$1"
10 | }
11 |
12 | bind_folder() {
13 | LOCAL="$1/$2"
14 | CACHE="/cache/kivy/$2"
15 |
16 | echo "[CACHE] Bind $LOCAL to $CACHE"
17 | rm -rf "$LOCAL"
18 | create_and_chmod "$(dirname "$LOCAL")"
19 | create_and_chmod "$CACHE"
20 | # sudo mount --bind "$CACHE" "$LOCAL"
21 | sudo ln -s "$CACHE" "$LOCAL"
22 | }
23 |
24 | bind_folder "$HOME" .buildozer/android
25 | bind_folder "$HOME" .gradle
26 | bind_folder "$HOME" .android
27 |
--------------------------------------------------------------------------------
/vendor/update-vendor.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | for dep in buildozer python-for-android; do
4 | pushd $dep
5 | if ! git remote -v | grep upstream >/dev/null; then
6 | git remote set-url origin git@github.com:mkg20001/$dep
7 | git remote add upstream git@github.com:kivy/$dep
8 | fi
9 | git fetch -p
10 | git remote update -p
11 | git branch -D master
12 | git reset --hard origin/master
13 | git checkout -b master
14 | git rebase upstream/master
15 | bash
16 | if [ -e .ok ]; then
17 | git push origin HEAD:$(date +%s)
18 | git push -uf origin master
19 | rm .ok
20 | fi
21 | popd
22 | done
23 |
--------------------------------------------------------------------------------
/src/translate/languages/it.json:
--------------------------------------------------------------------------------
1 | {
2 | "Welcome to ZeroNet!":"Benvenuto su ZeroNet!",
3 | "Below you see sites which are available in ZeroNet":"Qui trovi l'elenco dei siti disponibili su ZeroNet",
4 | "ZeroNet Homepage":"Homepage di ZeroNet",
5 | "Simple Messaging Board":"Semplice spazio di messaggistica",
6 | "Reddit-Like, Decentralized Forum":"Forum decentralizzato, stile Reddit",
7 | "Microblogging Platform":"Piattaforma di microblogging",
8 | "End-to-End Encrypted Mailing":"Email con crittografia end-to-end",
9 | "Peer-to-Peer Social Network":"Social network P2P",
10 | "Reddit-Like, Decentralized Forum for China":"Forum decentralizzato in cinese"
11 | }
12 |
--------------------------------------------------------------------------------
/src/translate/languages/fa.json:
--------------------------------------------------------------------------------
1 | {
2 | "Welcome to ZeroNet!":"به زیرونت خوشآمدید",
3 | "Below you see sites which are available in ZeroNet":"در زیر شما سایت هایی که در زیرونت در دسترس هستند را میبینید",
4 | "ZeroNet Homepage":"صفحه خانه زیرونت",
5 | "Simple Messaging Board":"تخته پیامرسانی ساده",
6 | "Reddit-Like, Decentralized Forum":"فروم غیرمتمرکز شبیه ردیت",
7 | "Microblogging Platform":"پلتفرم وبلاگ نویسی کوچک",
8 | "End-to-End Encrypted Mailing":"نامهرسانی سرتاسر رمزنگاری شده",
9 | "Peer-to-Peer Social Network":"شبکه اجتماعی سرتاسر رمزنگاری شده",
10 | "Reddit-Like, Decentralized Forum for China":"فروم غیرمتمرکز شبیه ردیت برای چین",
11 | "[b]Report a Bug[/b]": "[b]گزارش یک مشکل[/b]",
12 | "[b]Donate[/b]": "[b]حمایت[/b]"
13 | }
14 |
--------------------------------------------------------------------------------
/src/translate/languages/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "Welcome to ZeroNet!":"Willkommen bei ZeroNet!",
3 | "Below you see sites which are available in ZeroNet":"Hier unten siehst du Seiten die im ZeroNet verfügbar sind",
4 | "ZeroNet Homepage":"ZeroNet Startseite",
5 | "Simple Messaging Board":"Einfaches Narichten Board",
6 | "Reddit-Like, Decentralized Forum":"Reddit ähnliches, dezentralisiertes Forum",
7 | "Microblogging Platform":"Microblogging Platform",
8 | "End-to-End Encrypted Mailing":"Ende-zu-Ende verschlüsseltes E-Mail System",
9 | "Peer-to-Peer Social Network":"Peer-zu-Peer Soziales Netzwerk",
10 | "Reddit-Like, Decentralized Forum for China":"Reddit ähnliches, dezentralisiertes Forum für China",
11 | "[b]Report a Bug[/b]": "[b]Fehler melden[/b]",
12 | "[b]Donate[/b]": "[b]Spenden[/b]"
13 | }
14 |
--------------------------------------------------------------------------------
/src/translate/languages/pt-br.json:
--------------------------------------------------------------------------------
1 | {
2 | "Welcome to ZeroNet!":"Bem-vindo ao ZeroNet!",
3 | "Below you see sites which are available in ZeroNet":"Abaixo você vê sites disponíveis no ZeroNet",
4 | "ZeroNet Homepage":"Página Inicial ZeroNet",
5 | "Simple Messaging Board":"Quadro Simples de mensagens",
6 | "Reddit-Like, Decentralized Forum":"Fórum descentralizado, semelhante ao Reddit",
7 | "Microblogging Platform":"Plataforma de Microblogging",
8 | "End-to-End Encrypted Mailing":"Correspondência criptografada de ponta a ponta",
9 | "Peer-to-Peer Social Network":"Rede social Peer-to-Peer",
10 | "Reddit-Like, Decentralized Forum for China":"Fórum descentralizado e semelhante ao Reddit para a China",
11 | "[b]Report a Bug[/b]": "[b]Reportar um erro[/b]",
12 | "[b]Donate[/b]": "[b]Doar[/b]"
13 | }
14 |
--------------------------------------------------------------------------------
/src/translate/languages/zh-tw.json:
--------------------------------------------------------------------------------
1 | {
2 | "Roboto":"DroidSansFallback",
3 | "string.feedback":"想要妥善地關閉ZeroNet背景服務,\n請在瀏覽器中點擊ZeroHello首頁左上方的 ┇ 按鈕,\n 選擇關閉ZeroNet,謝謝!\n更多信息和相關討論點這裡(中文版))[/ref]",
4 | "Talk.ZeroNetwork.bit/?Topic:13_13Z7XxTa7JuFat3KzzMWu3onwM6biLuurJ/":"NewGFWTalk.bit/?Topic:59_13Z7XxTa7JuFat3KzzMWu3onwM6biLuurJ/",
5 |
6 | "Welcome to ZeroNet!":"歡迎使用 ZeroNet",
7 | "Below you see sites which are available in ZeroNet":"下面你看到的是 ZeroNet 的可用網站",
8 | "ZeroNet Homepage":"ZeroNet 首頁",
9 | "Simple Messaging Board":"简单的佈告欄",
10 | "Reddit-Like, Decentralized Forum":"類似於 Reddit 的,分散式的論壇",
11 | "Microblogging Platform":"輕量化網誌平台",
12 | "End-to-End Encrypted Mailing":"端對端加密郵件",
13 | "Peer-to-Peer Social Network":"對等社交網路",
14 | "Reddit-Like, Decentralized Forum for China":"來自於中國的,類似於 Reddit 的,分散式的論壇"
15 | }
16 |
--------------------------------------------------------------------------------
/src/translate/languages/zh.json:
--------------------------------------------------------------------------------
1 | {
2 | "Roboto":"DroidSansFallback",
3 | "string.feedback":"想要妥善地关闭ZeroNet后台服务,\n请在浏览器中点击ZeroHello首页左上方的 ┇ 按钮,\n 选择关闭ZeroNet,谢谢!\n更多信息和相关讨论点这里(中文版))[/ref]",
4 | "Talk.ZeroNetwork.bit/?Topic:13_13Z7XxTa7JuFat3KzzMWu3onwM6biLuurJ/":"NewGFWTalk.bit/?Topic:59_13Z7XxTa7JuFat3KzzMWu3onwM6biLuurJ/",
5 |
6 | "Welcome to ZeroNet!":"欢迎使用 ZeroNet",
7 | "Below you see sites which are available in ZeroNet":"下面你看到的是 ZeroNet 的可用站点",
8 | "ZeroNet Homepage":"ZeroNet 首页",
9 | "Simple Messaging Board":"简单的消息版",
10 | "Reddit-Like, Decentralized Forum":"类似于 Reddit 的,分布式的论坛",
11 | "Microblogging Platform":"轻量化博客平台",
12 | "End-to-End Encrypted Mailing":"端对端加密邮件",
13 | "Peer-to-Peer Social Network":"点对点社交网络",
14 | "Reddit-Like, Decentralized Forum for China":"来自于中国的,类似于 Reddit 的,分布式的论坛"
15 | }
16 |
--------------------------------------------------------------------------------
/src/main.py:
--------------------------------------------------------------------------------
1 | from webbrowser import open as browser
2 |
3 | from kivy.app import App
4 | from kivy.lang import Builder
5 |
6 | from os_platform import Service, platform, wrapSentry
7 | from zeronet_config import getConfigValue
8 |
9 |
10 | class ZeronetApp(App):
11 |
12 | '''This is the app itself'''
13 |
14 | def url_click(self, url):
15 | full = "http://127.0.0.1:" + \
16 | getConfigValue(self.service.config, "ui_port", "43110") + "/" + url
17 | print("Opening in browser %s" % full)
18 | browser(full)
19 |
20 | def build(self):
21 | print("Starting...")
22 |
23 | print("Running on platform %s" % platform)
24 |
25 | self.service = Service()
26 | '''Starts 2 watchdog processes, which will then start zeronet'''
27 | self.service.run()
28 |
29 | if __name__ == "__main__":
30 | '''Start the application'''
31 |
32 | wrapSentry(ZeronetApp().run)
33 |
--------------------------------------------------------------------------------
/icons/icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/maint/RELEASE_CHECKLIST.md:
--------------------------------------------------------------------------------
1 | # A new version is coming! :tada:
2 |
3 | # Changelog
4 |
5 | - **update** - ZeroNet updated to Version XYZ
6 | - **bug fix** - Another bug squashed
7 | - **feature** - Another cool feature
8 |
9 | ## Pre-Release
10 |
11 | - [ ] Test whether latest devel works
12 | - [ ] 28 aka 9.0 Pie
13 | - [ ] 27 aka 8.1 Oreo
14 | - [ ] 22 aka 5.1 Lollipop
15 | - [ ] Bump version in .version.sh if necesarry
16 | - [ ] Create git tag
17 | - [ ] Push to master and push tag
18 | - [ ] Wait for build to finish
19 |
20 | ## Release
21 |
22 | - [ ] Download package artifacts and extract
23 | - [ ] Run release script
24 | - [ ] Test APKs
25 | - [ ] 28 aka 9.0 Pie
26 | - [ ] 27 aka 8.1 Oreo
27 | - [ ] 22 aka 5.1 Lollipop
28 | - [ ] Run CI job for release manually
29 | - [ ] Publish on
30 | - [ ] F-Droid (check if script succeeded)
31 | - [ ] Google Play
32 | - [ ] GitHub Releases
33 | - [ ] ZeroNet-Android.bit
34 |
35 | ## Post-Release
36 |
37 | - [ ] Share on social media?
38 | - [ ] Close this issue
39 |
--------------------------------------------------------------------------------
/Tutorial-of-packaging-APK-zh-cn.md:
--------------------------------------------------------------------------------
1 | # 指导:
2 |
3 | 在Ubuntu 16.04上测试过
4 |
5 | 必需品:
6 | - A phone or armv7 emulator (can't build for non-arm currently)
7 | - Git
8 | - Make
9 | - ADB
10 | - Docker or Vagrant (for vagrant please skip to the bottom)
11 |
12 | ## 初始步骤
13 | - 首先 `git clone https://github.com/HelloZeroNet/ZeroNet-kivy --recursive`
14 | - 现在验证在 `src/zero` 的内容
15 |
16 | ## 安装
17 | - 首先,您需要生成环境配置。使用`make .env`执行此操作
18 | - 之后使用`make .pre`准备构建
19 |
20 | ## 建设
21 | - 运行`make debug`来构建应用程序的调试版本
22 | - 运行`make release`来构建应用程序的发布版本
23 | - 如果构建成功,则会显示带有ZeroNet.apk的bin文件夹
24 | - 运行`make run`来测试连接手机上的应用程序
25 | - 果您使用模拟器,请在命令后附加`ADB_FLAG=-e`
26 |
27 | ## 调试
28 | - 运行 `make test` 应该启动adb logcat
29 | - 其他日志位于 `/storage/emulated/0/Android/data/net.mkg20001.zeronet/files/zero/log`
30 | - 如果`make test`不起作用,请尝试`make run`
31 |
32 | ## Vagrant
33 | - 首先运行 `vagrant up`
34 | - 这应该创建和准备虚拟机
35 |
36 | ### Building
37 | - 运行所有命令 **inside** the vagrant VM (Use `vagrant ssh` to enter the vm)
38 | - 测试你需要安装adb. Run `make run` or `make test` **outside** the VM
39 | - 如果你安装了它,运行 `make run`
40 | - 如果您使用模拟器,请在命令后附加 `ADB_FLAG=-e`
41 |
--------------------------------------------------------------------------------
/.ci/package.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # test: mkdir -p ci-out/{a,b,c} && touch ci-out/{a,b,c}/{buildozer.spec,test-{release-unsigned,debug}.apk} && for f in ci-out/*/buildozer.spec; do echo -e "# test\ntest\n\n" > "$f"; done
4 |
5 | set -e
6 |
7 | mkdir -p package/{unsigned,debug,spec}
8 |
9 | for arch_path in ci-out/*; do
10 | arch=$(basename "$arch_path")
11 |
12 | # generate stripped spec file
13 | cat "$arch_path/buildozer.spec" | sed "s|^#.+||g" | grep -v "^\$" > "package/spec/buildozer.$arch.spec"
14 |
15 | # get apks
16 | release_unsigned=$(echo "$arch_path/"*release-unsigned*)
17 | debug=$(echo "$arch_path/"*debug*)
18 |
19 | # move apks
20 | for f in "$release_unsigned" "$debug"; do
21 | outfolder=$(echo "$f" | sed -r "s|.+-([a-z-]+).apk|\1|g")
22 | fout=${f/".apk"/"-$arch.apk"}
23 | fout=$(basename "$fout")
24 | fout="package/$outfolder/$fout"
25 | mv -v "$f" "${fout}"
26 | done
27 | done
28 |
29 | getmeta() {
30 | cat src/zero/src/Config.py | grep "$1 =" | sed -r "s|(.*) = ||g"
31 | }
32 |
33 | echo "{\"rev\":$(getmeta self.rev),\"ver\":$(getmeta self.version),\"date\":$(expr $(date +%s) \* 1000)}" > package/metadata.json
34 |
--------------------------------------------------------------------------------
/src/watchdog.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | from time import sleep
4 |
5 | import os_platform as platform
6 | from env_json import loadEnv
7 |
8 | if "watchdog_id" not in os.environ:
9 | raise Exception("No watchdog id!")
10 | id = int(os.environ["watchdog_id"])
11 | print("This is watchdog %s" % id)
12 |
13 | service = platform.Service()
14 | service.setPid("watchdog%s" % str(id), os.getpid())
15 |
16 |
17 | def isRunning(what):
18 | i = service.isRunning(what)
19 | if not i:
20 | print("%s is not running, starting now" % what)
21 | # else:
22 | # print "%s is running, pid=%s" % (what,service.getPid(what))
23 | return i
24 |
25 | while(True): # runs forever
26 | sleep(1) # delay first, so processes can start up
27 | if id == 1: # the first watchdog checks if watchdog2 and zeronet are running and starts them
28 | if not isRunning("watchdog2"):
29 | # if not os.fork():
30 | service.startWatchdog(2)
31 | # exit(0)
32 | if not isRunning("zeronet"):
33 | # if not os.fork():
34 | service.runZero()
35 | # exit(0)
36 | elif id == 2: # the second check only if the first is running
37 | if not isRunning("watchdog1"):
38 | # if not os.fork():
39 | service.startWatchdog(1)
40 | # exit(0)
41 |
--------------------------------------------------------------------------------
/.ci/update-cron.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # reset src
4 | if [ -e .pre ]; then
5 | rm -rf src/zero
6 | git submodule update
7 | rm .pre
8 | fi
9 |
10 | git pull --recurse-submodule
11 |
12 | # get version wrapper
13 | zn_ver() {
14 | pushd src/zero/src
15 |
16 | lver=$(cat Config.py | grep "^[ ]*self.version" | grep "[0-9]*\.[0-9]*\.[0-9]*" -o)
17 |
18 | lat=$(git log --grep="Rev[0-9]*" --format="[%H] = %s" | head -n 1)
19 | lc=$(echo "$lat" | grep "\[[a-z0-9A-Z]*\]" -o | grep "[a-z0-9A-Z]*" -o)
20 | lrev=$(echo "$lat" | grep "Rev[0-9]*" -o)
21 |
22 | echo "commit = $lc / rev = $lrev / ver = $lver"
23 |
24 | popd
25 | }
26 |
27 | zn_ver
28 | CMT_BEFORE="$lc"
29 |
30 | # fetch new zn
31 | git -C src/zero remote update -p
32 | git -C src/zero merge --ff-only origin/master
33 |
34 | zn_ver
35 |
36 | if [ "$CMT_BEFORE" != "$lc" ]; then
37 | source .version.sh
38 |
39 | if [ "$CUR_VERSION" != "$lver" ]; then
40 | CUR_VERSION="$lver"
41 | VER_SUFFIX=1
42 | echo "Major upgrade, reset suffix"
43 | else
44 | VER_SUFFIX=$(( $VER_SUFFIX + 1 ))
45 | echo "Minor upgrade, suffix++"
46 | fi
47 |
48 | echo '#!/bin/bash
49 |
50 | CUR_VERSION="'"$CUR_VERSION"'
51 |
52 | VER_SUFFIX='"$VER_SUFFIX"'' > .version.sh
53 |
54 | git commit -m "Update ZeroNet to $lrev" src/zero .version.sh
55 | git push
56 |
57 | echo DONE
58 | fi
59 |
--------------------------------------------------------------------------------
/.ci/build.sh:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | set -ev
4 |
5 | # prepare
6 | bash .ci/bind-cache.sh
7 | export TERM=xterm-256color
8 | export DISABLE_PROGRESS=1
9 | # source .version.sh
10 |
11 | replace_var() {
12 | sed -r "s|#* *$1 = .*|$1 = $2|g" -i buildozer.spec
13 | }
14 |
15 | disable_var() {
16 | sed -r "s|#* *$1 = .*|# $1 (disabled) = 0|g" -i buildozer.spec
17 | }
18 |
19 | if [ -z "$CI_COMMIT_TAG" ]; then # build a nightly
20 | replace_var package.domain luna.mkg20001
21 | replace_var title ZeroNetN
22 | # disable_var version.regex
23 | # disable_var version.filename
24 | # replace_var version "$CUR_VERSION.$(date +%s)"
25 | # SUFFIX=$(git log --oneline | wc -l | sed -r "s|(.+)([0-9]{2})|\1.\2|g") # turns commit count into version, e.g. 111 -> 1.11
26 | SUFFIX=$(git log --oneline | wc -l) # counts commits
27 | sed -r "s|VER_SUFFIX.+|VER_SUFFIX=$SUFFIX|g" -i .version.sh
28 | fi
29 |
30 | # setup
31 | replace_var android.arch "$TARGET_ARCH"
32 | echo -e "EXEC=docker\nDOCKER_IMAGE=$IMAGE_TAG\nDISABLE_PROGRESS=1" > .env
33 | docker pull $IMAGE_TAG
34 | bash ./tool.sh prebuild
35 |
36 | # execute
37 | script -q -e -c "make _ci"
38 |
39 | # post-check
40 | ls bin | grep debug | grep .apk # ensure job generated debug apk
41 | ls bin | grep release | grep .apk # ensure job generated release apk
42 | mkdir ci-out && mv bin ci-out/$CI_JOB_NAME && mv buildozer.spec ci-out/$CI_JOB_NAME/
43 |
--------------------------------------------------------------------------------
/src/bug.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | services:
2 | - docker:dind
3 |
4 | stages:
5 | - image
6 | - build
7 | - package
8 | - release
9 | - fdroid
10 |
11 | variables:
12 | GIT_SUBMODULE_STRATEGY: recursive
13 | DOCKER_HOST: tcp://docker:2375
14 | DOCKER_DRIVER: overlay2
15 | IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
16 | DOCKER_TLS: ""
17 | DOCKER_TLS_CERTDIR: ""
18 |
19 | before_script:
20 | - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
21 |
22 | docker-image:
23 | stage: image
24 | script:
25 | - docker build -t $IMAGE_TAG .
26 | - docker push $IMAGE_TAG
27 |
28 | .build: &build
29 | stage: build
30 | script:
31 | - bash .ci/build.sh
32 | artifacts:
33 | paths:
34 | - ci-out/
35 |
36 | armeabi-v7a:
37 | <<: *build
38 | variables:
39 | TARGET_ARCH: armeabi-v7a
40 |
41 | arm64-v8a:
42 | <<: *build
43 | variables:
44 | TARGET_ARCH: arm64-v8a
45 |
46 | x86:
47 | <<: *build
48 | variables:
49 | TARGET_ARCH: x86
50 |
51 | x86-64:
52 | <<: *build
53 | variables:
54 | TARGET_ARCH: x86_64
55 |
56 | package:
57 | stage: package
58 | script:
59 | - ./.ci/package.sh
60 | only:
61 | - master
62 | - tags
63 | artifacts:
64 | paths:
65 | - package/
66 |
67 | release-nightly:
68 | stage: release
69 | script:
70 | - ./.ci/release-nightly.sh
71 | only:
72 | - master
73 | tags:
74 | - argon
75 | artifacts:
76 | paths:
77 | - release/
78 |
79 | release-production:
80 | stage: release
81 | script:
82 | - ./.ci/download-signed-stable.sh
83 | only:
84 | - tags
85 | except:
86 | - branches
87 | when: manual
88 | artifacts:
89 | paths:
90 | - release/
91 |
92 | push-to-fdroid:
93 | stage: fdroid
94 | script:
95 | - ./.ci/push-fdroid.sh
96 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:18.04
2 |
3 | ENV HOME /home
4 |
5 | RUN rm -f /etc/apt/apt.conf.d/01autoremove-kernels \
6 | \
7 | #&& echo '#!/bin/sh' > /usr/sbin/policy-rc.d \
8 | #&& echo 'exit 101' >> /usr/sbin/policy-rc.d \
9 | #&& chmod +x /usr/sbin/policy-rc.d \
10 | #\
11 | #&& dpkg-divert --local --rename --add /sbin/initctl \
12 | #&& cp -a /usr/sbin/policy-rc.d /sbin/initctl \
13 | #&& sed -i 's/^exit.*/exit 0/' /sbin/initctl \
14 | #\
15 | #&& echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \
16 | \
17 | && echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' > /etc/apt/apt.conf.d/docker-clean \
18 | && echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; };' >> /etc/apt/apt.conf.d/docker-clean \
19 | && echo 'Dir::Cache::pkgcache "";' >> /etc/apt/apt.conf.d/docker-clean \
20 | && echo 'Dir::Cache::srcpkgcache "";' >> /etc/apt/apt.conf.d/docker-clean \
21 | \
22 | && echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/docker-no-languages \
23 | \
24 | && echo 'Acquire::GzipIndexes "true";' > /etc/apt/apt.conf.d/docker-gzip-indexes \
25 | && echo 'Acquire::CompressionTypes::Order:: "gz";' > /etc/apt/apt.conf.d/docker-gzip-indexes \
26 | \
27 | && echo 'Apt::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/docker-autoremove-suggests
28 |
29 | RUN apt-get update
30 |
31 | #Locale
32 | RUN apt-get install language-pack-en -y
33 | ENV LANG en_US.UTF-8
34 | ENV LANGUAGE en_US:en
35 | ENV LC_ALL en_US.UTF-8
36 | RUN locale-gen en_US.UTF-8
37 | RUN update-locale
38 |
39 | RUN apt-get install -y make sudo
40 |
41 | RUN chmod 777 /home
42 | #This is required, fixes: KeyError: 'getpwuid(): uid not found: 1000' (later tool.sh adds user with right UID, done dynamic so we don't have to mess with user perms)
43 | RUN chmod 777 /etc/passwd
44 |
45 | ADD Makefile .
46 | ADD tool.sh .
47 | RUN make -C . env
48 |
49 | RUN rm -rfv /home
50 | RUN mkdir /home
51 | RUN chmod 777 /home
52 |
--------------------------------------------------------------------------------
/Tutorial-of-packaging-APK.md:
--------------------------------------------------------------------------------
1 | # Guide:
2 |
3 | Tested on Ubuntu 18.04
4 |
5 | Required things:
6 | - A phone or armv7 emulator (can't build for non-arm currently)
7 | - Git
8 | - Make
9 | - ADB
10 | - Docker or Vagrant
11 |
12 | ## Initial Steps
13 | - First `git clone https://github.com/HelloZeroNet/ZeroNet-kivy --recursive`
14 | - Now verify the contents in `src/zero`
15 | - (If you cloned without `--recursive` then run `git submodule init && git submodule update`)
16 |
17 | ## Setup
18 |
19 | ### Docker (recommended)
20 | - Run `make .env`. This will prompt you a few questions (you can usually leave the defaults as-is) and pull the docker-image.
21 | - Now run `setup` to complete the setup
22 |
23 | ### Vagrant
24 | - Run `vagrant up`. This will create an ubuntu 18.04 vm and run the necesarry setup-commands for you.
25 | - NOTES:
26 | - Run all the _building_ commands **inside** the vagrant VM (Use `vagrant ssh` to enter the vm)
27 | - Run all the commands that install the app on your phone **outside** the vagrant VM
28 | - To test you need adb installed. Run `make run` or `make test` **outside** the VM
29 | - If you got it installed run `make run`
30 | - If you are using an emulator append `ADB_FLAG=-e` to the command
31 |
32 | ### Local machine
33 | - Run `make .env`
34 |
35 | ## Building
36 | - Run `make debug` to build the debug version of the app
37 | - Run `make release` to build the release version of the app
38 | - If building succeeds a bin folder with the ZeroNet.apk appears
39 | - Run `make run` to test the app on the connected phone
40 | - If you are using an emulator append `ADB_FLAG=-e` to the command
41 |
42 | ## Debugging
43 | - Running `make test` should start adb logcat
44 | - Additional logs are in `/storage/emulated/0/Android/data/net.mkg20001.zeronet/files/zero/log`
45 | - If `make test` does not work try `make run`
46 |
47 | ### Building
48 | - Run all the commands **inside** the vagrant VM (Use `vagrant ssh` to enter the vm)
49 | - To test you need adb installed. Run `make run` or `make test` **outside** the VM
50 | - If you got it installed run `make run`
51 | - If you are using an emulator append `ADB_FLAG=-e` to the command
52 |
--------------------------------------------------------------------------------
/README-zh-cn.md:
--------------------------------------------------------------------------------
1 | # ZeroNet-kivy
2 | [English](./README.md)
3 |
4 | ZeroNet的图形界面控制面板和APP打包,使用Kivy框架
5 | [Kivy](https://kivy.org) 是一个基于Python的跨平台的开源GUI框架。它可以部署到Android和iOS,甚至是桌面平台 (Win, Linux, Mac )。
6 |
7 | 目前本项目的代码只能在Android上运行,欢迎对iOS开发感兴趣的同学加入。
8 | 目前本项目处于Alpha阶段,其GUI缺乏功能和美工设计,代码里保留了很多用于测试的代码。请贡献你的创意,无论是美工还是代码!
9 |
10 | ### 屏幕截图:
11 |
12 | #### 启动界面
13 | 
14 | #### UI
15 | 
16 |
17 | ### ZeroNet:
18 |
19 | #### 加载界面
20 | 
21 | #### ZeroHello
22 | 
23 | #### ZeroMe
24 | 
25 |
26 |
27 | ## 目标:
28 |
29 | * 易于安装
30 | - 去掉无用文件,减小安装包体积
31 | - 在Google Play, Apple App Store上发布,另外还有其他平台的官方APP市场或软件包仓库
32 | * 易于使用
33 | - 仅仅一触即可启动或停止ZeroNet服务
34 | - 稳定运行,防止被系统杀掉
35 | + 在Android上,使ZeroNet运行为前台服务,降低被杀几率。如果还是被杀,可以创建一两个守护进程,用来重启ZeroNet服务。
36 | - 在移动设备上,降低电池、流量、存储的消耗量。自动调节ZeroNet在不同情景下的运行模式:是Wifi还是流量,是充着电还是低电量。当然,用户也能自行调节。
37 | - 使users.json和其他敏感数据保存在APP的内部私有目录,避免让其他APP接触到
38 | - 通过GUI导入主密钥或users.json,让用户能够跨设备使用同一ID
39 | - 通过GUI设置ZeroNet,而不是手动编辑zeronet.conf
40 | - 提供一个瘦客户端供用户选择。就像比特币瘦客户端一样,用户无需等待同步大量数据、消耗大量电量和存储,即可使用ZeroNet。瘦客户端向随机的代理 ( gateway ) 服务器接收和发送数据(发送前用私钥签名),私钥并不会泄露。
41 |
42 | 以上的目标,有一部分不是本项目单干就能搞定的,需要向ZeroNet贡献代码,提交更改。
43 |
44 | ## ZeroNet的APK打包教程
45 |
46 | 打包过程不是很难,因为Kivy的Buildozer自动化了很多工作。
47 | [打包教程在这,很详细的](./Tutorial-of-packaging-APK-zh-cn.md)
48 |
49 | ## APK下载
50 |
51 | [ » 点击下载](https://github.com/HelloZeroNet/ZeroNet-kivy/releases)
52 |
53 | [ » 老版本](https://github.com/mkg20001/ZeroNet-kivy/releases)
54 |
55 | ## 如何使用APK
56 |
57 | * 注意你手机上的防火墙和权限控制的设置,请让本APK通过
58 | * 如果你浏览网站时遇到问题,请尝试其他浏览器
59 | * 如果你想关闭ZeroNet,请点击ZeroHello首页的左上角的⋮ 按钮,在菜单中选择关闭
60 | * 你可以升级ZeroNet本身的代码,方法跟在电脑上一样:点击ZeroHello首页的左上角的⋮ 按钮,在菜单中选择版本 x.x.x( rev xxxx),不要管它是不是显示最新,就点它,就会升级到最新的开发版
61 | * 遇到bug或其他问题到外部存储/Android/data/包名如android.test.myapp17/files/zero/log里的log看看有什么异常报错
62 |
63 | ## 项目结构一览
64 | * src
65 | - zeronet.kv - Gui 布局
66 | - main.py - 主文件
67 | - service.py - 服务文件
68 | - platform_*.py - 平台具体代码
69 | * zero - ZeroNet本身的全部代码 (if content is missing run `git submodule init --recursive`)
70 | - zeronet.py - ZeroNet 启动器
71 | * buildozer.spec - Buildozer的配置,你可以定义APK的包名、标题、版本号、android权限、服务等等.
72 |
--------------------------------------------------------------------------------
/src/zeronet_config.py:
--------------------------------------------------------------------------------
1 | import configparser
2 | import os
3 |
4 |
5 | # Parse config file
6 |
7 |
8 | def parseConfig(config_file):
9 | # Load config file
10 | res = dict({})
11 | if os.path.isfile(config_file):
12 | config = configparser.ConfigParser(allow_no_value=True)
13 | config.read(config_file)
14 | for section in config.sections():
15 | for key, val in config.items(section):
16 | if section != "global": # If not global prefix key with section
17 | key = section + "_" + key
18 | resval = None
19 | if val:
20 | if len(val.strip().split("\n")) > 1:
21 | resval = []
22 | for line in val.strip().split("\n"): # Allow multi-line values
23 | resval.append(line)
24 | else:
25 | resval = val
26 | res[key] = resval
27 | return res
28 |
29 |
30 | def saveConfigValue(config_file, key, value):
31 | if not os.path.isfile(config_file):
32 | content = ""
33 | else:
34 | content = open(config_file).read()
35 | lines = content.splitlines()
36 |
37 | global_line_i = None
38 | key_line_i = None
39 | i = 0
40 | for line in lines:
41 | if line.strip() == "[global]":
42 | global_line_i = i
43 | if line.startswith(key + " = "):
44 | key_line_i = i
45 | i += 1
46 |
47 | if value is None: # Delete line
48 | if key_line_i:
49 | del lines[key_line_i]
50 | else: # Add / update
51 | new_line = "%s = %s" % (
52 | key, str(value).replace("\n", "").replace("\r", ""))
53 | if key_line_i: # Already in the config, change the line
54 | lines[key_line_i] = new_line
55 | elif global_line_i is None: # No global section yet, append to end of file
56 | lines.append("[global]")
57 | lines.append(new_line)
58 | else: # Has global section, append the line after it
59 | lines.insert(global_line_i + 1, new_line)
60 |
61 | open(config_file, "w").write("\n".join(lines) + "\n")
62 |
63 |
64 | def getConfigValue(f, key, default=None):
65 | c = parseConfig(f)
66 | if key not in c:
67 | return default
68 | return c[key]
69 |
--------------------------------------------------------------------------------
/src/service.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import os
4 | import sys
5 |
6 | from env_json import loadEnv
7 | from os_platform import wrapSentry
8 |
9 | env = loadEnv()
10 |
11 | if env["platform"] == "android":
12 | import android
13 | from jnius import autoclass
14 |
15 | ANDROID_VERSION = autoclass('android.os.Build$VERSION')
16 | SDK_INT = ANDROID_VERSION.SDK_INT
17 |
18 | Service = autoclass('org.kivy.android.PythonService').mService
19 | notifi = autoclass("android.app.Notification$Builder")(Service)
20 | notifi.setContentTitle("ZeroNet")
21 | notifi.setContentText("ZeroNet is running")
22 |
23 | if SDK_INT >= 26:
24 | manager = autoclass('android.app.NotificationManager') # manager is NotificationManager
25 | channel = autoclass('android.app.NotificationChannel')
26 | managerID = autoclass('android.content.Context').NOTIFICATION_SERVICE
27 |
28 | app_channel = channel( # val mChannel = NotificationChannel(CHANNEL_ID, name, importance)
29 | "service_zn", "ZeroNet Background Service", manager.IMPORTANCE_MIN # val importance = NotificationManager.IMPORTANCE_DEFAULT
30 | )
31 | Service.getSystemService(managerID).createNotificationChannel(app_channel) # val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
32 | # notificationManager.createNotificationChannel(mChannel)
33 | notifi.setChannel("service_zn")
34 | # if SDK_INT >= 28:
35 | # Service.startForeground(233,notifi)
36 | # else:
37 | # notification = notifi.build()
38 | # Service.startForeground(233,notification)
39 | notification = notifi.build()
40 | Service.startForeground(233,notification)
41 |
42 | print("env %s" % env)
43 |
44 | sys.path.insert(1, env['srcdir'])
45 | sys.path.insert(1, env['srcdir'] + '/src') # insert $src/src too, since sometimes it can't find itself
46 | print("srcdir: %s" % env['srcdir'])
47 | print("sys.path: %s" % sys.path)
48 |
49 | os.chdir(env['srcdir'])
50 |
51 | print("sys.argv: %s" % sys.argv)
52 |
53 | with open(env['pidfile'], "w") as f:
54 | f.write(str(os.getpid()))
55 | f.close()
56 |
57 | if True: # so beautification does not move this to the top
58 | import zeronet # this is only available AFTER sys.path.insert, since it isn't anywhere in this directory
59 |
60 |
61 | def main():
62 | zeronet.start()
63 |
64 | if __name__ == '__main__':
65 | wrapSentry(main)
66 |
67 |
--------------------------------------------------------------------------------
/src/platform_linux.py:
--------------------------------------------------------------------------------
1 | # Linux Specific Code
2 | import locale
3 | import os
4 | import re
5 | import sys
6 | import threading
7 | from os import path
8 | from subprocess import PIPE, Popen
9 |
10 | from platform_service import SystemService
11 |
12 |
13 | def getSystemLang(index=0):
14 | ls = locale.getdefaultlocale()
15 | if len(locale.getdefaultlocale()) < index:
16 | return "en" # fallback
17 | l = ls[index]
18 | if l is None:
19 | return "en" # No locales
20 | print("LOCALE: %s" % l)
21 | match = re.search("^([a-z]{2})_[A-Z]+.*", str(l))
22 | if match:
23 | return match.group(1)
24 | else:
25 | return getSystemLang(index + 1)
26 |
27 |
28 | def getDir(append=""):
29 | if len(append):
30 | return path.join(path.expanduser("~"), ".zeronet", append)
31 | else:
32 | return path.join(path.expanduser("~"), ".zeronet")
33 |
34 |
35 | def realpath():
36 | return os.path.dirname(os.path.realpath(__file__))
37 |
38 |
39 | def getDebug():
40 | return os.path.exists(os.path.join(realpath(), "..", ".git"))
41 |
42 |
43 | class pipeThread (threading.Thread):
44 |
45 | def __init__(self, threadID, name, counter, args):
46 | threading.Thread.__init__(self)
47 | self.threadID = threadID
48 | self.name = name
49 | self.counter = counter
50 | self.args = args
51 |
52 | def run(self):
53 | # print "Starting "+self.name
54 | self.args.communicate()
55 | print(self.name + " has exited")
56 |
57 |
58 | class Service(SystemService):
59 |
60 | def zeroDir(self):
61 | return os.path.join(realpath(), "zero")
62 |
63 | def getPath(self, append=""):
64 | return getDir(append)
65 |
66 | def getEnvJsonPath(self):
67 | return getDir("env.json")
68 |
69 | def getPidfilePath(self, what="zeronet"):
70 | return getDir(what + ".pid")
71 |
72 | def startWatchdog(self, id):
73 | # if not os.fork():
74 | self.runGeneric("watchdog_" + str(id) + ".py",
75 | "Watchdog_" + str(id), "watchdog" + str(id))
76 | # sys.exit(0)
77 |
78 | def runService(self):
79 | return self.runGeneric("service.py", "ZeroNet", "zeronet")
80 |
81 | def runGeneric(self, what, name, pidid):
82 | if self.isRunning(pidid):
83 | print("Skip starting %s, already running as %s" % (name, self.getPid(pidid)))
84 | return False
85 | self.count += 1
86 | env = os.environ
87 | env['ENV_JSON'] = getDir("env.json")
88 | process = Popen([os.path.join(realpath(), what)], env=env)
89 | self.setPid(pidid, process.pid)
90 | running = True
91 | thread = pipeThread(self.count, name, self.count, process)
92 | thread.start()
93 | return thread, process
94 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure
5 | # configures the configuration version (we support older styles for
6 | # backwards compatibility). Please don't change it unless you know what
7 | # you're doing.
8 | Vagrant.configure("2") do |config|
9 | # The most common configuration options are documented and commented below.
10 | # For a complete reference, please see the online documentation at
11 | # https://docs.vagrantup.com.
12 |
13 | # Every Vagrant development environment requires a box. You can search for
14 | # boxes at https://atlas.hashicorp.com/search.
15 | config.vm.box = "ubuntu/bionic64"
16 |
17 | # Disable automatic box update checking. If you disable this, then
18 | # boxes will only be checked for updates when the user runs
19 | # `vagrant box outdated`. This is not recommended.
20 | # config.vm.box_check_update = false
21 |
22 | # Create a forwarded port mapping which allows access to a specific port
23 | # within the machine from a port on the host machine. In the example below,
24 | # accessing "localhost:8080" will access port 80 on the guest machine.
25 | # config.vm.network "forwarded_port", guest: 80, host: 8080
26 |
27 | # Create a private network, which allows host-only access to the machine
28 | # using a specific IP.
29 | # config.vm.network "private_network", ip: "192.168.33.10"
30 |
31 | # Create a public network, which generally matched to bridged network.
32 | # Bridged networks make the machine appear as another physical device on
33 | # your network.
34 | # config.vm.network "public_network"
35 |
36 | # Share an additional folder to the guest VM. The first argument is
37 | # the path on the host to the actual folder. The second argument is
38 | # the path on the guest to mount the folder. And the optional third
39 | # argument is a set of non-required options.
40 | config.vm.synced_folder "./", "/home/data"
41 |
42 | # Provider-specific configuration so you can fine-tune various
43 | # backing providers for Vagrant. These expose provider-specific options.
44 | # Example for VirtualBox:
45 | #
46 | config.vm.provider "virtualbox" do |vb|
47 | # # Display the VirtualBox GUI when booting the machine
48 | # vb.gui = true
49 | #
50 | # # Customize the amount of memory on the VM:
51 | vb.memory = "4096"
52 | vb.cpus = "4"
53 | end
54 | #
55 | # View the documentation for the provider you are using for more
56 | # information on available options.
57 |
58 | # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
59 | # such as FTP and Heroku are also available. See the documentation at
60 | # https://docs.vagrantup.com/v2/push/atlas.html for more information.
61 | # config.push.define "atlas" do |push|
62 | # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
63 | # end
64 |
65 | # Enable provisioning with a shell script. Additional provisioners such as
66 | # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
67 | # documentation for more information about their specific syntax and use.
68 | config.vm.provision "shell", inline: <<-SHELL
69 | whoami
70 | sudo apt-get update
71 | sudo apt-get install -y make sudo
72 | echo -e "EXEC=host\n" > /vagrant/.env
73 | sleep 5s # fix clock skew error
74 | sudo make -C /vagrant env
75 | sudo make -C /vagrant .pre
76 | SHELL
77 | end
78 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Config
2 |
3 | # Vars
4 |
5 | TOOL=bash ./tool.sh
6 | EXEC=$(TOOL) exec
7 | EXEC_NAME=$(shell $(TOOL) _getvar EXEC)
8 |
9 | # Continuous Integration (gitlab-ci)
10 |
11 | _ci: # Wrapper
12 | $(EXEC) make -C /home/data _ci_exec
13 |
14 | _ci_exec: # Actual commands
15 | APP_ALLOW_MISSING_DEPS=true CI_MODE=1 CI=1 buildozer android debug
16 | APP_ALLOW_MISSING_DEPS=true CI_MODE=1 CI=1 buildozer android release
17 |
18 | # Setup
19 |
20 | env:
21 | sudo dpkg --add-architecture i386
22 | sudo apt-get update
23 | sudo apt-get install -y python2.7 python-pip software-properties-common python3 python3-dev python-dev
24 | sudo apt-get install -y mesa-common-dev libgl1-mesa-dev libglu1-mesa-dev zip
25 | sudo add-apt-repository ppa:kivy-team/kivy -y
26 | sudo apt-get update
27 | sudo apt-get install -y build-essential cmake swig ccache git libtool pkg-config libncurses5:i386 libstdc++6:i386 libgtk2.0-0:i386 libpangox-1.0-0:i386 libpangoxft-1.0-0:i386 libidn11:i386 python2.7 python2.7-dev openjdk-8-jdk unzip zlib1g-dev zlib1g:i386
28 | sudo apt-get install -y automake aidl libbz2-dev libffi-dev lld
29 | sudo apt-get install -y python-kivy
30 | sudo pip2 install --upgrade Cython==0.28.6
31 | sudo pip2 install --upgrade colorama appdirs 'sh>=1.10,<1.12.5' jinja2 six clint requests
32 | sudo pip2 install --upgrade git+https://github.com/mkg20001/buildozer kivy
33 | sudo pip2 install "appdirs" "colorama>=0.3.3" 'sh>=1.10,<1.12.5' "jinja2" "six"
34 |
35 | # Targets for setup
36 |
37 | setup: .pre
38 | .env:
39 | @echo "No .env file found..."
40 | @echo "Running setup..."
41 | $(TOOL) setup
42 |
43 | .pre: .env .deps
44 |
45 | # Targets for specific build modes
46 |
47 | .deps:
48 | make -C . $(EXEC_NAME)-deps
49 | touch .deps
50 |
51 | host-deps: prebuild
52 |
53 | docker-deps:
54 | # TODO: rethink below cmd
55 | mkdir -p $(HOME)/.buildozer && sudo chmod 777 $(HOME)/.buildozer && mkdir -p $(HOME)/.gradle && sudo chmod 777 $(HOME)/.gradle && mkdir -p $(HOME)/.android/cache && sudo chmod 777 $(HOME)/.android/cache
56 | $(EXEC) make -C /home/data prebuild # Launch in wrapper
57 |
58 | docker-build:
59 | docker build -t kivy .
60 |
61 | # Actual Targets
62 |
63 | debug: .pre
64 | $(EXEC) env APP_ALLOW_MISSING_DEPS=true buildozer -v android debug
65 |
66 | release: .pre
67 | $(EXEC) env APP_ALLOW_MISSING_DEPS=true buildozer -v android release
68 |
69 | run: .pre
70 | adb $(ADB_FLAG) install -r bin/$(shell dir -w 1 bin | sort | tail -n 1)
71 | make logcat
72 |
73 | logcat:
74 | adb $(ADB_FLAG) logcat | grep "[A-Z] python\|linker\|art\|zn\|watch1\|watch2"
75 |
76 | test: .pre
77 | $(EXEC) buildozer -v android deploy logcat
78 |
79 | prebuild: .env
80 | $(TOOL) prebuild
81 |
82 | # Old targets (will be replaced by automated scripts later)
83 | release-do:
84 | cp -v bin/release/ZeroNet.apk $(HOME)/ZeroNet/data/1A9gZwjdcTh3bpdriaWm7Z4LNdUL8GhDu2
85 | cp -v bin/release/metadata.json $(HOME)/ZeroNet/data/1A9gZwjdcTh3bpdriaWm7Z4LNdUL8GhDu2
86 | release-align:
87 | rm -f bin/release.apk
88 | zipalign -v -p 4 $(shell find bin -type f -iname "*-release-unsigned.apk") bin/release.apk
89 | release-sign:
90 | rm -rf release bin/release
91 | mkdir release
92 | $(shell find $(ANDROID_HOME) -iname "apksigner" | sort | tac | head -n 1) sign --ks $(HOME)/.android/release --out release/ZeroNet.apk bin/release.apk
93 | $(shell find $(ANDROID_HOME) -iname "apksigner" | sort | tac | head -n 1) verify release/ZeroNet.apk
94 | mv release bin/release
95 | $(TOOL) metadata
96 | watch: #runs on desktop
97 | nodemon -e kv,py,json -x /usr/bin/python2 src/main.py
98 |
--------------------------------------------------------------------------------
/src/translate/Translate.py:
--------------------------------------------------------------------------------
1 | import inspect
2 | import json
3 | import logging
4 | import os
5 | import re
6 |
7 | from os_platform import getSystemLang
8 |
9 |
10 | class Translate(dict):
11 |
12 | def __init__(self, lang_dir=None, lang=None):
13 | if not lang_dir:
14 | lang_dir = os.path.join(os.path.dirname(
15 | os.path.abspath(__file__)), "languages")
16 | if not lang:
17 | lang = getSystemLang()
18 | self.lang = lang
19 | self.lang_dir = lang_dir
20 | self.setLanguage(lang)
21 |
22 | def setLanguage(self, lang):
23 | self.lang = lang
24 | self.lang_file = os.path.join(self.lang_dir, "%s.json" % lang)
25 | return self.load()
26 |
27 | def __repr__(self):
28 | return "" % self.lang
29 |
30 | def load(self):
31 | if os.path.isfile(self.lang_file):
32 | data = json.load(open(self.lang_file))
33 | print("Loaded translate file: %s (%s entries)" % (self.lang_file, len(data)))
34 | dict.__init__(self, data)
35 | return True
36 | else:
37 | data = {}
38 | dict.__init__(self, data)
39 | self.clear()
40 | print("Translate file not exists: %s" % self.lang_file)
41 | return False
42 |
43 | def format(self, s, kwargs, nested=False):
44 | kwargs["_"] = self
45 | if nested:
46 | return s.format(**kwargs).format(**kwargs)
47 | else:
48 | return s.format(**kwargs)
49 |
50 | def formatLocals(self, s, nested=False):
51 | kwargs = inspect.currentframe().f_back.f_locals
52 | return self.format(s, kwargs, nested=nested)
53 |
54 | def __call__(self, s):
55 | return self.translateString(s)
56 |
57 | # def __call__(self, s, kwargs=None, nested=False):
58 | # if kwargs:
59 | # return self.format(s, kwargs, nested=nested)
60 | # else:
61 | # kwargs = inspect.currentframe().f_back.f_locals
62 | # return self.format(s, kwargs, nested=nested)
63 |
64 | def __missing__(self, key):
65 | return key
66 |
67 | def pluralize(self, value, single, multi):
68 | if value > 1:
69 | return self[single].format(value)
70 | else:
71 | return self[multi].format(value)
72 |
73 | def translateString(self, string, translate_table=None, mode="js"):
74 | if not translate_table:
75 | translate_table = self
76 |
77 | if string in translate_table:
78 | return translate_table[string]
79 | else:
80 | return string
81 |
82 | def translateData(self, data, translate_table=None, mode="js"):
83 | if not translate_table:
84 | translate_table = self
85 |
86 | data = data.decode("utf8")
87 |
88 | patterns = []
89 | for key, val in list(translate_table.items()):
90 | # Problematic string: only match if called between _(" ") function
91 | if key.startswith("_("):
92 | key = key.replace("_(", "").replace(
93 | ")", "").replace(", ", '", "')
94 | translate_table[key] = "|" + val
95 | patterns.append(re.escape(key))
96 |
97 | def replacer(match):
98 | target = translate_table[match.group(1)]
99 | if mode == "js":
100 | if target and target[0] == "|": # Strict string match
101 | # Only if the match if called between _(" ") function
102 | if match.string[match.start() - 2] == "_":
103 | return '"' + target[1:] + '"'
104 | else:
105 | return '"' + match.group(1) + '"'
106 | return '"' + target + '"'
107 | else:
108 | return match.group(0)[0] + target + match.group(0)[-1]
109 |
110 | if mode == "html":
111 | pattern = '[">](' + "|".join(patterns) + ')["<]'
112 | else:
113 | pattern = '"(' + "|".join(patterns) + ')"'
114 | data = re.sub(pattern, replacer, data)
115 | return data.encode("utf8")
116 |
117 | translate = Translate()
118 |
--------------------------------------------------------------------------------
/tool.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Config
4 |
5 | ADB_FLAG=-d
6 | source .version.sh
7 |
8 | # Vars
9 |
10 | [ -z "$UID" ] && UID=$(id -u)
11 | [ -z "$PWD" ] && PWD="$PWD"
12 |
13 | bold=$(tput bold)
14 | normal=$(tput sgr0)
15 | RED=$(tput setaf 1)
16 | NC="$normal" # No Color
17 |
18 | # Executors
19 |
20 | exec_docker() {
21 | DOCKER_CMD=(docker run -u "$UID" --rm "--privileged=true" -it -e "APP_ALLOW_MISSING_DEPS=true" -e "USE_SDK_WRAPPER=1" -v "$PWD:/home/data" -v "$HOME/.gradle:/home/.gradle" -v "$HOME/.buildozer:/home/.buildozer" -v "$HOME/.android:/home/.android")
22 |
23 | # if [ ! -z "$USE_VENDOR_BUILDOZER" ]; then
24 | DOCKER_CMD+=(-v "$PWD/vendor/buildozer/buildozer:/usr/local/lib/python2.7/dist-packages/buildozer")
25 | # fi
26 |
27 | if [ ! -z "$CI" ]; then
28 | DOCKER_CMD+=(-e "CI=$CI")
29 | fi
30 |
31 | DOCKER_CMD+=("$docker_image" sh -c "echo builder:x:$UID:27:Builder:/home:/bin/bash | tee /etc/passwd > /dev/null && cd /home/data && $*")
32 |
33 | "${DOCKER_CMD[@]}"
34 | }
35 |
36 | exec_host() {
37 | export USE_SDK_WRAPPER=1
38 | export APP_ALLOW_MISSING_DEPS=true
39 | "$@"
40 | }
41 |
42 | _exec() {
43 | [ -z "$*" ] && die "No command passed to exec!"
44 | debug "EXEC $EXEC, CMD $*"
45 | "exec_$EXEC" "$@"
46 | }
47 |
48 | debug() {
49 | [ ! -z "$DEBUG" ] && echo "${bold}DEBUG${NC}: $*"
50 | }
51 |
52 | info() {
53 | echo "${bold}[INFO]${NC}: $*"
54 | }
55 |
56 | menu() {
57 | a=($1) # arrayify
58 | i=0
59 | for c in $1; do # show list
60 | echo -n "[$i] $c"
61 | [ "$i" == "0" ] && echo " (recommended)" || echo
62 | i=$(expr $i + 1)
63 | done
64 | read -p "> " id # prompt user
65 | res="${a[$id]}"
66 | [ -z "$res" ] && echo "Invalid ID: $id" && menu "$1" && return 0
67 | echo "< $res"
68 | }
69 |
70 | error() {
71 | echo "${RED}${bold}[ERROR]${NC}: $*"
72 | }
73 |
74 | die() {
75 | error "$*"
76 | exit 2
77 | }
78 |
79 | # Scripts
80 |
81 | mkenv() {
82 | info "Running 'make env'"
83 | set +e
84 | make -C env
85 | }
86 |
87 | getmeta() {
88 | cat src/zero/src/Config.py | grep "$1 =" | sed -r "s|(.*) = ||g"
89 | }
90 |
91 | # Main Code
92 |
93 | if [ "$1" == "_getvar" ]; then
94 | [ -e .env ] && source .env && echo "${!2}"
95 | exit 0
96 | fi
97 |
98 | [ ! -e .env ] && [ "$1" != "setup" ] && die "No .env file found! Run '$0 setup'"
99 |
100 | source .env
101 |
102 | docker_image="$DOCKER_IMAGE"
103 |
104 | debug "EXEC=$EXEC"
105 | debug "docker_image=$docker_image"
106 |
107 | case "$1" in
108 | setup)
109 | echo "How should buildozer/kivy be executed?"
110 | menu "docker host"
111 | echo "EXEC=$res" > .env
112 | case "$res" in
113 | docker)
114 | echo "Which image should be used?"
115 | echo "(The 'kivy' image should only be used if you are building the image yourself using '$0 docker-build')"
116 | menu "registry.gitlab.com/mkg20001-gh/zeronet-kivy:latest kivy"
117 | echo "DOCKER_IMAGE=$res" >> .env
118 | [ "$res" != "kivy" ] && docker pull "$res"
119 | ;;
120 | host)
121 | echo "Please run 'make host-deps' to complete the setup"
122 | echo "(This will install all needed packages and tools)"
123 | exit 2
124 | ;;
125 | esac
126 | ;;
127 | env)
128 | mkenv
129 | ;;
130 | exec)
131 | shift
132 | _exec "$@"
133 | ;;
134 | prebuild)
135 | if [ -e .pre ]; then rm -rf src/zero && git submodule update; fi
136 | V=$(echo $(cat src/zero/src/Config.py | grep self.version | sed -r "s|self\.version = ['\"](.*)['\"]|\1|g" | head -n 1))
137 | if [ "$V" != "$CUR_VERSION" ]; then echo ".version.sh \$VER_SUFFIX needs to be reset, major version change: $CUR_VERSION != $V" && exit 2; fi
138 | cd src/zero && cp src/Config.py src/Config.py_ && sed -r "s|self\.version = ['\"](.*)['\"]|self.version = \"\1.$VER_SUFFIX\"|g" -i src/Config.py
139 | echo ZGlmZiAtLWdpdCBhL3NyYy9tYWluLnB5IGIvc3JjL21haW4ucHkKaW5kZXggZGZjMzJjYzkuLjlmMjFlZjJjIDEwMDY0NAotLS0gYS9zcmMvbWFpbi5weQorKysgYi9zcmMvbWFpbi5weQpAQCAtNTIsNyArNTIsNyBAQCBpZiBjb25maWcuYWN0aW9uID09ICJtYWluIjoKICAgICAgICAgICAgICAgICBwcmludCgiRXJyb3Igc3RhcnRpbmcgYnJvd3NlcjogJXMiICUgZXJyKQogICAgICAgICBzeXMuZXhpdCgpCiAKLWNvbmZpZy5pbml0TG9nZ2luZygpCitjb25maWcuaW5pdExvZ2dpbmcoY29uc29sZV9sb2dnaW5nPUZhbHNlKQogCiAKICMgRGVidWcgZGVwZW5kZW50IGNvbmZpZ3VyYXRpb24K | base64 -d | git apply -
140 | cd ../../
141 | touch .pre
142 | ;;
143 | metadata)
144 | echo "{\"rev\":$(getmeta self.rev),\"ver\":$(getmeta self.version),\"date\":$(expr $(date +%s) \* 1000)}" > release/metadata.json
145 | ;;
146 | post-sign)
147 | cp -v bin/release/{ZeroNet.apk,metadata.json} $HOME/ZeroNet/data/1A9gZwjdcTh3bpdriaWm7Z4LNdUL8GhDu2
148 | ;;
149 | docker-build)
150 | make docker-build
151 | ;;
152 | *)
153 | die "No command specified! Use '$0 {setup, env, exec, docker-build, prebuild}'"
154 | ;;
155 | esac
156 |
--------------------------------------------------------------------------------
/src/platform_android.py:
--------------------------------------------------------------------------------
1 | # Android Specific Code
2 | import os
3 | import re
4 | import sys
5 | import time
6 | from os import path
7 |
8 | import android
9 | import M2Crypto
10 | from jnius import autoclass
11 | from M2Crypto import EVP, RSA
12 | from platform_service import SystemService
13 | # plyer in pip is old and has bugs, so need to download source code
14 | # manually from plyer repo to replace all the plyer source code folder
15 | # downloaded by buildozer
16 | from plyer.platforms.android import SDK_INT, activity
17 |
18 | mActivity = autoclass('org.kivy.android.PythonActivity').mActivity
19 |
20 |
21 | def getSystemLang():
22 | l = mActivity.getResources().getConfiguration().locale.toString()
23 | print("LOCALE: %s" % l)
24 | match = re.search("^([a-z]{2})_[A-Z]+.*", l)
25 | if match:
26 | return match.group(1)
27 | else:
28 | return "en"
29 |
30 |
31 | def getDir(append=""):
32 | if len(append):
33 | return path.join(mActivity.getExternalFilesDir(None).getPath(), append)
34 | else:
35 | return mActivity.getExternalFilesDir(None).getPath()
36 |
37 |
38 | def realpath():
39 | return os.path.dirname(os.path.realpath(__file__))
40 |
41 |
42 | def getDebug():
43 | return autoclass(activity.getPackageName() + ".BuildConfig").DEBUG
44 |
45 | def wrapSentry(mainFunc):
46 | if not getDebug():
47 | import traceback
48 | try:
49 | import sentry_sdk
50 | from sentry_sdk import capture_exception
51 | sentry_sdk.init("https://1cc0c8280fa54361920e75f014add9fe@sentry.io/1406946")
52 | try:
53 | mainFunc()
54 | except Exception as e:
55 | traceback.print_exc()
56 | capture_exception(e)
57 | except Exception as e:
58 | traceback.print_exc()
59 | mainFunc()
60 | else:
61 | mainFunc()
62 |
63 | # Generate a SSL certificate using module M2Crypto, an existing one will
64 | # be overwritten .
65 |
66 |
67 | def generate_self_signed_cert_m2(cert_dir):
68 | if not os.path.exists(cert_dir):
69 | os.makedirs(cert_dir)
70 | cert_path = os.path.join(cert_dir, 'cert-rsa.pem')
71 | key_path = os.path.join(cert_dir, 'key-rsa.pem')
72 |
73 | if os.path.exists(cert_path):
74 | os.remove(cert_path)
75 | if os.path.exists(key_path):
76 | os.remove(key_path)
77 |
78 | # create a key pair
79 | key = RSA.gen_key(2048, 65537)
80 | key.save_key(key_path, None)
81 | pkey = EVP.PKey() # Converting the RSA key into a PKey() which is stored in a certificate
82 | pkey.assign_rsa(key)
83 |
84 | # create a self-signed cert, the config is copied from src/lib/opensslVerify/openssl.cnf. not sure whether making it random is good or not.
85 | # time for certificate to stay valid
86 | cur_time = M2Crypto.ASN1.ASN1_UTCTIME()
87 | cur_time.set_time(int(time.time()) - 60 * 60 * 24)
88 | expire_time = M2Crypto.ASN1.ASN1_UTCTIME()
89 | expire_time.set_time(int(time.time()) + 60 * 60 * 24 * 365)
90 | # creating a certificate
91 | cert = M2Crypto.X509.X509()
92 | cert.set_pubkey(pkey)
93 | cs_name = M2Crypto.X509.X509_Name()
94 | cs_name.C = "US"
95 | cs_name.ST = 'NY'
96 | cs_name.L = 'New York'
97 | cs_name.O = 'Example, LLC'
98 | cs_name.CN = 'Example Company'
99 | # cs_name.Email = "example@example.com"
100 | cert.set_subject(cs_name)
101 | cert.set_issuer_name(cs_name)
102 | cert.set_not_before(cur_time)
103 | cert.set_not_after(expire_time)
104 | # self signing a certificate
105 | cert.sign(pkey, md="sha256")
106 | cert.save_pem(cert_path)
107 | return cert_path, key_path
108 |
109 |
110 | class Service(SystemService):
111 |
112 | def zeroDir(self):
113 | return os.path.join(os.environ['ANDROID_APP_PATH'], 'zero')
114 |
115 | def getPath(self, append=""):
116 | return getDir(append)
117 |
118 | def runGeneric(self, what, pidid):
119 | if self.isRunning(pidid):
120 | print("Skip starting %s, already running as %s" % (what, self.getPid(pidid)))
121 | return False
122 | service_fullname = activity.getPackageName() + '.Service' + what
123 | service = autoclass(service_fullname)
124 | argument = ""
125 | service.start(mActivity, argument)
126 |
127 | def startWatchdog(self, id):
128 | return self.runGeneric("Watch%s" % id, "watchdog%s" % id)
129 |
130 | def runService(self):
131 | # Generate a SSL certificate to 'data' folder, existing pem files will
132 | # be overwritten . TODO: read the `data_dir` in zeronet.conf
133 | generate_self_signed_cert_m2(
134 | os.path.join(self.getPath("zero"), 'data'))
135 | # Start service ( system will run service.py)
136 | return self.runGeneric("Zn", "zeronet")
137 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ZeroNet-kivy
2 | [简体中文](./README-zh-cn.md)
3 | [Support](https://t.me/zeronet_android)
4 |
5 | This app is a simple GUI to control the ZeroNet client. It is packaged using buildozer and uses [Kivy](https://kivy.io).
6 |
7 | Currently the code of this repo only works on Android, anyone interested in iOS development is welcome to contribute. Simply drop your comment on [this page](https://github.com/HelloZeroNet/ZeroNet-kivy/issues/35) if you want to become a maintainer for that platform!
8 | Currently this project is in Alpha phase, lack of GUI functionalities and creative design, containing many code for testing purpose. Please feel free to contribute!
9 |
10 | # Downloads
11 |
12 | You can download the latest version of the app from:
13 |
14 | - the [ » PlayStore](https://play.google.com/store/apps/details?id=net.mkg20001.zeronet)
15 | - the [ » F-Droid repository for ZeroNet](https://f-droid.mkg20001.io/repos/jVVkbOD2it_bf_UxFIGGh1qa950KrUsq/repo/?fingerprint=005E888A5A203D40E28F372B939B8E5995FB29081EFC845DB99A8D4C14B509E2)
16 | - [ » GitHub Releases](https://github.com/HelloZeroNet/ZeroNet-kivy/releases)
17 |
18 | ## Downloads for really old phones
19 |
20 | If you're using a phone with Android 4 or less then you can't use this app. If you insist you can use the [ » old version](https://gateway.ipfs.io/ipfs/QmWKSoPfXpfvTU7jtiwn51zPVFZ6fWMiKNgDBzbnH9krXY/ZeroNet-OLDVERSION.apk). But beware: NO functionality and NO security are guaranteed.
21 |
22 | You can also go to the list of [ » older releases](https://github.com/mkg20001/ZeroNet-kivy/releases) if you're intrested in the very first versions
23 |
24 | ## Screenshots:
25 |
26 | ### App:
27 |
28 | #### Splash Screen
29 | 
30 | #### UI
31 | 
32 |
33 | ### ZeroNet:
34 |
35 | #### Loading Screen
36 | 
37 | #### ZeroHello
38 | 
39 | #### ZeroMe
40 | 
41 |
42 |
43 | ## Goals:
44 |
45 | * [ ] User-friendly installing
46 | - [ ] Reduce the package size by removing unused files
47 | - [x] Release on F-Droid, Google Play, Apple App Store and other platform's official APP market or package repository.
48 | * [ ] Easy to use
49 | - [ ] Start or stop ZeroNet service by just a single tap
50 | - [ ] Running without killed by system
51 | + [x] On Android, make ZeroNet service Foreground to keep it less likely to be killed. If still killed, create 1~2 daemon services to restart ZeroNet service when it killed
52 | - [ ] Reduce battery and data quota ( bandwidth ) as well as data storage consuming on mobile devices. Auto-adjust the behavior of ZeroNet in different scenarios, e.g. using Wifi or cellular data, being charged or low battery. Of course, users can adjust it by themselves via GUI
53 | - [ ] Keep users.json and other sensitive data in internal private directory of the APP, out of other APPs' reach
54 | - [ ] Import master seed or users.json via GUI to let users import their ZeroNet IDs
55 | - [ ] GUI config of ZeroNet instead of editing zeronet.conf manually
56 | - [ ] Offer a thin client of ZeroNet for users' choice, working like a thin client of Bitcoin, via which users can use ZeroNet without joining as a full client, waiting large data sync, consuming much battery and data quota ( bandwidth ) as well as data storage. The thin client, holding the user's private keys, receives data from random proxies ( gateways ) and posts signed data to random proxies ( gateways ) without user's private keys leaving the user's own device
57 |
58 | Actually, some above goals are out of the scope of this project, which means we also need to contribute to ZeroNet project itself to achieve said goals.
59 |
60 |
61 | ## Tutorial of packaging APK for ZeroNet
62 |
63 | The packaging is not hard, thanks to Kivy's Buildozer which automates many things for us.
64 | [The tutorial is here, which shows you in details how to do that.](./Tutorial-of-packaging-APK.md)
65 |
66 | ## How to use the APK
67 |
68 | * Be careful of your phone's firewall and permission control, let the APK go.
69 | * If you have any problem using the web UI, you can try anther browser
70 | * If you want to shut down ZeroNet, click ZeroHello's top-left ⋮ button and choose `shut down`
71 | * You can update ZeroNet's source code just as you do on your PC: click ZeroHello's top-left ⋮ button, choose Version x.x.x (rev xxxx)
72 | - Even if it says "Already Up-To-Date" just choose it so you'll get newest dev version of ZeroNet
73 | * You can find all the ZeroNet things and do what you want in External Storage/Android/data/net.mkg20001.zeronet/files/zero
74 | * If you find any bug or something, go to External Storage/Android/data/net.mkg20001.zeronet/files/zero/log to see what it said in log
75 |
76 | ## Project Structure
77 | * src
78 | - zeronet.kv - Gui layout
79 | - main.py - Main file
80 | - service.py - Service file
81 | - platform_*.py - Platform Specific code
82 | * zero - ZeroNet Source Code (if content is missing run `git submodule init --recursive`)
83 | - zeronet.py - ZeroNet Launcher
84 | * buildozer.spec - Buildozer config file with package name, title, version, android.permissions, services, etc.
85 |
--------------------------------------------------------------------------------
/src/zeronet.kv:
--------------------------------------------------------------------------------
1 | #:kivy 1.8.0
2 | #:import _ translate.translate
3 | #:import hex kivy.utils.get_color_from_hex
4 | #:import hex2 light_colors.hex
5 | #:import browser webbrowser.open
6 |
7 |