misc: several improvements on the web ui
This commit is contained in:
parent
6e26463278
commit
b1d8aa3ba1
@ -32,7 +32,10 @@ if __name__ == '__main__':
|
|||||||
help="Enable debug logs.")
|
help="Enable debug logs.")
|
||||||
|
|
||||||
parser.add_argument('--version', dest="version", action="store_true", default=False,
|
parser.add_argument('--version', dest="version", action="store_true", default=False,
|
||||||
help="Prints the version.")
|
help="Print the version.")
|
||||||
|
|
||||||
|
parser.add_argument('--print-config', dest="print_config", action="store_true", default=False,
|
||||||
|
help="Print the configuration.")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@ -41,6 +44,10 @@ if __name__ == '__main__':
|
|||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
config = utils.load_config(args)
|
config = utils.load_config(args)
|
||||||
|
if args.print_config:
|
||||||
|
print(yaml.dump(config, default_flow_style=False))
|
||||||
|
exit(0)
|
||||||
|
|
||||||
utils.setup_logging(args, config)
|
utils.setup_logging(args, config)
|
||||||
|
|
||||||
pwnagotchi.set_name(config['main']['name'])
|
pwnagotchi.set_name(config['main']['name'])
|
||||||
@ -53,8 +60,6 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
logging.info("%s@%s (v%s)" % (pwnagotchi.name(), agent.fingerprint(), pwnagotchi.version))
|
logging.info("%s@%s (v%s)" % (pwnagotchi.name(), agent.fingerprint(), pwnagotchi.version))
|
||||||
|
|
||||||
logging.debug("effective configuration:\n\n%s\n\n" % yaml.dump(config, default_flow_style=False))
|
|
||||||
|
|
||||||
for _, plugin in plugins.loaded.items():
|
for _, plugin in plugins.loaded.items():
|
||||||
logging.debug("plugin '%s' v%s" % (plugin.__class__.__name__, plugin.__version__))
|
logging.debug("plugin '%s' v%s" % (plugin.__class__.__name__, plugin.__version__))
|
||||||
|
|
||||||
|
@ -12,8 +12,12 @@ API_ADDRESS = "http://127.0.0.1:8666/api/v1"
|
|||||||
|
|
||||||
def is_connected():
|
def is_connected():
|
||||||
try:
|
try:
|
||||||
socket.create_connection(("api.pwnagotchi.ai", 443), timeout=30)
|
# check DNS
|
||||||
return True
|
host = socket.gethostbyname('api.pwnagotchi.ai')
|
||||||
|
if host:
|
||||||
|
# check connectivity itself
|
||||||
|
socket.create_connection((host, 443), timeout=30)
|
||||||
|
return True
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
return False
|
return False
|
||||||
|
@ -119,12 +119,14 @@ class View(object):
|
|||||||
|
|
||||||
def _refresh_handler(self):
|
def _refresh_handler(self):
|
||||||
delay = 1.0 / self._config['ui']['fps']
|
delay = 1.0 / self._config['ui']['fps']
|
||||||
# logging.info("view refresh handler started with period of %.2fs" % delay)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
name = self._state.get('name')
|
try:
|
||||||
self.set('name', name.rstrip('█').strip() if '█' in name else (name + ' █'))
|
name = self._state.get('name')
|
||||||
self.update()
|
self.set('name', name.rstrip('█').strip() if '█' in name else (name + ' █'))
|
||||||
|
self.update()
|
||||||
|
except Exception as e:
|
||||||
|
logging.warning("non fatal error while updating view: %s" % e)
|
||||||
|
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
|
|
||||||
def set(self, key, value):
|
def set(self, key, value):
|
||||||
@ -360,14 +362,15 @@ class View(object):
|
|||||||
if self._frozen:
|
if self._frozen:
|
||||||
return
|
return
|
||||||
|
|
||||||
changes = self._state.changes(ignore=self._ignore_changes)
|
state = self._state
|
||||||
|
changes = state.changes(ignore=self._ignore_changes)
|
||||||
if force or len(changes):
|
if force or len(changes):
|
||||||
self._canvas = Image.new('1', (self._width, self._height), WHITE)
|
self._canvas = Image.new('1', (self._width, self._height), WHITE)
|
||||||
drawer = ImageDraw.Draw(self._canvas)
|
drawer = ImageDraw.Draw(self._canvas)
|
||||||
|
|
||||||
plugins.on('ui_update', self)
|
plugins.on('ui_update', self)
|
||||||
|
|
||||||
for key, lv in self._state.items():
|
for key, lv in state.items():
|
||||||
lv.draw(self._canvas, drawer)
|
lv.draw(self._canvas, drawer)
|
||||||
|
|
||||||
web.update_frame(self._canvas)
|
web.update_frame(self._canvas)
|
||||||
|
@ -3,6 +3,7 @@ import os
|
|||||||
import base64
|
import base64
|
||||||
import _thread
|
import _thread
|
||||||
import secrets
|
import secrets
|
||||||
|
import json
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
# https://stackoverflow.com/questions/14888799/disable-console-messages-in-flask-server
|
# https://stackoverflow.com/questions/14888799/disable-console-messages-in-flask-server
|
||||||
@ -61,9 +62,11 @@ class Handler:
|
|||||||
@wraps(f)
|
@wraps(f)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
auth = request.authorization
|
auth = request.authorization
|
||||||
if not auth or not auth.username or not auth.password or not self._check_creds(auth.username, auth.password):
|
if not auth or not auth.username or not auth.password or not self._check_creds(auth.username,
|
||||||
|
auth.password):
|
||||||
return Response('Unauthorized', 401, {'WWW-Authenticate': 'Basic realm="Unauthorized"'})
|
return Response('Unauthorized', 401, {'WWW-Authenticate': 'Basic realm="Unauthorized"'})
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
def index(self):
|
def index(self):
|
||||||
@ -82,6 +85,9 @@ class Handler:
|
|||||||
error = None
|
error = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if not grid.is_connected():
|
||||||
|
raise Exception('not connected')
|
||||||
|
|
||||||
inbox = grid.inbox(page, with_pager=True)
|
inbox = grid.inbox(page, with_pager=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.exception('error while reading pwnmail inbox')
|
logging.exception('error while reading pwnmail inbox')
|
||||||
@ -106,7 +112,7 @@ class Handler:
|
|||||||
return render_template('profile.html',
|
return render_template('profile.html',
|
||||||
name=pwnagotchi.name(),
|
name=pwnagotchi.name(),
|
||||||
fingerprint=self._agent.fingerprint(),
|
fingerprint=self._agent.fingerprint(),
|
||||||
data=data,
|
data=json.dumps(data, indent=2),
|
||||||
error=error)
|
error=error)
|
||||||
|
|
||||||
def inbox_peers(self):
|
def inbox_peers(self):
|
||||||
@ -129,6 +135,9 @@ class Handler:
|
|||||||
error = None
|
error = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if not grid.is_connected():
|
||||||
|
raise Exception('not connected')
|
||||||
|
|
||||||
message = grid.inbox_message(id)
|
message = grid.inbox_message(id)
|
||||||
if message['data']:
|
if message['data']:
|
||||||
message['data'] = base64.b64decode(message['data']).decode("utf-8")
|
message['data'] = base64.b64decode(message['data']).decode("utf-8")
|
||||||
@ -151,6 +160,9 @@ class Handler:
|
|||||||
error = None
|
error = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if not grid.is_connected():
|
||||||
|
raise Exception('not connected')
|
||||||
|
|
||||||
grid.send_message(to, message)
|
grid.send_message(to, message)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error = str(e)
|
error = str(e)
|
||||||
@ -158,6 +170,9 @@ class Handler:
|
|||||||
return jsonify({"error": error})
|
return jsonify({"error": error})
|
||||||
|
|
||||||
def mark_message(self, id, mark):
|
def mark_message(self, id, mark):
|
||||||
|
if not grid.is_connected():
|
||||||
|
abort(200)
|
||||||
|
|
||||||
logging.info("marking message %d as %s" % (int(id), mark))
|
logging.info("marking message %d as %s" % (int(id), mark))
|
||||||
grid.mark_message(id, mark)
|
grid.mark_message(id, mark)
|
||||||
return redirect("/inbox")
|
return redirect("/inbox")
|
||||||
|
@ -35,6 +35,7 @@ class Server:
|
|||||||
static_url_path='',
|
static_url_path='',
|
||||||
static_folder=os.path.join(web_path, 'static'),
|
static_folder=os.path.join(web_path, 'static'),
|
||||||
template_folder=os.path.join(web_path, 'templates'))
|
template_folder=os.path.join(web_path, 'templates'))
|
||||||
|
|
||||||
app.secret_key = secrets.token_urlsafe(256)
|
app.secret_key = secrets.token_urlsafe(256)
|
||||||
|
|
||||||
if self._origin:
|
if self._origin:
|
||||||
|
@ -1,22 +1,7 @@
|
|||||||
form {
|
.ui-image {
|
||||||
margin-block-end: 0;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.content {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
height: calc(var(--vh, 1vh) * 100);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* make sure image is displayed without any blur
|
|
||||||
*/
|
|
||||||
.pixelated {
|
.pixelated {
|
||||||
image-rendering: optimizeSpeed; /* Legal fallback */
|
image-rendering: optimizeSpeed; /* Legal fallback */
|
||||||
image-rendering: -moz-crisp-edges; /* Firefox */
|
image-rendering: -moz-crisp-edges; /* Firefox */
|
||||||
@ -33,33 +18,6 @@ form {
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-image {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
max-width: 100vw;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: contain;
|
|
||||||
object-position: 50% 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons-wrapper {
|
|
||||||
flex-shrink: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
padding: 0 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 2em;
|
|
||||||
background: #f8b506;
|
|
||||||
margin: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.status {
|
div.status {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
window.onload = function() {
|
|
||||||
var image = document.getElementById("ui");
|
|
||||||
function updateImage() {
|
|
||||||
image.src = image.src.split("?")[0] + "?" + new Date().getTime();
|
|
||||||
}
|
|
||||||
setInterval(updateImage, 1000);
|
|
||||||
}
|
|
71
pwnagotchi/ui/web/templates/base.html
Normal file
71
pwnagotchi/ui/web/templates/base.html
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<title>
|
||||||
|
{% block title %}
|
||||||
|
{% endblock %}
|
||||||
|
</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/js/jquery.mobile/jquery.mobile-1.4.5.min.css"/>
|
||||||
|
<script type="text/javascript" src="/js/jquery-1.12.4.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/js/jquery.mobile/jquery.mobile-1.4.5.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/js/jquery.timeago.js"></script>
|
||||||
|
<script type="text/javascript" src="/js/jquery-qrcode-0.17.0.min.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/style.css"/>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$.mobile.ajaxEnabled = false;
|
||||||
|
|
||||||
|
jQuery(document).ready(function() {
|
||||||
|
jQuery("time.timeago").timeago();
|
||||||
|
});
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
{% endblock %}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div data-role="page">
|
||||||
|
|
||||||
|
{% if error %}
|
||||||
|
<div id="error" class="error ui-content" data-role="popup" data-overlay-theme="a" data-theme="b">
|
||||||
|
<p>{{ error }}</p>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
$(function(){
|
||||||
|
$("#error").popup("open");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% set navigation = [
|
||||||
|
( '/', 'home', 'eye', 'Home' ),
|
||||||
|
( '/inbox', 'inbox', 'bars', 'Inbox' ),
|
||||||
|
( '/inbox/new', 'new', 'mail', 'New' ),
|
||||||
|
( '/inbox/profile', 'profile', 'info', 'Profile' ),
|
||||||
|
( '/inbox/peers', 'peers', 'user', 'Peers' ),
|
||||||
|
] %}
|
||||||
|
{% set active_page = active_page|default('inbox') %}
|
||||||
|
|
||||||
|
<div data-role="footer">
|
||||||
|
<div data-role="navbar" data-iconpos="left">
|
||||||
|
<ul>
|
||||||
|
{% for href, id, icon, caption in navigation %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ href }}" id="{{ id }}" data-icon="{{ icon }}" class="{{ 'ui-btn-active' if active_page == id }}">{{ caption }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,81 +1,38 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html>
|
{% set active_page = "inbox" %}
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
|
|
||||||
<title>{{ name }} Inbox</title>
|
{% block title %}
|
||||||
|
{{ name }} Inbox
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
<link rel="stylesheet" href="/js/jquery.mobile/jquery.mobile-1.4.5.min.css"/>
|
{% block content %}
|
||||||
<script type="text/javascript" src="/js/jquery-1.12.4.min.js"></script>
|
<ul class="inbox" data-role="listview" data-filter="true" data-filter-placeholder="Search inbox..." data-inset="true">
|
||||||
<script type="text/javascript" src="/js/jquery.mobile/jquery.mobile-1.4.5.min.js"></script>
|
{% for message in inbox.messages %}
|
||||||
<script type="text/javascript" src="/js/jquery.timeago.js"></script>
|
<li class="message">
|
||||||
|
<a href="/inbox/{{ message.id }}" class="{{ 'unread' if not message.seen_at else 'read' }}">
|
||||||
|
<h2>{{ message.sender_name }}@{{ message.sender }}</h2>
|
||||||
|
<p>
|
||||||
|
Received
|
||||||
|
<time class="timeago" datetime="{{ message.created_at }}">{{ message.created_at }}</time>
|
||||||
|
{% if message.seen_at %}, seen
|
||||||
|
<time class="timeago" datetime="{{ message.seen_at }}">{{ message.seen_at }}</time>
|
||||||
|
{% endif %}.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/style.css"/>
|
{% if inbox.pages > 1 %}
|
||||||
|
<div data-role="navbar">
|
||||||
<script type="text/javascript">
|
<ul>
|
||||||
$.mobile.ajaxEnabled = false;
|
{% if page > 1 %}
|
||||||
|
<li><a href="/inbox?p={{ page - 1 }}" class="ui-btn">Prev</a></li>
|
||||||
jQuery(document).ready(function() {
|
{% endif %}
|
||||||
jQuery("time.timeago").timeago();
|
{% if page < inbox.pages %}
|
||||||
});
|
<li><a href="/inbox?p={{ page + 1 }}" class="ui-btn">Next</a></li>
|
||||||
</script>
|
{% endif %}
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div data-role="page">
|
|
||||||
|
|
||||||
{% if error %}
|
|
||||||
<div class="error">{{ error }}</div>
|
|
||||||
{% else %}
|
|
||||||
{% if inbox.records == 0 %}
|
|
||||||
<small>Inbox is empty.</small>
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
<div data-role="footer">
|
|
||||||
<div data-role="navbar">
|
|
||||||
<ul>
|
|
||||||
<li><a href="/inbox" id="email" class="ui-btn-active" data-icon="bars">Inbox</a></li>
|
|
||||||
<li><a href="/inbox/new" id="new" data-icon="mail">New</a></li>
|
|
||||||
<li><a href="/inbox/profile" id="profile" data-icon="info">Profile</a></li>
|
|
||||||
<li><a href="/inbox/peers" id="peers" data-icon="user">Peers</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class="inbox" data-role="listview" data-filter="true" data-filter-placeholder="Search inbox..." data-inset="true">
|
|
||||||
{% for message in inbox.messages %}
|
|
||||||
<li class="message">
|
|
||||||
<a href="/inbox/{{ message.id }}" class="{{ 'unread' if not message.seen_at else 'read' }}">
|
|
||||||
<h2>{{ message.sender_name }}@{{ message.sender }}</h2>
|
|
||||||
<p>
|
|
||||||
Received
|
|
||||||
<time class="timeago" datetime="{{ message.created_at }}">{{ message.created_at }}</time>
|
|
||||||
{% if message.seen_at %}, seen
|
|
||||||
<time class="timeago" datetime="{{ message.seen_at }}">{{ message.seen_at }}</time>
|
|
||||||
{% endif %}.
|
|
||||||
</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if inbox.pages > 1 %}
|
|
||||||
<div data-role="navbar">
|
|
||||||
<ul>
|
|
||||||
{% if page > 1 %}
|
|
||||||
<li><a href="/inbox?p={{ page - 1 }}" class="ui-btn">Prev</a></li>
|
|
||||||
{% endif %}
|
|
||||||
{% if page < inbox.pages %}
|
|
||||||
<li><a href="/inbox?p={{ page + 1 }}" class="ui-btn">Next</a></li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</body>
|
{% endblock %}
|
||||||
</html>
|
|
||||||
|
@ -1,35 +1,39 @@
|
|||||||
<html>
|
{% extends "base.html" %}
|
||||||
<head>
|
{% set active_page = "home" %}
|
||||||
<title>{{ title }}</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/style.css"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="content">
|
|
||||||
<div class="image-wrapper">
|
|
||||||
<img class="ui-image pixelated" src="/ui" id="ui"/>
|
|
||||||
</div>
|
|
||||||
<div class="buttons-wrapper">
|
|
||||||
<form class="action" method="POST" action="/shutdown"
|
|
||||||
onsubmit="return confirm('This will halt the unit, continue?');">
|
|
||||||
<input type="submit" class="button" value="Shutdown"/>
|
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form class="action" method="POST" action="/restart"
|
{% block title %}
|
||||||
onsubmit="return confirm('This will restart the service in {{ other_mode }} mode, continue?');">
|
{{ title }}
|
||||||
<input type="submit" class="button" value="Restart in {{ other_mode }} mode"/>
|
{% endblock %}
|
||||||
<input type="hidden" name="mode" value="{{ other_mode }}"/>
|
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form class="action" method="GET" action="/inbox">
|
{% block script %}
|
||||||
<input type="submit" class="button" value="PwnMail"/>
|
window.onload = function() {
|
||||||
</form>
|
var image = document.getElementById("ui");
|
||||||
</div>
|
function updateImage() {
|
||||||
|
image.src = image.src.split("?")[0] + "?" + new Date().getTime();
|
||||||
|
}
|
||||||
|
setInterval(updateImage, 1000);
|
||||||
|
}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<img class="ui-image pixelated" src="/ui" id="ui"/>
|
||||||
|
<div data-role="navbar">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<form class="action" method="post" action="/shutdown"
|
||||||
|
onsubmit="return confirm('this will halt the unit, continue?');">
|
||||||
|
<input type="submit" class="button ui-btn ui-corner-all" value="shutdown"/>
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<form class="action" method="post" action="/restart"
|
||||||
|
onsubmit="return confirm('this will restart the service in {{ other_mode }} mode, continue?');">
|
||||||
|
<input type="submit" class="button ui-btn ui-corner-all" value="restart in {{ other_mode }} mode"/>
|
||||||
|
<input type="hidden" name="mode" value="{{ other_mode }}"/>
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
{% endblock %}
|
||||||
<script type="text/javascript" src="/js/refresh.js"></script>
|
|
||||||
<script type="text/javascript" src="/js/viewportHeight.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
@ -1,70 +1,37 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html>
|
{% set active_page = "" %}
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
|
|
||||||
<title>Message from {{ message.sender_name }}</title>
|
{% block title %}
|
||||||
|
Message from {{ message.sender_name }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
<link rel="stylesheet" href="/js/jquery.mobile/jquery.mobile-1.4.5.min.css"/>
|
{% block script %}
|
||||||
<script type="text/javascript" src="/js/jquery-1.12.4.min.js"></script>
|
jQuery(document).ready(function() {
|
||||||
<script type="text/javascript" src="/js/jquery.mobile/jquery.mobile-1.4.5.min.js"></script>
|
// mark the message as read
|
||||||
<script type="text/javascript" src="/js/jquery.timeago.js"></script>
|
jQuery.get("/inbox/{{ message.id }}/seen", function(res){ console.log(res); });
|
||||||
|
});
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/style.css"/>
|
{% block content %}
|
||||||
|
<p class="messagebody">
|
||||||
<script type="text/javascript">
|
|
||||||
$.mobile.ajaxEnabled = false;
|
|
||||||
|
|
||||||
jQuery(document).ready(function() {
|
|
||||||
jQuery("time.timeago").timeago();
|
|
||||||
// mark the message as read
|
|
||||||
jQuery.get("/inbox/{{ message.id }}/seen", function(res){
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div data-role="page">
|
|
||||||
|
|
||||||
{% if error %}
|
|
||||||
<div class="error">{{ error }}</div>
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
<div data-role="footer">
|
|
||||||
<div data-role="navbar">
|
|
||||||
<ul>
|
|
||||||
<li><a href="/inbox" id="email" data-icon="back">Back</a></li>
|
|
||||||
<li><a href="/inbox/new?to={{ message.sender }}" id="reply" data-icon="edit">Reply</a></li>
|
|
||||||
<li><a href="/inbox/{{ message.id }}/deleted" id="delete" data-icon="delete"
|
|
||||||
onclick="return confirm('Are you sure?')">Delete</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="messagebody">
|
|
||||||
<span style="color: #888">
|
<span style="color: #888">
|
||||||
Message from {{ message.sender_name }}@{{ message.sender }}, received
|
Message from {{ message.sender_name }}@{{ message.sender }}, sent
|
||||||
<time class="timeago" datetime="{{ message.created_at }}">{{ message.created_at }}</time>
|
<time class="timeago" datetime="{{ message.created_at }}">{{ message.created_at }}</time>
|
||||||
{% if message.seen_at %}, seen
|
{% if message.seen_at %}, seen
|
||||||
<time class="timeago" datetime="{{ message.seen_at }}">{{ message.seen_at }}</time>{% endif %}.</span>
|
<time class="timeago" datetime="{{ message.seen_at }}">{{ message.seen_at }}</time>{% endif %}.</span>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
{% if message.data %}
|
|
||||||
<span style="white-space: pre-line">{{ message.data }}</span>
|
|
||||||
{% else %}
|
|
||||||
<small>This message is empty.</small>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
{% if message.data %}
|
||||||
|
<span style="white-space: pre-line">{{ message.data }}</span>
|
||||||
|
{% else %}
|
||||||
|
<small>This message is empty.</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
<br/>
|
||||||
|
<br/>
|
||||||
</body>
|
<a href="/inbox/new?to={{ message.sender }}" class="ui-btn ui-icon-comment ui-btn-icon-left ui-shadow-icon">Reply</a>
|
||||||
</html>
|
<a href="/inbox/{{ message.id }}/deleted" class="ui-btn ui-icon-delete ui-btn-icon-left ui-shadow-icon" onclick="return confirm('Are you sure?')">Delete</a>
|
||||||
|
</p>
|
||||||
|
{% endblock %}
|
||||||
|
@ -1,81 +1,55 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html>
|
{% set active_page = "new" %}
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
|
|
||||||
{% if to %}
|
{% block title %}
|
||||||
<title>Reply to {{ to }}</title>
|
{% if to %}
|
||||||
{% else %}
|
title>Reply to {{ to }}
|
||||||
<title>New Message</title>
|
{% else %}
|
||||||
{% endif %}
|
New Message
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
<link rel="stylesheet" href="/js/jquery.mobile/jquery.mobile-1.4.5.min.css"/>
|
{% block script %}
|
||||||
<script type="text/javascript" src="/js/jquery-1.12.4.min.js"></script>
|
$(function(){
|
||||||
<script type="text/javascript" src="/js/jquery.mobile/jquery.mobile-1.4.5.min.js"></script>
|
$("#message_form").submit(function(e) {
|
||||||
<script type="text/javascript" src="/js/jquery.timeago.js"></script>
|
e.preventDefault();
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/style.css"/>
|
var form = $(this);
|
||||||
|
var url = form.attr('action');
|
||||||
|
|
||||||
<script type="text/javascript">
|
$.ajax({
|
||||||
$.mobile.ajaxEnabled = false;
|
type: "POST",
|
||||||
|
url: url,
|
||||||
|
data: form.serialize(),
|
||||||
|
success: function(data) {
|
||||||
|
if( data.error ) {
|
||||||
|
if( data.error.indexOf('404') != -1 )
|
||||||
|
alert('Fingerprint not found.');
|
||||||
|
else if( data.error.indexOf('aborted') != -1 )
|
||||||
|
alert('Empty or invalid message.');
|
||||||
|
else
|
||||||
|
alert(data.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$(function(){
|
alert("Message sent!");
|
||||||
$("#message_form").submit(function(e) {
|
document.location.href = "/inbox";
|
||||||
e.preventDefault();
|
}
|
||||||
|
|
||||||
var form = $(this);
|
|
||||||
var url = form.attr('action');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: url,
|
|
||||||
data: form.serialize(),
|
|
||||||
success: function(data) {
|
|
||||||
if( data.error ) {
|
|
||||||
if( data.error.indexOf('404') != -1 )
|
|
||||||
alert('Fingerprint not found.');
|
|
||||||
else if( data.error.indexOf('aborted') != -1 )
|
|
||||||
alert('Empty or invalid message.');
|
|
||||||
else
|
|
||||||
alert(data.error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
alert("Message sent!");
|
|
||||||
document.location.href = "/inbox";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
</script>
|
{% block content %}
|
||||||
|
<div style="padding: 1em">
|
||||||
</head>
|
<form id="message_form" method="POST" action="/inbox/send">
|
||||||
<body>
|
<label for="to">To:</label>
|
||||||
<div data-role="page">
|
<input type="text" name="to" id="to" value="{{ to }}">
|
||||||
|
|
||||||
<div data-role="footer">
|
|
||||||
<div data-role="navbar">
|
|
||||||
<ul>
|
|
||||||
<li><a href="/inbox" id="email" data-icon="back">Back</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="padding: 1em">
|
|
||||||
<form id="message_form" method="POST" action="/inbox/send">
|
|
||||||
<label for="to">To:</label>
|
|
||||||
<input type="text" name="to" id="to" value="{{ to }}">
|
|
||||||
|
|
||||||
<label for="message">Message:</label>
|
|
||||||
<textarea cols="40" rows="8" name="message" id="message"></textarea>
|
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
|
||||||
<input type="submit" class="button" value="Send"/>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<label for="message">Message:</label>
|
||||||
|
<textarea cols="40" rows="8" name="message" id="message"></textarea>
|
||||||
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||||
|
<input type="submit" class="button" value="Send"/>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
{% endblock %}
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
@ -1,49 +1,21 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html>
|
{% set active_page = "peers" %}
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
|
|
||||||
<title>{{ name }} friends</title>
|
{% block title %}
|
||||||
|
{{ name }} Friends
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
<link rel="stylesheet" href="/js/jquery.mobile/jquery.mobile-1.4.5.min.css"/>
|
{% block content %}
|
||||||
<script type="text/javascript" src="/js/jquery-1.12.4.min.js"></script>
|
<ul class="peers" data-role="listview" data-filter="true" data-filter-placeholder="Search peers..." data-inset="true">
|
||||||
<script type="text/javascript" src="/js/jquery.mobile/jquery.mobile-1.4.5.min.js"></script>
|
{% for peer in peers %}
|
||||||
<script type="text/javascript" src="/js/jquery.timeago.js"></script>
|
<li class="peer">
|
||||||
<script type="text/javascript" src="/js/jquery-qrcode-0.17.0.min.js"></script>
|
<a href="/inbox/new?to={{ peer.fingerprint }}">
|
||||||
|
<h2>{{ peer.advertisement.face }} {{ peer.advertisement.name }}@{{ peer.fingerprint }}</h2>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/style.css"/>
|
<p>
|
||||||
|
Pwned {{ peer.advertisement.pwnd_tot }} networks, {{ peer.encounters }} encounters.
|
||||||
<script type="text/javascript">
|
</p>
|
||||||
$.mobile.ajaxEnabled = false;
|
</a>
|
||||||
</script>
|
</li>
|
||||||
|
{% endfor %}
|
||||||
</head>
|
</ul>
|
||||||
<body>
|
{% endblock %}
|
||||||
<div data-role="page">
|
|
||||||
|
|
||||||
<div data-role="footer">
|
|
||||||
<div data-role="navbar">
|
|
||||||
<ul>
|
|
||||||
<li><a href="/inbox" id="email" data-icon="back">Back</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class="peers" data-role="listview" data-filter="true" data-filter-placeholder="Search peers..." data-inset="true">
|
|
||||||
{% for peer in peers %}
|
|
||||||
<li class="peer">
|
|
||||||
<a href="/inbox/new?to={{ peer.fingerprint }}">
|
|
||||||
<h2>{{ peer.advertisement.face }} {{ peer.advertisement.name }}@{{ peer.fingerprint }}</h2>
|
|
||||||
<p>
|
|
||||||
Pwned {{ peer.advertisement.pwnd_tot }} networks, {{ peer.encounters }} encounters.
|
|
||||||
</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
@ -1,60 +1,35 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "base.html" %}
|
||||||
<html>
|
{% set active_page = "profile" %}
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
|
|
||||||
<title>Profile</title>
|
{% block title %}
|
||||||
|
Profile
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
<link rel="stylesheet" href="/js/jquery.mobile/jquery.mobile-1.4.5.min.css"/>
|
{% block script %}
|
||||||
<script type="text/javascript" src="/js/jquery-1.12.4.min.js"></script>
|
$(function(){
|
||||||
<script type="text/javascript" src="/js/jquery.mobile/jquery.mobile-1.4.5.min.js"></script>
|
$('#qrcode').qrcode({
|
||||||
<script type="text/javascript" src="/js/jquery.timeago.js"></script>
|
render: 'div',
|
||||||
<script type="text/javascript" src="/js/jquery-qrcode-0.17.0.min.js"></script>
|
mode: 0,
|
||||||
|
size: 400,
|
||||||
|
fontname: 'sans',
|
||||||
|
fontcolor: '#000'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/style.css"/>
|
{% block content %}
|
||||||
|
<div style="padding: 1em">
|
||||||
|
<label for="name">Name</label>
|
||||||
|
<h4 id="name">{{ name }}</h4>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<label for="fingerprint">Fingerprint</label>
|
||||||
$.mobile.ajaxEnabled = false;
|
<h4 id="fingerprint">
|
||||||
$(function(){
|
<a href="https://pwnagotchi.ai/pwnfile/#{{ fingerprint }}" target="_blank">{{ fingerprint }}</a>
|
||||||
$('#qrcode').qrcode({
|
</h4>
|
||||||
render: 'div',
|
<div id="qrcode"></div>
|
||||||
mode: 0,
|
|
||||||
size: 400,
|
|
||||||
fontname: 'sans',
|
|
||||||
fontcolor: '#000'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div data-role="page">
|
|
||||||
|
|
||||||
<div data-role="footer">
|
|
||||||
<div data-role="navbar">
|
|
||||||
<ul>
|
|
||||||
<li><a href="/inbox" id="email" data-icon="back">Back</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="padding: 1em">
|
|
||||||
<label for="name">Name</label>
|
|
||||||
<h4 id="name">{{ name }}</h4>
|
|
||||||
|
|
||||||
<label for="fingerprint">Fingerprint</label>
|
|
||||||
<h4 id="fingerprint">
|
|
||||||
<a href="https://pwnagotchi.ai/pwnfile/#{{ fingerprint }}" target="_blank">{{ fingerprint }}</a>
|
|
||||||
</h4>
|
|
||||||
<div id="qrcode"></div>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<label for="data">Data</label>
|
|
||||||
<pre><code id="data">{{ data }}</code></pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<label for="data">Data</label>
|
||||||
|
<pre><code id="data">{{ data }}</code></pre>
|
||||||
</div>
|
</div>
|
||||||
|
{% endblock %}
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user