diff --git a/README.md b/README.md index 8959f15..721eb08 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ A password management app for Ubuntu Touch aiming to be compatible with [ZX2C4’s pass command line application](https://www.passwordstore.org/) the standard unix password manager. - # Building * Install [clickable](https://github.com/bhdouglass/clickable). @@ -11,6 +10,13 @@ A password management app for Ubuntu Touch aiming to be compatible with [ZX2C4 For more options/details see the [clickable documentation](http://clickable.bhdouglass.com/en/latest/index.html) +## Custom clickable command +* ```clickable c ``` : clean third directory and run ```clickable clean``` +* ```clickable crun ``` : clean third directory and run ```clickable``` +* ```clickable run``` : run ```clickable --dirty``` +* ```clickable crund ``` : clean third directory and run ```clickable desktop``` +* ```clickable rund ``` : run ```clickable desktop --dirty ``` + # Contributing Any contributions are welcome using the github issue & pull request system. @@ -110,8 +116,10 @@ List passwords that match pass-names along with this program. If not, see . -# Acknowledge -* Ubports -* pass -* clikable -* gpgmepp & gpgme & gpg +# Useful Links + +Some useful links related to UTpass development : +* [Ubports](https://ubports.com/) : Ubuntu Touch Community +* [ZX2C4’s pass command line application](https://www.passwordstore.org/) : the standard unix password manager. +* [Clickable](https://github.com/bhdouglass/clickable) : Compile, build, and deploy Ubuntu Touch click packages +* [Gpgme](https://www.gnupg.org/software/gpgme/index.html) : GnuPG Made Easy (GPGME) is a library designed to make access to GnuPG easier for applications diff --git a/clickable.json b/clickable.json index b51c9b1..e64cd45 100644 --- a/clickable.json +++ b/clickable.json @@ -2,7 +2,11 @@ "template": "cmake", "kill": "UTPass", "scripts": { - "clean_third": "third/clean.sh" + "c": "third/clean.sh && clickable clean", + "crun": "third/clean.sh && clickable", + "run": "clickable --dirty", + "crund": "third/clean.sh && clickable desktop", + "rund": "clickable desktop --dirty" }, "dependencies_build": [ "texinfo", diff --git a/main.cpp b/main.cpp index 0e6c89b..46b912b 100644 --- a/main.cpp +++ b/main.cpp @@ -3,10 +3,11 @@ #include #include #include -#include "gpgme++/global.h" +#include int main(int argc, char *argv[]) { + new QGuiApplication(argc, argv); QGuiApplication::setApplicationName("utpass.qrouland"); diff --git a/password-store/dir/pass.gpg b/password-store/dir/pass.gpg new file mode 100644 index 0000000..e69de29 diff --git a/password-store/pass.gpg b/password-store/pass.gpg new file mode 100644 index 0000000..e69de29 diff --git a/plugins/Pass/pass.cpp b/plugins/Pass/pass.cpp index eed9570..e095a4f 100644 --- a/plugins/Pass/pass.cpp +++ b/plugins/Pass/pass.cpp @@ -1,20 +1,59 @@ #include -#include -#include +#include #include "pass.h" +#include "gpgme++/global.h" +#include "qgpgme/protocol.h" +#include "qgpgme/encryptjob.h" +#include "qgpgme/decryptjob.h" +#include "qgpgme/keylistjob.h" + Pass::Pass() { - + GpgME::initializeLibrary(); + this->gpgHome = qgetenv("GNUPGHOME"); } -void Pass::cmd_show(const QString path) { - QDir dir = QDir(path); - if (!dir.exists()) { - qWarning("Path to show not found"); - return; +QString Pass::decrypt(const QByteArray cipherText) { + /*auto decJob = QGpgME::openpgp()->decryptJob(); + auto ctx = QGpgME::Job::context(decJob); + + TestPassphraseProvider provider; + ctx->setPassphraseProvider(&provider); + ctx->setPinentryMode(Context::PinentryLoopback); + + QByteArray plainText; + decJob->exec(cipherText, plainText); + + return QString::fromUtf8(plainText);*/ +} + +QString Pass::decrypt_file(const QString path) { + /*QFile file(path); + if (!file.open(QIODevice::ReadOnly)) { + qErrnoWarning("Can't open the File"); + return nullptr; } + QByteArray plainText = file.readAll(); + return Pass::decrypt(plainText);*/ } -void Pass::cmd_version() { +QByteArray Pass::encrypt(const QString str) { + /*auto listjob = QGpgME::openpgp()->keyListJob(false, false, false); + std::vector keys; + auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"), + false, keys); + auto job = QGpgME::openpgp()->encryptJob(/*ASCII Armor *//*true, /* Textmode *//* true); + QByteArray cipherText; + auto result = job->exec(keys, QStringLiteral("Hello World").toUtf8(), GpgME::Context::AlwaysTrust, cipherText); + return cipherText;*/ +} +bool Pass::encrypt_file(const QString str, const QString path) { + /*QFile file(path); + if (!file.open(QIODevice::WriteOnly)) { + qErrnoWarning("Can't open the File"); + return false; + } + file.write(Pass::encrypt(str)); + return true;*/ } \ No newline at end of file diff --git a/plugins/Pass/pass.h b/plugins/Pass/pass.h index cc73cc2..dbe9bb0 100644 --- a/plugins/Pass/pass.h +++ b/plugins/Pass/pass.h @@ -5,13 +5,16 @@ class Pass: public QObject { Q_OBJECT + QString gpgHome; public: Pass(); ~Pass() override = default; - Q_INVOKABLE void cmd_show(QString path) ; - Q_INVOKABLE void cmd_version() ; + Q_INVOKABLE QString decrypt(QByteArray plainText); + Q_INVOKABLE QString decrypt_file(QString path); + Q_INVOKABLE QByteArray encrypt(QString str); + Q_INVOKABLE bool encrypt_file(QString str, QString path); }; #endif diff --git a/plugins/Pass/plugin.h b/plugins/Pass/plugin.h index 9a366e6..c0988f5 100644 --- a/plugins/Pass/plugin.h +++ b/plugins/Pass/plugin.h @@ -8,7 +8,7 @@ class PassPlugin : public QQmlExtensionPlugin { Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") public: - void registerTypes(const char *uri); + void registerTypes(const char *uri) override; }; #endif diff --git a/po/utpass.qrouland.pot b/po/utpass.qrouland.pot index a9b6d74..72a5bc9 100644 --- a/po/utpass.qrouland.pot +++ b/po/utpass.qrouland.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: utpass.qrouland\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-03-13 20:28+0000\n" +"POT-Creation-Date: 2019-03-15 16:52+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,6 +17,31 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: ../qml/Main.qml:26 UTPass.desktop.in.h:1 +#: ../qml/pages/Settings.qml:8 ../qml/pages/headers/MainHeader.qml:19 +msgid "Settings" +msgstr "" + +#: ../qml/pages/PasswordList.qml:17 +msgid "Back" +msgstr "" + +#: ../qml/pages/PasswordList.qml:39 +msgid "No password found in the current folder" +msgstr "" + +#: ../qml/pages/Info.qml:9 ../qml/pages/headers/MainHeader.qml:26 +msgid "Info" +msgstr "" + +#: ../qml/pages/Info.qml:43 ../qml/pages/headers/MainHeader.qml:8 +#: ../qml/pages/headers/StackHeader.qml:7 UTPass.desktop.in.h:1 msgid "UTPass" msgstr "" + +#: ../qml/pages/Info.qml:53 +msgid "Suggest improvements or report a bug" +msgstr "" + +#: ../qml/pages/headers/MainHeader.qml:15 +msgid "Search" +msgstr "" diff --git a/qml/Main.qml b/qml/Main.qml index 19b022d..19a6b50 100644 --- a/qml/Main.qml +++ b/qml/Main.qml @@ -1,78 +1,22 @@ import QtQuick 2.4 import QtQuick.Layouts 1.1 -import Qt.labs.folderlistmodel 2.1 import Ubuntu.Components 1.3 -import Pass 1.0 -import "components" as MyComponents +import "components" MainView { id: root objectName: "mainView" applicationName: "utpass.qrouland" + automaticOrientation: true width: units.gu(45) height: units.gu(75) - - Page { - id: page + PageStack { + id: pageStack anchors.fill: parent - header: PageHeader { - id: header - width: parent.width - height: units.gu(6) - title: i18n.tr("UTPass") - flickable: navigation - leadingActionBar.height: units.gu(4) - leadingActionBar.actions: [ - Action { - id: backAction - iconName: "back" - text: "Back" - visible:false - onTriggered: { - folderModel.folder = folderModel.parentFolder; - if(folderModel.rootFolder === folderModel.folder) { - backAction.visible = false; - } - } - } - ] - } - - Flickable { - id: navigation - anchors.fill: parent - - Rectangle { - width: page.width - visible: folderModel.count == 0 - height: units.gu(5) - Text { - text: "No password found in the current folder" - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - } - } - - ListView { - id : listViewDirs - anchors.fill: parent - spacing: 1 - model: FolderListModel { - id: folderModel - nameFilters: ["*.gpg"] - rootFolder: "file:password-store" - folder: "file:password-store" - } - delegate: MyComponents.ViewFileDir { - id: fileDelegate - } - } - } - + Component.onCompleted: push(pageStack.push(Qt.resolvedUrl("pages/PasswordList.qml"))) } - //Component.onCompleted: Pass.speak() } diff --git a/qml/components/ViewFileDir.qml b/qml/components/FileDir.qml similarity index 91% rename from qml/components/ViewFileDir.qml rename to qml/components/FileDir.qml index 7485a71..f6697b2 100644 --- a/qml/components/ViewFileDir.qml +++ b/qml/components/FileDir.qml @@ -1,9 +1,10 @@ import QtQuick 2.4 import Ubuntu.Components 1.3 +import "../styles" Component { Rectangle { - width: page.width + width: parent.width height: units.gu(5) Text { @@ -19,7 +20,7 @@ Component { width: units.gu(4) height: units.gu(4) name: fileIsDir ? "go-next" : "lock" - color: UbuntuColors.orange + color: Theme.raisin_black } MouseArea { diff --git a/qml/components/Link.qml b/qml/components/Link.qml new file mode 100644 index 0000000..a9fc165 --- /dev/null +++ b/qml/components/Link.qml @@ -0,0 +1,55 @@ +import QtQuick 2.4 +import Ubuntu.Components 1.3 +import "../styles" + +Item { + property string url + property string text + + property bool commonBorder : true + property int lBorderwidth : 0 + property int rBorderwidth : 0 + property int tBorderwidth : 0 + property int bBorderwidth : 0 + property int commonBorderWidth : 0 + property string borderColor : UbuntuColors.warmGrey + + width: parent.width + height: units.gu(6) + + Rectangle { + width: parent.width + height: parent.height + + Text { + text: parent.parent.text + anchors.left: parent.left + anchors.leftMargin: units.gu(1) + anchors.verticalCenter: parent.verticalCenter + } + + Icon { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + width: units.gu(4) + height: units.gu(4) + name: "go-next" + color: Theme.raisin_black + } + + MouseArea { + anchors.fill: parent + onClicked: { Qt.openUrlExternally(parent.parent.url); } + } + + CustomBorder { + id : cb + commonBorder: parent.parent.commonBorder + lBorderwidth: parent.parent.lBorderwidth + rBorderwidth: parent.parent.rBorderwidth + tBorderwidth: parent.parent.tBorderwidth + bBorderwidth: parent.parent.bBorderwidth + borderColor: parent.parent.borderColor + } + } +} \ No newline at end of file diff --git a/qml/components/qmldir b/qml/components/qmldir new file mode 100644 index 0000000..dc821f9 --- /dev/null +++ b/qml/components/qmldir @@ -0,0 +1,2 @@ +FileDir 1.0 FileDir.qml +Link 1.0 Link.qml \ No newline at end of file diff --git a/qml/models/Manifest.qml b/qml/models/Manifest.qml new file mode 100644 index 0000000..a840c46 --- /dev/null +++ b/qml/models/Manifest.qml @@ -0,0 +1,6 @@ +pragma Singleton +import QtQuick 2.4 + +Item { + +} diff --git a/qml/models/Passstore.qml b/qml/models/Passstore.qml new file mode 100644 index 0000000..e69de29 diff --git a/qml/models/qmldir b/qml/models/qmldir new file mode 100644 index 0000000..959f056 --- /dev/null +++ b/qml/models/qmldir @@ -0,0 +1,2 @@ +singleton Passtore 1.0 Passtore.qml +singleton Manifest 1.0 Manifest.qml \ No newline at end of file diff --git a/qml/pages/Info.qml b/qml/pages/Info.qml new file mode 100644 index 0000000..2574b65 --- /dev/null +++ b/qml/pages/Info.qml @@ -0,0 +1,59 @@ +import QtQuick 2.4 +import Ubuntu.Components 1.3 +import "headers" +import "../components" + +Page { + header: StackHeader { + id : infoHeader + title: i18n.tr('Info') + } + + Rectangle { + anchors.top: infoHeader.bottom + anchors.bottom: parent.bottom + width: parent.width + color: "#FFF" + + Flow { + spacing: 2 + anchors.fill: parent + Rectangle { + width: parent.width + height: units.gu(4) + } + Rectangle { + width: parent.width + height: units.gu(12) + Image { + source: "../../assets/logo.svg" + width: units.gu(12) + height: units.gu(12) + anchors.horizontalCenter: parent.horizontalCenter + } + } + Rectangle { + width: parent.width + height: units.gu(4) + } + Text { + horizontalAlignment: Text.AlignHCenter + width: parent.width + height: units.gu(6) + text: i18n.tr('UTPass') + } + Text { + horizontalAlignment: Text.AlignHCenter + width: parent.width + height: units.gu(6) + text: "Version" //i18n.tr("Version %1").arg(Manifest.get("version")) + } + Link { + url: "https://github.com/QRouland/UTPass/issues" + text: i18n.tr('Suggest improvements or report a bug') + } + } + } +} + + diff --git a/qml/pages/PasswordList.qml b/qml/pages/PasswordList.qml new file mode 100644 index 0000000..67aac9b --- /dev/null +++ b/qml/pages/PasswordList.qml @@ -0,0 +1,59 @@ +import QtQuick 2.4 +import Ubuntu.Components 1.3 +import Qt.labs.folderlistmodel 2.1 +import "../components" +import "headers" + + +Page { + header : MainHeader { + flickable : nav + + leadingActionBar.height: units.gu(4) + leadingActionBar.actions: [ + Action { + id: backAction + iconName: "back" + text: i18n.tr("Back") + visible:false + onTriggered: { + folderModel.folder = folderModel.parentFolder; + if(folderModel.rootFolder === folderModel.folder) { + backAction.visible = false; + } + } + } + ] + } + + Flickable { + id: nav + height: parent.height + width: parent.width + + Rectangle { + width: parent.width + visible: folderModel.count == 0 + height: units.gu(5) + Text { + text: i18n.tr("No password found in the current folder") + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } + } + + ListView { + anchors.fill: parent + spacing: 1 + model: FolderListModel { + id: folderModel + nameFilters: ["*.gpg"] + rootFolder: "file:password-store" + folder: "file:password-store" + } + delegate: FileDir { + id: fileDelegate + } + } + } +} \ No newline at end of file diff --git a/qml/pages/Settings.qml b/qml/pages/Settings.qml new file mode 100644 index 0000000..f9f341e --- /dev/null +++ b/qml/pages/Settings.qml @@ -0,0 +1,30 @@ +import QtQuick 2.4 +import Ubuntu.Components 1.3 +import "headers" + +Page { + header: StackHeader { + id:settingsHeader + title: i18n.tr('Settings') + } + + Rectangle { + anchors.top: settingsHeader.bottom + anchors.bottom: parent.bottom + width: parent.width + color: "#FFF" + + Flow { + spacing: 1 + anchors.fill: parent + Text { + horizontalAlignment: Text.AlignHCenter + width: parent.width + height: units.gu(6) + text: "Settings" + } + } + } +} + + diff --git a/qml/pages/headers/MainHeader.qml b/qml/pages/headers/MainHeader.qml new file mode 100644 index 0000000..2b4944c --- /dev/null +++ b/qml/pages/headers/MainHeader.qml @@ -0,0 +1,32 @@ +import QtQuick 2.4 +import Ubuntu.Components 1.3 + +PageHeader { + id: mainHeader + width: parent.width + height: units.gu(6) + title: i18n.tr("UTPass") + + trailingActionBar.height: units.gu(4) + trailingActionBar.numberOfSlots: 2 + trailingActionBar.actions: [ + Action { + iconName: "search" + text: i18n.tr("Search") + }, + Action { + iconName: "settings" + text: i18n.tr("Settings") + onTriggered: { + pageStack.push(Qt.resolvedUrl("../Settings.qml")) + } + }, + Action { + iconName: "info" + text: i18n.tr("Info") + onTriggered: { + pageStack.push(Qt.resolvedUrl("../Info.qml")) + } + } + ] +} \ No newline at end of file diff --git a/qml/pages/headers/StackHeader.qml b/qml/pages/headers/StackHeader.qml new file mode 100644 index 0000000..a274986 --- /dev/null +++ b/qml/pages/headers/StackHeader.qml @@ -0,0 +1,20 @@ +import QtQuick 2.4 +import Ubuntu.Components 1.3 + +PageHeader { + width: parent.width + height: units.gu(6) + title: i18n.tr("UTPass") + + leadingActionBar.height: units.gu(4) + leadingActionBar.actions: [ + Action { + id: backAction + iconName: "back" + text: "Back" + onTriggered: { + pageStack.pop() + } + } + ] +} diff --git a/qml/pages/headers/qmldir b/qml/pages/headers/qmldir new file mode 100644 index 0000000..8381250 --- /dev/null +++ b/qml/pages/headers/qmldir @@ -0,0 +1,2 @@ +MainHeader 1.0 MainHeader.qml +StackHeader 1.0 StackHeader.qml diff --git a/qml/pages/qmldir b/qml/pages/qmldir new file mode 100644 index 0000000..27f324e --- /dev/null +++ b/qml/pages/qmldir @@ -0,0 +1,4 @@ +Info 1.0 Info.qml +PassordList 1.0 Password.qml +Settings 1.0 Settings.qml +UTPassPage 1.0 UTPassPage.qml diff --git a/qml/components/CustomBorder.qml b/qml/styles/CustomBorder.qml similarity index 100% rename from qml/components/CustomBorder.qml rename to qml/styles/CustomBorder.qml diff --git a/qml/styles/Theme.qml b/qml/styles/Theme.qml new file mode 100644 index 0000000..76ffc64 --- /dev/null +++ b/qml/styles/Theme.qml @@ -0,0 +1,10 @@ +pragma Singleton +import QtQuick 2.4 + +Item { + readonly property color claret : "#77172A" + readonly property color raisin_black : "#AE2B25" + readonly property color steel_blue : "#462C98" + readonly property color twilight_lavender : "#754888" + readonly property color eerie_black : "#191716" +} \ No newline at end of file diff --git a/qml/styles/qmldir b/qml/styles/qmldir new file mode 100644 index 0000000..7e8032e --- /dev/null +++ b/qml/styles/qmldir @@ -0,0 +1,2 @@ +CustomBorder 1.0 CustomBorder.qml +singleton Theme 1.0 Theme.qml \ No newline at end of file