Initial project setup.

This commit is contained in:
Morgan McMillian 2020-07-13 17:59:16 -07:00
commit b56e219bcf
18 changed files with 855 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
build/
pantalaimon-arm64
pantalaimon-armhf

88
CMakeLists.txt Normal file
View file

@ -0,0 +1,88 @@
cmake_minimum_required(VERSION 3.0.0)
project(pantalaimon C CXX)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(Qt5Core)
find_package(Qt5Qml)
find_package(Qt5Quick)
# Automatically create moc files
set(CMAKE_AUTOMOC ON)
# Components PATH
execute_process(
COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
OUTPUT_VARIABLE ARCH_TRIPLET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(QT_IMPORTS_DIR "lib/${ARCH_TRIPLET}")
set(PROJECT_NAME "pantalaimon")
set(FULL_PROJECT_NAME "pantalaimon.thrrgilag")
set(CMAKE_INSTALL_PREFIX /)
set(DATA_DIR /)
set(DESKTOP_FILE_NAME ${PROJECT_NAME}.desktop)
# This command figures out the target architecture for use in the manifest file
# Either via the environment variable ARCH (set by Clickable) or dpkg
if(DEFINED ENV{ARCH})
set(CLICK_ARCH "$ENV{ARCH}")
else()
execute_process(
COMMAND dpkg-architecture -qDEB_HOST_ARCH
OUTPUT_VARIABLE CLICK_ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/manifest.json)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json DESTINATION ${CMAKE_INSTALL_PREFIX})
install(FILES ${PROJECT_NAME}.apparmor DESTINATION ${DATA_DIR})
install(DIRECTORY assets DESTINATION ${DATA_DIR})
install(DIRECTORY src DESTINATION ${DATA_DIR})
install(DIRECTORY qml DESTINATION ${DATA_DIR})
# example config file for local testing
# install(FILES example.conf DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME pantalaimon.conf)
# Translations
file(GLOB_RECURSE I18N_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po qml/*.qml qml/*.js)
list(APPEND I18N_SRC_FILES ${DESKTOP_FILE_NAME}.in.h)
find_program(INTLTOOL_MERGE intltool-merge)
if(NOT INTLTOOL_MERGE)
message(FATAL_ERROR "Could not find intltool-merge, please install the intltool package")
endif()
find_program(INTLTOOL_EXTRACT intltool-extract)
if(NOT INTLTOOL_EXTRACT)
message(FATAL_ERROR "Could not find intltool-extract, please install the intltool package")
endif()
add_custom_target(${DESKTOP_FILE_NAME} ALL
COMMENT "Merging translations into ${DESKTOP_FILE_NAME}..."
COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${CMAKE_SOURCE_DIR}/${DESKTOP_FILE_NAME}.in ${DESKTOP_FILE_NAME}
COMMAND sed -i 's/${PROJECT_NAME}-//g' ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE_NAME}
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DESKTOP_FILE_NAME} DESTINATION ${DATA_DIR})
# TODO: figure out how to cross compile this
install(PROGRAMS ${PROJECT_NAME}-${CLICK_ARCH} DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME ${PROJECT_NAME})
add_subdirectory(po)
# Make source files visible in qtcreator
file(GLOB_RECURSE PROJECT_SRC_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
qml/*.qml
qml/*.js
src/*
*.json
*.json.in
*.apparmor
*.desktop.in
)
add_custom_target(${PROJECT_NAME}_FILES ALL SOURCES ${PROJECT_SRC_FILES})

17
LICENSE Normal file
View file

@ -0,0 +1,17 @@
Apache Software License 2.0
Copyright (c) 2020, Morgan McMillian
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

26
README.md Normal file
View file

@ -0,0 +1,26 @@
# Pantalaimon
End-to-end encryption aware Matrix reverse proxy daemon for Ubuntu Touch.
## TODO
- [ ] Proper app icon
- [ ] Cross compile python+pantalaimon
- [ ] Fix image fetching
- [ ] Ability to verify, ingore, or blacklist devices
## Build
This project is not currently setup for cross building. A binary will need to
be compiled on a device for each target architecture.
## Known Issues
* Images (including avatars) are not fetched
* No user interaction to verify, ignore, or blacklist devices
## License
Copyright (C) 2020 Morgan McMillian
Licensed under the Apache Software License 2.0

24
assets/logo.svg Normal file
View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg style="enable-background:new" xmlns="http://www.w3.org/2000/svg" height="512" viewBox="0 0 512.40002 512" width="512.4" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="a" y2="494" gradientUnits="userSpaceOnUse" x2="256" gradientTransform="matrix(1 0 0 1.076 0 -19.36)" y1="18" x1="256">
<stop style="stop-color:#eaeaea" offset="0"/>
<stop style="stop-color:#f4f4f4" offset="1"/>
</linearGradient>
</defs>
<rect style="color:#000000;enable-background:accumulate;fill:url(#a)" height="512" width="512" y="0" x="0"/>
<path style="opacity:.1" d="m256 112c-79.5 0-144 64.5-144 144s64.5 144 144 144 144-64.5 144-144-64.5-144-144-144zm49.47 39.98c3.098 0.0797 6.222 0.9104 9.096 2.568 9.197 5.312 12.34 17.07 7.029 26.26-5.305 9.196-17.06 12.34-26.25 7.029-9.19-5.305-12.34-17.06-7.039-26.25 3.653-6.322 10.35-9.787 17.17-9.611zm-49.48 20.5c7.731 0 15.21 1.074 22.31 3.035 1.253 7.726 5.837 14.84 13.15 19.06 7.298 4.207 15.74 4.629 23.05 1.867 14.22 13.98 23.47 32.99 24.81 54.17l-27.39 0.4043c-2.5-28.7-26.6-51.2-55.9-51.2-8.451 0-16.47 1.88-23.65 5.225l-13.4-23.9c11.16-5.522 23.72-8.645 37.01-8.645zm-46.33 14.03 14.06 23.54c-14.44 10.16-23.88 26.95-23.88 45.95s9.437 35.78 23.88 45.94l-14.06 23.55c-16.83-11.24-29.34-28.43-34.54-48.55 6.069-4.952 9.953-12.49 9.953-20.94 0-8.451-3.884-15.99-9.953-20.94 5.201-20.12 17.72-37.3 34.54-48.55zm-51.58 50.26c10.62 0 19.22 8.608 19.22 19.23s-8.605 19.22-19.22 19.22-19.23-8.605-19.23-19.22 8.607-19.23 19.23-19.23zm153.8 24.21 27.4 0.4023c-1.348 21.18-10.6 40.19-24.81 54.17-7.31-2.762-15.75-2.347-23.05 1.867-7.309 4.227-11.89 11.34-13.15 19.06-7.104 1.967-14.58 3.041-22.31 3.041-13.29 0-25.86-3.124-37.01-8.652l13.36-23.94c7.186 3.344 15.2 5.225 23.65 5.225 29.34 0 53.41-22.49 55.93-51.18zm-7.482 60.6c6.816-0.1758 13.51 3.289 17.16 9.607 5.311 9.197 2.16 20.95-7.035 26.25-9.196 5.311-20.95 2.159-26.25-7.037-5.312-9.191-2.159-20.94 7.037-26.25 2.872-1.658 5.994-2.49 9.092-2.57z"/>
<g transform="translate(0,18)">
<path style="opacity:.3;color:#000000;enable-background:accumulate;fill:#fff" d="m256 256l-147.8 256h403.8v-256h-122.7-133.3z" transform="translate(0,-18)"/>
<path style="opacity:.15;color:#000000;enable-background:accumulate;fill:#fff" d="m0 0v512h108.2l76.4-132.3 71.4-123.7-68.9-120-0.2 0.3-78.7-136.3h-108.2z" transform="translate(0,-18)"/>
</g>
<path d="m-208.3 605.6c-7.842 0-14.55 5.029-17.32 12.19-0.0612-0.00067-0.1208 0-0.1823 0-7.088 0-12.83 6.002-12.83 13.41 0 7.404 5.746 13.41 12.83 13.41h17.5 16.33c5.155 0 9.333-4.365 9.333-9.75 0-4.543-2.974-8.363-7-9.445 0.001-0.1029 0-0.2015 0-0.3047 0-10.77-8.357-19.5-18.67-19.5z" style="stroke-width:4;color:#000000;stroke:#ccc;enable-background:accumulate;display:none;fill:#fff"/>
<path style="stroke-width:4;color:#000000;stroke:#ccc;enable-background:accumulate;display:none;fill:none" d="m288.9 828.1c-6.349 0-11.78 4.072-14.02 9.867-0.0496-0.00055-0.0978 0-0.1476 0-5.738 0-10.39 4.86-10.39 10.85 0 5.995 4.652 10.85 10.39 10.85h14.17 13.22c4.173 0 7.557-3.534 7.557-7.894 0-3.678-2.408-6.771-5.667-7.647 0.001-0.0833 0-0.1632 0-0.2467 0-8.719-6.766-15.79-15.11-15.79z"/>
<g style="display:none" transform="translate(0 -558.4)">
<path d="m166.1 576.4h179.9c145.3 0 166.1 20.74 166.1 165.9v144.2c0 145.2-20.76 165.9-166.1 165.9h-179.9c-145.3 0-166.1-20-166.1-165.5v-144.2c0-145.2 20.76-165.9 166.1-165.9z" style="stroke:#00f;fill:#00f;display:inline;fill-opacity:.08118"/>
<circle style="stroke-width:.8333;fill-opacity:.08118;color:#000000;stroke:#00f;enable-background:accumulate;display:inline;fill:#00f" cx="256" transform="matrix(1.2 0 0 1.2 -51.2 528.8)" cy="238" r="120"/>
<rect style="stroke-linejoin:round;fill-opacity:.08118;color:#000000;stroke:#00f;stroke-linecap:round;enable-background:accumulate;display:inline;fill:#00f" height="272" width="272" y="678.4" x="120"/>
<rect style="stroke-linejoin:round;fill-opacity:.08118;color:#000000;stroke:#00f;stroke-linecap:round;enable-background:accumulate;display:inline;fill:#00f" height="240" width="304" y="694.4" x="104"/>
<rect style="stroke-linejoin:round;fill-opacity:.08118;color:#000000;stroke:#00f;stroke-linecap:round;enable-background:accumulate;display:inline;fill:#00f" height="304" width="240" y="662.4" x="136"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

5
clickable.json Normal file
View file

@ -0,0 +1,5 @@
{
"clickable_minimum_required": "6.12.2",
"builder": "cmake",
"kill": "qmlscene"
}

94
dev-build.sh Executable file
View file

@ -0,0 +1,94 @@
#!/bin/bash
PROJECT_DIR=~/pantalaimon-build
TMP_DIR="${PROJECT_DIR}/tmp"
VIRTENV_DIR="${PROJECT_DIR}/virtenv"
OLM_DIR="${PROJECT_DIR}/olm"
PANTALAIMON_DIR="${PROJECT_DIR}/pantalaimon"
PYTHON_VERSION_MINOR="3.7"
PYTHON_VERSION_PATCH="7"
PYTHON_VERSION="${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}"
PYTHON_DIR="${PROJECT_DIR}/python"
PYTHON_SRC_DIR="${TMP_DIR}/Python-${PYTHON_VERSION}"
PYTHON="${PYTHON_DIR}/bin/python${PYTHON_VERSION_MINOR}"
mkdir -p "${PROJECT_DIR}"
mkdir -p "${TMP_DIR}"
PACKAGES="make cmake build-essential zlibc python3-venv libffi-dev ppa-purge libssl-dev libsqlite3-dev"
PANTALAIMON_PATCH_CONTENT="
diff --git a/pantalaimon/main.py b/pantalaimon/main.py
index 896d29e..3e0fee8 100644
--- a/pantalaimon/main.py
+++ b/pantalaimon/main.py
@@ -32,6 +32,7 @@ from pantalaimon.log import logger
from pantalaimon.thread_messages import DaemonResponse
from pantalaimon.ui import UI_ENABLED
+keyring.core.set_keyring(keyring.core.load_keyring('keyring.backends.SecretService.Keyring'))
def create_dirs(data_dir, conf_dir):
try:
"
echo "Remounting RootFS writable..."
sudo mount -o remount,rw /
echo "Installing dependencies..."
sudo apt update
sudo apt install -y ${PACKAGES}
if [ ! -e "${OLM_DIR}/usr/local/lib/libolm.so" ]; then
cd "${TMP_DIR}"
echo "Downloading Olm..."
wget -qO- "https://gitlab.matrix.org/matrix-org/olm/-/archive/master/olm-master.tar.gz" | tar -xz
echo "Building Olm..."
cd olm-master
cmake . -Bbuild
cmake --build build
echo "Installing Olm..."
cd build
make install DESTDIR="${OLM_DIR}"
else
echo "Olm found. Skipping Olm Install..."
fi
if [ ! -e "${PYTHON}" ]; then
echo "Downloading Python..."
cd "${TMP_DIR}"
wget -qO- "https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz" | tar -xz
echo "Installing Python..."
cd "${PYTHON_SRC_DIR}"
./configure --prefix="${PYTHON_DIR}" --enable-shared
make
make install
else
echo "Python found. Skipping Python Install..."
fi
LD_LIBRARY_PATH=${PYTHON_DIR}/lib:${OLM_DIR}/usr/local/lib:${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH
echo "Installing PyInstaller..."
${PYTHON} -m pip install --upgrade pyinstaller
echo "Installing Pantalaimon..."
CFLAGS=-I"${OLM_DIR}/usr/local/include -I${OLM_DIR}/usr/local/include" LDFLAGS="-L${OLM_DIR}/usr/local/lib" ${PYTHON} -m pip install --upgrade pantalaimon
echo "Bundling Pantalaimon..."
cd ${PROJECT_DIR}
echo "${PANTALAIMON_PATCH_CONTENT}" > main.patch
patch ${PYTHON_DIR}/lib/python${PYTHON_VERSION_MINOR}/site-packages/pantalaimon/main.py main.patch
${PYTHON_DIR}/bin/pyinstaller --onefile ${PYTHON_DIR}/bin/pantalaimon
echo "Cleaning up, reverting changes to RootFS..."
sudo apt autoremove -y ${PACKAGES}
sudo apt clean

6
example.conf Normal file
View file

@ -0,0 +1,6 @@
[matrix.org]
Homeserver = https://matrix.org
ListenAddress = localhost
ListenPort = 8009
IgnoreVerification = True
UseKeyring = False

15
manifest.json.in Normal file
View file

@ -0,0 +1,15 @@
{
"name": "pantalaimon.thrrgilag",
"description": "End-to-end encryption aware Matrix reverse proxy daemon for Ubuntu Touch",
"architecture": "@CLICK_ARCH@",
"title": "Pantalaimon UT",
"hooks": {
"pantalaimon": {
"apparmor": "pantalaimon.apparmor",
"desktop": "pantalaimon.desktop"
}
},
"version": "0.1.0",
"maintainer": "Morgan McMillian <thrrgilag@dreamfall.space>",
"framework" : "ubuntu-sdk-16.04"
}

5
pantalaimon.apparmor Normal file
View file

@ -0,0 +1,5 @@
{
"template": "unconfined",
"policy_groups": ["networking"],
"policy_version": 16.04
}

7
pantalaimon.desktop.in Normal file
View file

@ -0,0 +1,7 @@
[Desktop Entry]
_Name=Pantalaimon UT
Exec=qmlscene %U qml/Main.qml
Icon=assets/logo.svg
Terminal=false
Type=Application
X-Ubuntu-Touch=true

34
po/CMakeLists.txt Normal file
View file

@ -0,0 +1,34 @@
include(FindGettext)
find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
set(DOMAIN ${FULL_PROJECT_NAME})
set(POT_FILE ${DOMAIN}.pot)
file(GLOB PO_FILES *.po)
# Creates the .pot file containing the translations template
add_custom_target(${POT_FILE} ALL
COMMENT "Generating translation template"
COMMAND ${INTLTOOL_EXTRACT} --update --type=gettext/ini
--srcdir=${CMAKE_SOURCE_DIR} ${DESKTOP_FILE_NAME}.in
COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} -o ${POT_FILE}
-D ${CMAKE_CURRENT_SOURCE_DIR}
-D ${CMAKE_CURRENT_BINARY_DIR}
--from-code=UTF-8
--c++ --qt --language=javascript --add-comments=TRANSLATORS
--keyword=tr --keyword=tr:1,2 --keyword=N_ --keyword=_
--package-name='${DOMAIN}'
--sort-by-file
${I18N_SRC_FILES}
COMMAND ${CMAKE_COMMAND} -E copy ${POT_FILE} ${CMAKE_CURRENT_SOURCE_DIR})
# Builds the binary translations catalog for each language
# it finds source translations (*.po) for
foreach(PO_FILE ${PO_FILES})
get_filename_component(LANG ${PO_FILE} NAME_WE)
gettext_process_po_files(${LANG} ALL PO_FILES ${PO_FILE})
set(INSTALL_DIR ${CMAKE_INSTALL_LOCALEDIR}/share/locale/${LANG}/LC_MESSAGES)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LANG}.gmo
DESTINATION ${INSTALL_DIR}
RENAME ${DOMAIN}.mo)
endforeach(PO_FILE)

View file

@ -0,0 +1,66 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the pantalaimon.thrrgilag package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: pantalaimon.thrrgilag\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-07-14 00:16+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../qml/Components/EditServerPage.qml:19
msgid "Homeserver Configuration"
msgstr ""
#: ../qml/Components/EditServerPage.qml:24
msgid "Save"
msgstr ""
#: ../qml/Components/EditServerPage.qml:83
msgid "Description:"
msgstr ""
#: ../qml/Components/EditServerPage.qml:103
msgid "Homeserver:"
msgstr ""
#: ../qml/Components/EditServerPage.qml:124
msgid "Listen on 127.0.0.1:"
msgstr ""
#: ../qml/SettingsPage.qml:19 pantalaimon.desktop.in.h:1
msgid "Pantalaimon UT"
msgstr ""
#: ../qml/SettingsPage.qml:24
msgid "About"
msgstr ""
#: ../qml/SettingsPage.qml:36
msgid "Service start disabled"
msgstr ""
#: ../qml/SettingsPage.qml:36
msgid "Service start enabled"
msgstr ""
#: ../qml/SettingsPage.qml:106
msgid "Delete homeserver"
msgstr ""
#: ../qml/SettingsPage.qml:124
msgid "No homeservers"
msgstr ""
#: ../qml/SettingsPage.qml:177
msgid "Add Homeserver"
msgstr ""

View file

@ -0,0 +1,146 @@
import QtQuick 2.7
import QtQuick.Layouts 1.3
import Ubuntu.Components 1.3
import Ubuntu.Components.ListItems 1.3
Page {
id: bottomEdgeComponent
property int idx: 0
property bool editmode: false
property alias instance: instance.text
property alias homeserver: homeserver.text
property alias listenport: listenport.text
signal save()
header: PageHeader {
id: header
title: i18n.tr('Homeserver Configuration')
trailingActionBar.actions: [
Action {
iconName: 'ok'
text: i18n.tr('Save')
onTriggered: {
var data = {
name: instance.text,
homeserver: homeserver.text,
listenport: listenport.text
}
if (editmode) {
listModel.set(idx, data);
pageStack.pop();
} else {
listModel.append(data)
bottomEdge.collapse();
}
save();
}
}
]
}
width: bottomEdge.width
height: bottomEdge.height
function resetdata() {
console.log("debug: resetdata");
instance.text = "";
homeserver.text = "";
listenport.text = "8009"; // TODO: maybe autoincrement based on existing entries?
}
Flickable {
clip: true
anchors {
top: header.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
contentHeight: contentColumn.height + units.gu(4)
Column {
id: contentColumn
anchors {
top: parent.top;
left: parent.left;
right: parent.right;
}
Row {
width: parent.width
height: units.gu(6)
leftPadding: units.gu(2)
spacing: units.gu(1)
Label {
anchors.verticalCenter: parent.verticalCenter
text: i18n.tr('Description:')
}
TextField {
id: instance
text: ""
anchors.verticalCenter: parent.verticalCenter
Layout.fillWidth: true
}
}
Row {
width: parent.width
height: units.gu(6)
leftPadding: units.gu(2)
spacing: units.gu(1)
Label {
anchors.verticalCenter: parent.verticalCenter
text: i18n.tr('Homeserver:')
}
TextField {
id: homeserver
text: ""
anchors.verticalCenter: parent.verticalCenter
Layout.fillWidth: true
inputMethodHints: Qt.ImhUrlCharactersOnly
}
}
Row {
width: parent.width
height: units.gu(6)
leftPadding: units.gu(2)
spacing: units.gu(1)
Label {
anchors.verticalCenter: parent.verticalCenter
text: i18n.tr('Listen on 127.0.0.1:')
}
TextField {
id: listenport
text: "8009"
anchors.verticalCenter: parent.verticalCenter
Layout.fillWidth: true
inputMethodHints: Qt.ImhDigitsOnly
}
}
}
}
Connections {
target: bottomEdge
onCollapseCompleted: {
resetdata();
}
}
}

21
qml/Main.qml Normal file
View file

@ -0,0 +1,21 @@
import QtQuick 2.7
import Ubuntu.Components 1.3
//import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import Qt.labs.settings 1.0
MainView {
id: root
objectName: 'mainView'
applicationName: 'pantalaimon.thrrgilag'
automaticOrientation: true
width: units.gu(45)
height: units.gu(75)
PageStack {
id: pageStack
Component.onCompleted: push(Qt.resolvedUrl('SettingsPage.qml'))
}
}

198
qml/SettingsPage.qml Normal file
View file

@ -0,0 +1,198 @@
import QtQuick 2.7
import QtQuick.Layouts 1.3
import Ubuntu.Components 1.3
import Ubuntu.Components.ListItems 1.3 as ListItems
import Qt.labs.settings 1.0
import io.thp.pyotherside 1.3
import "Components"
Page {
id: settingsPage
property bool is_running: false
property bool upstart: false
property string status_msg
header: PageHeader {
id: header
title: i18n.tr('Pantalaimon UT')
trailingActionBar.actions: [
Action {
iconName: 'info'
text: i18n.tr('About')
}
]
}
ListItem {
id: upstartState
anchors.top: header.bottom
width: parent.width
ListItems.Standard {
anchors.fill: parent
text: upstart ? i18n.tr("Service start enabled") : i18n.tr("Service start disabled")
control: Switch {
checked: upstart
onClicked: {
if (checked) {
py.call('service.add', [], function(result) {});
} else {
py.call('service.remove', [], function(result) {});
}
get_status();
}
}
}
}
ListItem {
id: serviceState
anchors.top: upstartState.bottom
width: parent.width
ListItems.Standard {
anchors.fill: parent
text: status_msg
control: Switch {
enabled: upstart
checked: is_running
onClicked: {
if (checked) {
py.call('service.start', [], function(result) {});
} else {
py.call('service.stop', [], function(result) {});
}
get_status();
}
}
}
}
ListView {
id: listView
width: parent.width
height: parent.height - bottomEdgeHint.height
anchors.top: serviceState.bottom
visible: (listView.count !== 0)
model: ListModel {
id: listModel
}
clip: true
delegate: ListItem {
ListItems.Standard {
anchors.fill: parent
text: name
progression: true
onClicked: {
var item = listModel.get(index);
console.log(item);
pageStack.push(editConfigPage, {
idx: index,
instance: item.name,
homeserver: item.homeserver,
listenport: item.listenport
});
}
}
leadingActions: ListItemActions {
actions: [
Action {
iconName: "delete"
text: i18n.tr("Delete homeserver")
onTriggered: {
console.log("debug: delete " + index);
listModel.remove(index);
saveConfig();
}
}
]
}
}
}
Rectangle {
visible: (listView.count === 0)
// color: "lightgrey"
anchors.fill: parent
Label {
text: i18n.tr("No homeservers")
fontSize: "x-large"
anchors.centerIn: parent
}
}
Python {
id: py
Component.onCompleted: {
addImportPath(Qt.resolvedUrl('../src/'));
importModule('config', function() {
py.call('config.load', [], function(result) {
for (var i=0; i<result.length; i++) {
listModel.append(result[i])
}
});
console.log("debug: python config loaded...");
});
importModule('service', function() {
console.log("debug: python service loaded...");
get_status();
});
}
}
function saveConfig() {
var lmdata = []
for (var i = 0; i < listModel.count; ++i) {
lmdata.push(listModel.get(i));
}
py.call("config.save", [JSON.stringify(lmdata)], function(result) {});
}
function get_status() {
py.call("service.check_upstart", [], function(result) {
upstart = result;
});
py.call("service.status", [], function(result) {
is_running = result[0];
status_msg = result[1];
});
}
BottomEdge {
id: bottomEdge
height: parent.height
hint {
id: bottomEdgeHint
text: i18n.tr("Add Homeserver")
iconName: "add"
status: BottomEdgeHint.Locked
onStatusChanged: if (status === BottomEdgeHint.Inactive) bottomEdge.hint.status = BottomEdgeHint.Locked
}
contentComponent: EditServerPage {
id: bottomEdgeComponent
onSave: saveConfig()
}
}
Component {
id: editConfigPage
EditServerPage {
editmode: true
onSave: saveConfig()
}
}
}

46
src/config.py Normal file
View file

@ -0,0 +1,46 @@
import configparser
import json
import logging
import os
logging.basicConfig(level=logging.DEBUG)
CONFFILE = '/home/phablet/.config/pantalaimon/pantalaimon.conf'
# CONFFILE = 'pantalaimon.conf'
def load():
entries = []
if os.path.exists(CONFFILE):
config = configparser.ConfigParser()
config.read_file(open(CONFFILE))
for instance in config.sections():
item = {'name': instance}
item['homeserver'] = config[instance].get('homeserver')
item['listenaddress'] = config[instance].get('listenaddress')
item['listenport'] = config[instance].get('listenport')
item['ignoreverification'] = config[instance].get('ignoreverification')
item['usekeyring'] = config[instance].get('usekeyring')
entries.append(item)
return entries
def save(data):
logging.debug("save config")
dataobj = json.loads(data)
config = configparser.ConfigParser()
for item in dataobj:
config[item['name']] = {}
config[item['name']]['homeserver'] = item['homeserver']
config[item['name']]['listenaddress'] = "127.0.0.1"
config[item['name']]['listenport'] = item['listenport']
config[item['name']]['ignoreverification'] = "true"
config[item['name']]['usekeyring'] = "false"
with open(CONFFILE,'w') as configfile:
config.write(configfile)

54
src/service.py Normal file
View file

@ -0,0 +1,54 @@
import subprocess
import logging
import os
logging.basicConfig(level=logging.DEBUG)
UPSTARTFILE = '/home/phablet/.config/upstart/pantalaimon.conf'
def status():
statuscmd = ['status', 'pantalaimon']
r = subprocess.run(statuscmd, stdout=subprocess.PIPE)
logging.debug(r)
running = "running" in r.stdout.decode()
return (running, r.stdout)
def start():
success = False
statuscmd = ['start', 'pantalaimon']
r = subprocess.run(statuscmd)
logging.debug(r)
if r.returncode == 0:
success = True
return success
def stop():
success = False
statuscmd = ['stop', 'pantalaimon']
r = subprocess.run(statuscmd)
logging.debug(r)
if r.returncode == 0:
success = True
return success
def add():
logging.debug('adding service file')
script = """
start on started unity8
respawn
exec /opt/click.ubuntu.com/pantalaimon.thrrgilag/current/pantalaimon
"""
with open(UPSTARTFILE, 'w') as upstart_file:
print(script, file=upstart_file)
start()
def remove():
logging.debug('removing service file')
stop()
os.remove(UPSTARTFILE)
def check_upstart():
return os.path.exists(UPSTARTFILE)
def check_env():
logging.debug(os.environ)