diff --git a/.gitignore b/.gitignore index 58560b2..c32c48e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ dist pwnagotchi.egg-info *backup*.tgz *backup*.gz +.vscode diff --git a/bin/pwnagotchi b/bin/pwnagotchi index 5b93d3f..6e3ab4a 100755 --- a/bin/pwnagotchi +++ b/bin/pwnagotchi @@ -14,9 +14,11 @@ from pwnagotchi import plugins from pwnagotchi import log from pwnagotchi.identity import KeyPair from pwnagotchi.agent import Agent +from pwnagotchi.ui import fonts from pwnagotchi.ui.display import Display from pwnagotchi import restart from pwnagotchi import fs +from pwnagotchi.utils import DottedTomlEncoder def do_clear(display): @@ -122,11 +124,13 @@ if __name__ == '__main__': config = utils.load_config(args) if args.print_config: - print(toml.dumps(config)) + print(toml.dumps(config, encoder=DottedTomlEncoder())) sys.exit(0) + pwnagotchi.config = config fs.setup_mounts(config) log.setup_logging(args, config) + fonts.init(config) pwnagotchi.set_name(config['main']['name']) diff --git a/builder/pwnagotchi.yml b/builder/pwnagotchi.yml index 8dd1379..b821632 100644 --- a/builder/pwnagotchi.yml +++ b/builder/pwnagotchi.yml @@ -104,6 +104,7 @@ - python3-flask - python3-flask-cors - python3-flaskext.wtf + - fonts-ipaexfont-gothic tasks: - name: change hostname diff --git a/pwnagotchi/__init__.py b/pwnagotchi/__init__.py index 3c0dbc6..58e7702 100644 --- a/pwnagotchi/__init__.py +++ b/pwnagotchi/__init__.py @@ -10,6 +10,7 @@ from pwnagotchi import fs from pwnagotchi._version import __version__ _name = None +config = None def set_name(new_name): @@ -66,8 +67,6 @@ def mem_usage(): kb_mem_total = int(line.split()[1]) if line.startswith("MemFree:"): kb_mem_free = int(line.split()[1]) - if line.startswith("MemAvailable:"): - kb_mem_available = int(line.split()[1]) if line.startswith("Buffers:"): kb_main_buffers = int(line.split()[1]) if line.startswith("Cached:"): @@ -78,18 +77,27 @@ def mem_usage(): return 0 -def cpu_load(): +def _cpu_stat(): + """ + Returns the splitted first line of the /proc/stat file + """ with open('/proc/stat', 'rt') as fp: - for line in fp: - line = line.strip() - if line.startswith('cpu '): - parts = list(map(int, line.split()[1:])) - user_n = parts[0] - sys_n = parts[2] - idle_n = parts[3] - tot = user_n + sys_n + idle_n - return (user_n + sys_n) / tot - return 0 + return list(map(int,fp.readline().split()[1:])) + + +def cpu_load(): + """ + Returns the current cpuload + """ + parts0 = _cpu_stat() + time.sleep(0.1) + parts1 = _cpu_stat() + parts_diff = [p1 - p0 for (p0, p1) in zip(parts0, parts1)] + user, nice, sys, idle, iowait, irq, softirq, steal, _guest, _guest_nice = parts_diff + idle_sum = idle + iowait + non_idle_sum = user + nice + sys + irq + softirq + steal + total = idle_sum + non_idle_sum + return non_idle_sum / total def temperature(celsius=True): diff --git a/pwnagotchi/defaults.toml b/pwnagotchi/defaults.toml index a3e058e..3d5c69d 100644 --- a/pwnagotchi/defaults.toml +++ b/pwnagotchi/defaults.toml @@ -148,6 +148,8 @@ personality.sad_num_epochs = 25 personality.bond_encounters_factor = 20000 ui.fps = 0.0 +ui.font.name = "DejaVuSansMono" # for japanese: fonts-japanese-gothic +ui.font.size_offset = 0 # will be added to the font size ui.faces.look_r = "( ⚆_⚆)" ui.faces.look_l = "(☉_☉ )" diff --git a/pwnagotchi/locale/jp/LC_MESSAGES/voice.mo b/pwnagotchi/locale/jp/LC_MESSAGES/voice.mo index 2ff6027..536f891 100644 Binary files a/pwnagotchi/locale/jp/LC_MESSAGES/voice.mo and b/pwnagotchi/locale/jp/LC_MESSAGES/voice.mo differ diff --git a/pwnagotchi/locale/jp/LC_MESSAGES/voice.po b/pwnagotchi/locale/jp/LC_MESSAGES/voice.po index 52acd38..efaabc4 100644 --- a/pwnagotchi/locale/jp/LC_MESSAGES/voice.po +++ b/pwnagotchi/locale/jp/LC_MESSAGES/voice.po @@ -3,12 +3,11 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR 24534649+wytshadow@users.noreply.github.com, 2019. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-16 15:05+0200\n" +"POT-Creation-Date: 2020-01-25 21:57+0900\n" "PO-Revision-Date: 2019-10-16 15:05+0200\n" "Last-Translator: wytshadow <24534649+wytshadow@users.noreply.github.com>\n" "Language-Team: pwnagotchi <24534649+wytshadow@users.noreply.github.com>\n" @@ -21,170 +20,207 @@ msgid "ZzzzZZzzzzZzzz" msgstr "すやすや〜" msgid "Hi, I'm Pwnagotchi! Starting ..." -msgstr "こんにちは、ポウナゴッチです!始めている。。。" +msgstr "僕、 ポーナゴッチです!" msgid "New day, new hunt, new pwns!" -msgstr "" +msgstr "ポーンしようよ。" msgid "Hack the Planet!" msgstr "ハックザプラネット!" msgid "AI ready." -msgstr "人工知能の準備ができました。" +msgstr "AIの準備ができました。" msgid "The neural network is ready." -msgstr "ニューラルネットワークの準備ができました。" +msgstr "ニューラルネットワークの\n準備ができました。" + +msgid "Generating keys, do not turn off ..." +msgstr "鍵生成をしてます。\n電源を落とさないでね。" #, python-brace-format msgid "Hey, channel {channel} is free! Your AP will say thanks." -msgstr "ねえ、チャンネル{channel}は無料です! キミのAPは感謝を言います。" +msgstr "チャンネル\n {channel} \nはfreeだよ。ありがとうね。" + +msgid "Reading last session logs ..." +msgstr "session log を読んでます。" + +#, python-brace-format +msgid "Read {lines_so_far} log lines so far ..." +msgstr "{lines_so_far} 行目長いよぉ。" msgid "I'm bored ..." -msgstr "退屈です。。。" +msgstr "退屈だぁ。。。" msgid "Let's go for a walk!" -msgstr "散歩に行きましょう!" +msgstr "散歩に行こうよ!" msgid "This is the best day of my life!" -msgstr "今日は私の人生で最高の日です!" +msgstr "人生最高の日だよ!" msgid "Shitty day :/" -msgstr "" +msgstr "がっかりな日だよ。orz" msgid "I'm extremely bored ..." -msgstr "とても退屈です。" +msgstr "退屈だね。" msgid "I'm very sad ..." -msgstr "とても悲しいです。。。" +msgstr "あ~悲しいよぉ。" msgid "I'm sad" -msgstr "悲しいです。" +msgstr "悲しいね。" + +msgid "Leave me alone ..." +msgstr "ひとりぼっちだよ。" + +msgid "I'm mad at you!" +msgstr "怒っちゃうよ。" msgid "I'm living the life!" -msgstr "人生を生きている!" +msgstr "わくわくするね。" msgid "I pwn therefore I am." -msgstr "" +msgstr "ポーンしてこそのオレ。" msgid "So many networks!!!" -msgstr "たくさんネットワークがある!!!" +msgstr "たくさん\nWiFiが飛んでるよ!" msgid "I'm having so much fun!" -msgstr "とても楽しんでいます!" +msgstr "楽しいよぉ!" msgid "My crime is that of curiosity ..." -msgstr "" +msgstr "APに興味津々..." #, python-brace-format -msgid "Hello {name}! Nice to meet you. {name}" -msgstr "こんにちは{name}!初めまして。{name}" +msgid "Hello {name}! Nice to meet you." +msgstr "こんにちは{name}!\n初めまして。{name}" #, python-brace-format -msgid "Unit {name} is nearby! {name}" -msgstr "" +msgid "Yo {name}! Sup?" +msgstr "ねぇねぇ、\n{name} どうしたの?" + +#, python-brace-format +msgid "Hey {name} how are you doing?" +msgstr "{name} こんにちは" + +#, python-brace-format +msgid "Unit {name} is nearby!" +msgstr "{name} が近くにいるよ。" #, python-brace-format msgid "Uhm ... goodbye {name}" -msgstr "ええと。。。さようなら{name}" +msgstr "じゃあね、さようなら {name}" #, python-brace-format msgid "{name} is gone ..." -msgstr "{name}がなくなった。。。" +msgstr "{name}\nがいなくなったよ。" #, python-brace-format msgid "Whoops ... {name} is gone." -msgstr "おっと。。。{name}がなくなった。" +msgstr "あらら、\n{name}\nがいなくなったね。" #, python-brace-format msgid "{name} missed!" -msgstr "{name}逃した!" +msgstr "{name} が逃げた!" msgid "Missed!" -msgstr "逃した!" +msgstr "残念、逃した!" + +msgid "Good friends are a blessing!" +msgstr "良い仲間にめぐりあえたよ。" + +msgid "I love my friends!" +msgstr "友達は大好きだよ。" msgid "Nobody wants to play with me ..." -msgstr "誰も僕と一緒にプレーしたくない。。。" +msgstr "誰も僕と一緒に\nあそんでくれない。" msgid "I feel so alone ..." -msgstr "僕は孤独を感じる。。。" +msgstr "ひとりぼっちだよ。" msgid "Where's everybody?!" -msgstr "みんなどこ?!" +msgstr "みんなどこにいるの?!" #, python-brace-format msgid "Napping for {secs}s ..." -msgstr "{secs}寝ている。" +msgstr "{secs}秒 寝ます。" msgid "Zzzzz" -msgstr "すや〜" +msgstr "ぐぅ〜" #, python-brace-format msgid "ZzzZzzz ({secs}s)" -msgstr "すやすや〜 ({secs})" +msgstr "すやすや〜 ({secs}秒)" msgid "Good night." -msgstr "お休みなさい。" +msgstr "おやすみなさい。" msgid "Zzz" -msgstr "す〜" +msgstr "ぐぅ~" #, python-brace-format msgid "Waiting for {secs}s ..." -msgstr "{secs}を待っている。。。" +msgstr "{secs}秒 待ちです。" #, python-brace-format msgid "Looking around ({secs}s)" -msgstr "{secs}を探している。" +msgstr "{secs}秒 探してます。" #, python-brace-format msgid "Hey {what} let's be friends!" -msgstr "ちょっと{what}友だちになりましょう!" +msgstr "ねぇねぇ\n{what} \n友だちになろうよ。" #, python-brace-format msgid "Associating to {what}" -msgstr "" +msgstr "{what} \nとつながるかな?" #, python-brace-format msgid "Yo {what}!" -msgstr "よー{what}!" +msgstr "ねぇねぇ\n{what}" #, python-brace-format msgid "Just decided that {mac} needs no WiFi!" -msgstr "" +msgstr "{mac}\nはWiFiじゃないのね。" #, python-brace-format msgid "Deauthenticating {mac}" -msgstr "" +msgstr "{mac}\nの認証取得中..." #, python-brace-format msgid "Kickbanning {mac}!" -msgstr "" +msgstr "{mac}\nに拒否られた。" #, python-brace-format msgid "Cool, we got {num} new handshake{plural}!" -msgstr "よし、{num}新しいハンドシェイクがある!" +msgstr "おぉ、\n{num}回\nハンドシェイクがあったよ!" -msgid "Oops, something went wrong ... Rebooting ..." -msgstr "おっと!何かが間違っていた。。。リブートしている。。。" +#, python-brace-format +msgid "You have {count} new message{plural}!" +msgstr "おぉ、\n{count}個メッセージがあるよ!" + +msgid "Ops, something went wrong ... Rebooting ..." +msgstr "何か間違った。\nリブートしている。" #, python-brace-format msgid "Kicked {num} stations\n" -msgstr "" +msgstr "{num}回拒否された。\n" + +msgid "Made >999 new friends\n" +msgstr "1000人以上友達ができた。\n" #, python-brace-format msgid "Made {num} new friends\n" -msgstr "{num}人の新しい友達を作りました\n" +msgstr "{num}人友達ができた。\n" #, python-brace-format msgid "Got {num} handshakes\n" -msgstr "{num}ハンドシェイクがある。\n" +msgstr "{num}回ハンドシェイクした。\n" msgid "Met 1 peer" -msgstr "1人の仲間を会いました。" +msgstr "1人 仲間に会いました。" #, python-brace-format msgid "Met {num} peers" -msgstr "{num}人の仲間を会いました。" +msgstr "{num}人 仲間に会いました。" #, python-brace-format msgid "" @@ -192,6 +228,9 @@ msgid "" "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "#pwnlog #pwnlife #hacktheplanet #skynet" msgstr "" +"{duration}中{deauted}のAPに拒否されたけど、{associated}回チャンスがあって" +"{handshakes}回ハンドシェイクがあったよ。。 #pownagotchi #pwnlog #pwnlife " +"#hacktheplanet #skynet" msgid "hours" msgstr "時間" @@ -203,7 +242,7 @@ msgid "seconds" msgstr "秒" msgid "hour" -msgstr "時間" +msgstr "時" msgid "minute" msgstr "分" diff --git a/pwnagotchi/plugins/__init__.py b/pwnagotchi/plugins/__init__.py index c8a70c6..6616be6 100644 --- a/pwnagotchi/plugins/__init__.py +++ b/pwnagotchi/plugins/__init__.py @@ -4,7 +4,10 @@ import _thread import threading import importlib, importlib.util import logging +import pwnagotchi from pwnagotchi.ui import view +from pwnagotchi.utils import save_config + default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default") loaded = {} @@ -37,10 +40,16 @@ def toggle_plugin(name, enable=True): returns True if changed, otherwise False """ global loaded, database + + if pwnagotchi.config: + pwnagotchi.config['main']['plugins'][name]['enabled'] = enable + save_config(pwnagotchi.config, '/etc/pwnagotchi/config.toml') + if not enable and name in loaded: if getattr(loaded[name], 'on_unload', None): loaded[name].on_unload(view.ROOT) del loaded[name] + return True if enable and name in database and name not in loaded: diff --git a/pwnagotchi/plugins/default/webcfg.py b/pwnagotchi/plugins/default/webcfg.py index d870953..4bf0538 100644 --- a/pwnagotchi/plugins/default/webcfg.py +++ b/pwnagotchi/plugins/default/webcfg.py @@ -2,8 +2,8 @@ import logging import json import toml import _thread -import pwnagotchi.plugins as plugins -from pwnagotchi import restart +from pwnagotchi import restart, plugins +from pwnagotchi.utils import save_config from flask import abort from flask import render_template_string @@ -499,13 +499,10 @@ class WebConfig(plugins.Plugin): elif request.method == "POST": if path == "save-config": try: - parsed_toml = toml.loads(request.get_json()) - with open('/etc/pwnagotchi/config.toml') as config_file: - toml.dump(parsed_toml, config_file) - + save_config(request.get_json(), '/etc/pwnagotchi/config.toml') # test _thread.start_new_thread(restart, (self.mode,)) return "success" except Exception as ex: logging.error(ex) - return "config error" + return "config error", 500 abort(404) diff --git a/pwnagotchi/ui/fonts.py b/pwnagotchi/ui/fonts.py index ca616d3..36f35ea 100644 --- a/pwnagotchi/ui/fonts.py +++ b/pwnagotchi/ui/fonts.py @@ -1,18 +1,38 @@ from PIL import ImageFont -PATH = '/usr/share/fonts/truetype/dejavu/DejaVuSansMono' +# should not be changed +FONT_NAME = 'DejaVuSansMono' -Bold = ImageFont.truetype("%s-Bold.ttf" % PATH, 10) -BoldSmall = ImageFont.truetype("%s-Bold.ttf" % PATH, 8) -BoldBig = ImageFont.truetype("%s-Bold.ttf" % PATH, 25) -Medium = ImageFont.truetype("%s.ttf" % PATH, 10) -Small = ImageFont.truetype("%s.ttf" % PATH, 9) -Huge = ImageFont.truetype("%s-Bold.ttf" % PATH, 25) +# can be changed +STATUS_FONT_NAME = None +SIZE_OFFSET = 0 + +Bold = None +BoldSmall = None +BoldBig = None +Medium = None +Small = None +Huge = None -def setup(bold, bold_small, medium, huge): - global PATH, Bold, BoldSmall, Medium, Huge - Bold = ImageFont.truetype("%s-Bold.ttf" % PATH, bold) - BoldSmall = ImageFont.truetype("%s-Bold.ttf" % PATH, bold_small) - Medium = ImageFont.truetype("%s.ttf" % PATH, medium) - Huge = ImageFont.truetype("%s-Bold.ttf" % PATH, huge) +def init(config): + global STATUS_FONT_NAME, SIZE_OFFSET + STATUS_FONT_NAME = config['ui']['font']['name'] + SIZE_OFFSET = config['ui']['font']['size_offset'] + setup(10, 8, 10, 25, 25, 9) + + +def status_font(old_font): + global STATUS_FONT_NAME, SIZE_OFFSET + return ImageFont.truetype(STATUS_FONT_NAME, size=old_font.size + SIZE_OFFSET) + + +def setup(bold, bold_small, medium, huge, bold_big, small): + global Bold, BoldSmall, Medium, Huge, BoldBig, Small, FONT_NAME + + Small = ImageFont.truetype(FONT_NAME, small) + Medium = ImageFont.truetype(FONT_NAME, medium) + BoldSmall = ImageFont.truetype("%s-Bold" % FONT_NAME, bold_small) + Bold = ImageFont.truetype("%s-Bold" % FONT_NAME, bold) + BoldBig = ImageFont.truetype("%s-Bold" % FONT_NAME, bold_big) + Huge = ImageFont.truetype("%s-Bold" % FONT_NAME, huge) diff --git a/pwnagotchi/ui/hw/base.py b/pwnagotchi/ui/hw/base.py index e3e0db0..72793b0 100644 --- a/pwnagotchi/ui/hw/base.py +++ b/pwnagotchi/ui/hw/base.py @@ -22,7 +22,7 @@ class DisplayImpl(object): # status is special :D 'status': { 'pos': (0, 0), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 20 } } diff --git a/pwnagotchi/ui/hw/dfrobot.py b/pwnagotchi/ui/hw/dfrobot.py index b79c7fa..1d9c8ee 100644 --- a/pwnagotchi/ui/hw/dfrobot.py +++ b/pwnagotchi/ui/hw/dfrobot.py @@ -9,7 +9,7 @@ class DFRobot(DisplayImpl): self._display = None def layout(self): - fonts.setup(10, 9, 10, 35) + fonts.setup(10, 9, 10, 35, 25, 9) self._layout['width'] = 250 self._layout['height'] = 122 self._layout['face'] = (0, 40) @@ -25,7 +25,7 @@ class DFRobot(DisplayImpl): self._layout['mode'] = (225, 109) self._layout['status'] = { 'pos': (125, 20), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 20 } return self._layout @@ -40,4 +40,4 @@ class DFRobot(DisplayImpl): self._display.display(buf) def clear(self): - self._display.Clear(0xFF) \ No newline at end of file + self._display.Clear(0xFF) diff --git a/pwnagotchi/ui/hw/inky.py b/pwnagotchi/ui/hw/inky.py index 7ae3327..bb02fd7 100644 --- a/pwnagotchi/ui/hw/inky.py +++ b/pwnagotchi/ui/hw/inky.py @@ -10,7 +10,7 @@ class Inky(DisplayImpl): self._display = None def layout(self): - fonts.setup(10, 8, 10, 28) + fonts.setup(10, 8, 10, 28, 25, 9) self._layout['width'] = 212 self._layout['height'] = 104 self._layout['face'] = (0, 37) @@ -26,7 +26,7 @@ class Inky(DisplayImpl): self._layout['mode'] = (187, 93) self._layout['status'] = { 'pos': (102, 18), - 'font': fonts.Small, + 'font': fonts.status_font(fonts.Small), 'max': 20 } return self._layout diff --git a/pwnagotchi/ui/hw/lcdhat.py b/pwnagotchi/ui/hw/lcdhat.py index 92e45a7..1e76799 100644 --- a/pwnagotchi/ui/hw/lcdhat.py +++ b/pwnagotchi/ui/hw/lcdhat.py @@ -10,7 +10,7 @@ class LcdHat(DisplayImpl): self._display = None def layout(self): - fonts.setup(10, 9, 10, 35) + fonts.setup(10, 9, 10, 35, 25, 9) self._layout['width'] = 240 self._layout['height'] = 240 self._layout['face'] = (0, 40) @@ -26,7 +26,7 @@ class LcdHat(DisplayImpl): self._layout['mode'] = (215, 109) self._layout['status'] = { 'pos': (125, 20), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 20 } diff --git a/pwnagotchi/ui/hw/oledhat.py b/pwnagotchi/ui/hw/oledhat.py index 3673630..1e66a2a 100644 --- a/pwnagotchi/ui/hw/oledhat.py +++ b/pwnagotchi/ui/hw/oledhat.py @@ -10,7 +10,7 @@ class OledHat(DisplayImpl): self._display = None def layout(self): - fonts.setup(8, 8, 8, 8) + fonts.setup(8, 8, 8, 8, 25, 9) self._layout['width'] = 128 self._layout['height'] = 64 self._layout['face'] = (0, 32) @@ -26,7 +26,7 @@ class OledHat(DisplayImpl): self._layout['mode'] = (103, 10) self._layout['status'] = { 'pos': (30, 18), - 'font': fonts.Small, + 'font': fonts.status_font(fonts.Small), 'max': 18 } return self._layout diff --git a/pwnagotchi/ui/hw/papirus.py b/pwnagotchi/ui/hw/papirus.py index 8da13be..44d0500 100644 --- a/pwnagotchi/ui/hw/papirus.py +++ b/pwnagotchi/ui/hw/papirus.py @@ -11,7 +11,7 @@ class Papirus(DisplayImpl): self._display = None def layout(self): - fonts.setup(10, 8, 10, 23) + fonts.setup(10, 8, 10, 23, 25, 9) self._layout['width'] = 200 self._layout['height'] = 96 self._layout['face'] = (0, 24) @@ -27,7 +27,7 @@ class Papirus(DisplayImpl): self._layout['mode'] = (175, 86) self._layout['status'] = { 'pos': (85, 14), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 16 } return self._layout diff --git a/pwnagotchi/ui/hw/spotpear24inch.py b/pwnagotchi/ui/hw/spotpear24inch.py index e93b071..73f4b9b 100644 --- a/pwnagotchi/ui/hw/spotpear24inch.py +++ b/pwnagotchi/ui/hw/spotpear24inch.py @@ -11,7 +11,7 @@ class Spotpear24inch(DisplayImpl): self._display = None def layout(self): - fonts.setup(12, 10, 12, 70) + fonts.setup(12, 10, 12, 70, 25, 9) self._layout['width'] = 320 self._layout['height'] = 240 self._layout['face'] = (35, 50) @@ -27,7 +27,7 @@ class Spotpear24inch(DisplayImpl): self._layout['mode'] = (280, 220) self._layout['status'] = { 'pos': (80, 160), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 20 } diff --git a/pwnagotchi/ui/hw/waveshare1.py b/pwnagotchi/ui/hw/waveshare1.py index 40ecc3f..4716fc4 100644 --- a/pwnagotchi/ui/hw/waveshare1.py +++ b/pwnagotchi/ui/hw/waveshare1.py @@ -11,7 +11,7 @@ class WaveshareV1(DisplayImpl): def layout(self): if self.config['color'] == 'black': - fonts.setup(10, 9, 10, 35) + fonts.setup(10, 9, 10, 35, 25, 9) self._layout['width'] = 250 self._layout['height'] = 122 self._layout['face'] = (0, 40) @@ -27,11 +27,11 @@ class WaveshareV1(DisplayImpl): self._layout['mode'] = (225, 109) self._layout['status'] = { 'pos': (125, 20), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 20 } else: - fonts.setup(10, 8, 10, 25) + fonts.setup(10, 8, 10, 25, 25, 9) self._layout['width'] = 212 self._layout['height'] = 104 self._layout['face'] = (0, 26) @@ -47,7 +47,7 @@ class WaveshareV1(DisplayImpl): self._layout['mode'] = (187, 93) self._layout['status'] = { 'pos': (91, 15), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 20 } return self._layout diff --git a/pwnagotchi/ui/hw/waveshare144lcd.py b/pwnagotchi/ui/hw/waveshare144lcd.py index d1d2044..0cef5f2 100644 --- a/pwnagotchi/ui/hw/waveshare144lcd.py +++ b/pwnagotchi/ui/hw/waveshare144lcd.py @@ -10,7 +10,7 @@ class Waveshare144lcd(DisplayImpl): self._display = None def layout(self): - fonts.setup(10, 8, 10, 18) + fonts.setup(10, 8, 10, 18, 25, 9) self._layout['width'] = 128 self._layout['height'] = 128 self._layout['face'] = (0, 43) @@ -26,7 +26,7 @@ class Waveshare144lcd(DisplayImpl): self._layout['mode'] = (0, 117) self._layout['status'] = { 'pos': (65, 26), - 'font': fonts.Small, + 'font': fonts.status_font(fonts.Small), 'max': 12 } return self._layout diff --git a/pwnagotchi/ui/hw/waveshare154inch.py b/pwnagotchi/ui/hw/waveshare154inch.py index fc9cfa7..a678121 100644 --- a/pwnagotchi/ui/hw/waveshare154inch.py +++ b/pwnagotchi/ui/hw/waveshare154inch.py @@ -10,7 +10,7 @@ class Waveshare154inch(DisplayImpl): self._display = None def layout(self): - fonts.setup(10, 9, 10, 35) + fonts.setup(10, 9, 10, 35, 25, 9) self._layout['width'] = 200 self._layout['height'] = 200 self._layout['face'] = (0, 40) @@ -26,7 +26,7 @@ class Waveshare154inch(DisplayImpl): self._layout['mode'] = (170, 187) self._layout['status'] = { 'pos': (5, 90), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 20 } return self._layout diff --git a/pwnagotchi/ui/hw/waveshare2.py b/pwnagotchi/ui/hw/waveshare2.py index 5065f65..fa00aaf 100644 --- a/pwnagotchi/ui/hw/waveshare2.py +++ b/pwnagotchi/ui/hw/waveshare2.py @@ -11,7 +11,7 @@ class WaveshareV2(DisplayImpl): def layout(self): if self.config['color'] == 'black': - fonts.setup(10, 9, 10, 35) + fonts.setup(10, 9, 10, 35, 25, 9) self._layout['width'] = 250 self._layout['height'] = 122 self._layout['face'] = (0, 40) @@ -27,11 +27,11 @@ class WaveshareV2(DisplayImpl): self._layout['mode'] = (225, 109) self._layout['status'] = { 'pos': (125, 20), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 20 } else: - fonts.setup(10, 8, 10, 25) + fonts.setup(10, 8, 10, 25, 25, 9) self._layout['width'] = 212 self._layout['height'] = 104 self._layout['face'] = (0, 26) @@ -48,7 +48,7 @@ class WaveshareV2(DisplayImpl): self._layout['mode'] = (187, 93) self._layout['status'] = { 'pos': (125, 20), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 14 } return self._layout diff --git a/pwnagotchi/ui/hw/waveshare213bc.py b/pwnagotchi/ui/hw/waveshare213bc.py index 70309a8..f889c9b 100644 --- a/pwnagotchi/ui/hw/waveshare213bc.py +++ b/pwnagotchi/ui/hw/waveshare213bc.py @@ -10,7 +10,7 @@ class Waveshare213bc(DisplayImpl): self._display = None def layout(self): - fonts.setup(10, 8, 10, 25) + fonts.setup(10, 8, 10, 25, 25, 9) self._layout['width'] = 212 self._layout['height'] = 104 self._layout['face'] = (0, 26) @@ -26,7 +26,7 @@ class Waveshare213bc(DisplayImpl): self._layout['mode'] = (187, 93) self._layout['status'] = { 'pos': (91, 15), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 20 } return self._layout diff --git a/pwnagotchi/ui/hw/waveshare213d.py b/pwnagotchi/ui/hw/waveshare213d.py index 9aa8ff8..0313081 100644 --- a/pwnagotchi/ui/hw/waveshare213d.py +++ b/pwnagotchi/ui/hw/waveshare213d.py @@ -10,7 +10,7 @@ class Waveshare213d(DisplayImpl): self._display = None def layout(self): - fonts.setup(10, 8, 10, 25) + fonts.setup(10, 8, 10, 25, 25, 9) self._layout['width'] = 212 self._layout['height'] = 104 self._layout['face'] = (0, 26) @@ -26,7 +26,7 @@ class Waveshare213d(DisplayImpl): self._layout['mode'] = (187, 93) self._layout['status'] = { 'pos': (91, 15), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 20 } return self._layout diff --git a/pwnagotchi/ui/hw/waveshare27inch.py b/pwnagotchi/ui/hw/waveshare27inch.py index 0cbc168..29fbbbe 100644 --- a/pwnagotchi/ui/hw/waveshare27inch.py +++ b/pwnagotchi/ui/hw/waveshare27inch.py @@ -10,7 +10,7 @@ class Waveshare27inch(DisplayImpl): self._display = None def layout(self): - fonts.setup(10, 9, 10, 35) + fonts.setup(10, 9, 10, 35, 25, 9) self._layout['width'] = 264 self._layout['height'] = 176 self._layout['face'] = (66, 27) @@ -26,7 +26,7 @@ class Waveshare27inch(DisplayImpl): self._layout['mode'] = (239, 163) self._layout['status'] = { 'pos': (38, 93), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 40 } return self._layout diff --git a/pwnagotchi/ui/hw/waveshare29inch.py b/pwnagotchi/ui/hw/waveshare29inch.py index cabbee9..2ae2b5a 100644 --- a/pwnagotchi/ui/hw/waveshare29inch.py +++ b/pwnagotchi/ui/hw/waveshare29inch.py @@ -10,7 +10,7 @@ class Waveshare29inch(DisplayImpl): self._display = None def layout(self): - fonts.setup(10, 9, 10, 35) + fonts.setup(10, 9, 10, 35, 25, 9) self._layout['width'] = 296 self._layout['height'] = 128 self._layout['face'] = (0, 40) @@ -26,7 +26,7 @@ class Waveshare29inch(DisplayImpl): self._layout['mode'] = (268, 114) self._layout['status'] = { 'pos': (130, 25), - 'font': fonts.Medium, + 'font': fonts.status_font(fonts.Medium), 'max': 28 } return self._layout diff --git a/pwnagotchi/utils.py b/pwnagotchi/utils.py index 17bd79f..92a42e0 100644 --- a/pwnagotchi/utils.py +++ b/pwnagotchi/utils.py @@ -10,11 +10,43 @@ import json import shutil import toml import sys +import re import pwnagotchi +from toml.encoder import TomlEncoder, _dump_str from pwnagotchi.fs import ensure_write +class DottedTomlEncoder(TomlEncoder): + """ + Dumps the toml into the dotted-key format + """ + + def __init__(self, _dict=dict): + super(DottedTomlEncoder, self).__init__(_dict) + + def dump_sections(self, o, sup): + retstr = "" + pre = "" + + if sup: + pre = sup + "." + + for section, value in o.items(): + section = str(section) + qsection = section + if not re.match(r'^[A-Za-z0-9_-]+$', section): + qsection = _dump_str(section) + if value is not None: + if isinstance(value, dict): + toadd, _ = self.dump_sections(value, pre + qsection) + retstr += toadd + else: + retstr += (pre + qsection + " = " + + str(self.dump_value(value)) + '\n') + return (retstr, self._dict()) + + # https://stackoverflow.com/questions/823196/yaml-merge-in-python def merge_config(user, default): if isinstance(user, dict) and isinstance(default, dict): @@ -44,6 +76,11 @@ def keys_to_str(data): return converted_dict +def save_config(config, target): + with open(target, 'wt') as fp: + fp.write(toml.dumps(config, encoder=DottedTomlEncoder())) + return True + def load_config(args): default_config_path = os.path.dirname(args.config) if not os.path.exists(default_config_path): diff --git a/requirements.txt b/requirements.txt index d2ec1d4..bd8d63f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ pycryptodome==3.9.4 requests==2.21.0 -PyYAML==5.1 +PyYAML==5.3.1 scapy==2.4.3 gym==0.14.0 scipy==1.3.1 @@ -17,7 +17,7 @@ spidev==3.4 gast==0.2.2 flask==1.0.2 flask-cors==3.0.7 -flask-wtf==0.14.2 +flask-wtf==0.14.3 dbus-python==1.2.12 toml==0.10.0 python-dateutil==2.8.1