This commit is contained in:
Quentin Rouland 2019-03-23 20:53:02 +01:00
parent c26443b6f8
commit c044cefc26
25 changed files with 420 additions and 331 deletions

8
.gitignore vendored
View File

@ -1,14 +1,14 @@
# Builds dirs
cmake-build-*
build
build*
# IDE
# IDE & Devs tools
.clickable
.idea
*.project
*.workspace
.codelite
*.kdev4
*swp
# Third parties ouput dir
third/local

View File

@ -3,6 +3,10 @@ cmake_minimum_required(VERSION 3.5.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
option(TEST_RUNNER "Run Test" OFF)
if(${TEST_RUNNER})
add_definitions(-DTEST_RUNNER)
endif()
execute_process(
COMMAND dpkg-architecture -qDEB_HOST_ARCH
@ -16,6 +20,7 @@ execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE
)
find_package(Qt5Core)
find_package(Qt5Qml)
find_package(Qt5Quick)
@ -36,7 +41,13 @@ set(DESKTOP_FILE_NAME ${PROJECT_NAME}.desktop)
add_executable(${PROJECT_NAME} main.cpp)
qt5_use_modules(${PROJECT_NAME} Gui Qml Quick)
if(${TEST_RUNNER})
find_package(Qt5QuickTest)
qt5_use_modules(${PROJECT_NAME} Gui Qml Quick QuickTest)
else()
qt5_use_modules(${PROJECT_NAME} Gui Qml Quick)
endif()
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/manifest.json)
@ -45,12 +56,15 @@ install(FILES ${PROJECT_NAME}.apparmor DESTINATION ${DATA_DIR})
install(DIRECTORY qml DESTINATION ${DATA_DIR})
install(DIRECTORY assets DESTINATION ${DATA_DIR})
file(GLOB_RECURSE BIN_FILES
"third/local/bin/${ARCH_TRIPLET}/*")
"third/local/${ARCH_TRIPLET}/bin/*")
install(
FILES ${BIN_FILES}
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
DESTINATION ${BIN_DIR}
)
if(${TEST_RUNNER})
install(DIRECTORY tests DESTINATION ${DATA_DIR})
endif()
# Translations
file(GLOB_RECURSE I18N_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po qml/*.qml qml/*.js)
@ -77,3 +91,4 @@ add_subdirectory(po)
add_subdirectory(plugins)
add_custom_target(${PROJECT_NAME}_FILES ALL SOURCES ${PROJECT_SRC_FILES})

79
FEATURES.MD Normal file
View File

@ -0,0 +1,79 @@
# Features
## Pass
- [ ] pass init [--path=subfolder,-p subfolder] gpg-id...
Initialize new password storage and use gpg-id for encryption.
Selectively reencrypt existing passwords using new gpg-id.
- [ ] Interactive dialog to init a new password storage
- [ ] Support subfolder
- [ ] Support reencrypt
---
- [x] pass [ls] [subfolder]
List passwords.
- [x] UI allowing to navigate through the password store showing the available passwords
---
- [ ] pass find pass-names...
List passwords that match pass-names
- [ ] Search bar allowing searchs by pass-names
---
- [ ] pass [show] [--clip[=line-number],-c[line-number]] pass-name
Show existing password and optionally put it on the clipboard.
If put on the clipboard, it will be cleared in 45 seconds.
- [ ] Click on a pass show the password
- [ ] Add option to put the password to the clipboard
- [ ] Clearing clipboard after 45 secs
- [ ] Line number option ???
---
- [ ] pass grep search-string
Search for password files containing search-string when decrypted.
- [ ] TBD
---
- [ ] pass insert [--echo,-e | --multiline,-m] [--force,-f] pass-name
Insert new password. Optionally, echo the password back to the console
during entry. Or, optionally, the entry may be multiline. Prompt before
overwriting existing password unless forced.
- [ ] TBD
---
- [ ] pass edit pass-name
Insert a new password or edit an existing password using editor.
- [ ] TBD
---
- [ ] pass generate [--no-symbols,-n] [--clip,-c] [--in-place,-i | --force,-f] pass-name [pass-length]
Generate a new password of pass-length (or 25 if unspecified) with optionally no symbols.
Optionally put it on the clipboard and clear board after 45 seconds.
Prompt before overwriting existing password unless forced.
Optionally replace only the first line of an existing file with a new password.
- [ ] TBD
---
- [ ] pass rm [--recursive,-r] [--force,-f] pass-name
Remove existing password or directory, optionally forcefully.
- [ ] TBD
---
- [ ] pass mv [--force,-f] old-path new-path
Renames or moves old-path to new-path, optionally forcefully, selectively reencrypting.
- [ ] TBD
---
- [ ] pass cp [--force,-f] old-path new-path
Copies old-path to new-path, optionally forcefully, selectively reencrypting.
- [ ] TBD
---
- [ ] pass git git-command-args...
If the password store is a git repository, execute a git command
specified by git-command-args.
- [ ] TBD
---
- [ ] pass help
Show this text.
- [ ] TBD
---
- [ ] pass version
Show version information.
- [ ] TBD
---
## Gpg
TODO

View File

@ -18,6 +18,20 @@ For more options/details see the [clickable documentation](http://clickable.bhdo
* ```clickable third_clean ``` : clean third parties
* ```clickable style ``` : reformat the code (Required [astyle](astyle.sourceforge.ne) & [qmlfmt](https://github.com/jesperhh/qmlfmt) installed)
## Testing
To switch to the tests build you need to add the following arguments to the build command : -DTEST_RUNNER=ON.
To do so with clickable you need to use the following commands:
```
export CLICKABLE_BUILD_ARGS='-DTEST_RUNNER=ON'
clickable
```
To comeback to the app build unset the environnment variable :
```
unset CLICKABLE_BUILD_ARGS
```
# Contributing
Any contributions are welcome using the github issue & pull request system.
@ -25,80 +39,8 @@ Please respect the code style format by running ```clickable style``` before com
# Features
The goal is to be closest possible of the features offer by [ZX2C4s pass command line application](https://www.passwordstore.org/):
---
- [ ] pass init [--path=subfolder,-p subfolder] gpg-id...
Initialize new password storage and use gpg-id for encryption.
Selectively reencrypt existing passwords using new gpg-id.
- [ ] Interactive dialog to init a new password storage
- [ ] Support subfolder
- [ ] Support reencrypt
---
- [x] pass [ls] [subfolder]
List passwords.
- [x] UI allowing to navigate through the password store showing the available passwords
---
- [ ] pass find pass-names...
List passwords that match pass-names
- [ ] Search bar allowing searchs by pass-names
---
- [ ] pass [show] [--clip[=line-number],-c[line-number]] pass-name
Show existing password and optionally put it on the clipboard.
If put on the clipboard, it will be cleared in 45 seconds.
- [ ] Click on a pass show the password
- [ ] Add option to put the password to the clipboard
- [ ] Clearing clipboard after 45 secs
- [ ] Line number option ???
---
- [ ] pass grep search-string
Search for password files containing search-string when decrypted.
- [ ] TBD
---
- [ ] pass insert [--echo,-e | --multiline,-m] [--force,-f] pass-name
Insert new password. Optionally, echo the password back to the console
during entry. Or, optionally, the entry may be multiline. Prompt before
overwriting existing password unless forced.
- [ ] TBD
---
- [ ] pass edit pass-name
Insert a new password or edit an existing password using editor.
- [ ] TBD
---
- [ ] pass generate [--no-symbols,-n] [--clip,-c] [--in-place,-i | --force,-f] pass-name [pass-length]
Generate a new password of pass-length (or 25 if unspecified) with optionally no symbols.
Optionally put it on the clipboard and clear board after 45 seconds.
Prompt before overwriting existing password unless forced.
Optionally replace only the first line of an existing file with a new password.
- [ ] TBD
---
- [ ] pass rm [--recursive,-r] [--force,-f] pass-name
Remove existing password or directory, optionally forcefully.
- [ ] TBD
---
- [ ] pass mv [--force,-f] old-path new-path
Renames or moves old-path to new-path, optionally forcefully, selectively reencrypting.
- [ ] TBD
---
- [ ] pass cp [--force,-f] old-path new-path
Copies old-path to new-path, optionally forcefully, selectively reencrypting.
- [ ] TBD
---
- [ ] pass git git-command-args...
If the password store is a git repository, execute a git command
specified by git-command-args.
- [ ] TBD
---
- [ ] pass help
Show this text.
- [ ] TBD
---
- [ ] pass version
Show version information.
- [ ] TBD
---
The goal is to be closest possible of the features offer by [ZX2C4s pass command line application](https://www.passwordstore.org/).
See to the FEATURES.MD file for detailed comparison.
# License

View File

@ -4,8 +4,8 @@
"scripts": {
"third_build": "clickable run 'cd third && ./clean.sh && mkdir build && cd build && cmake .. && make'",
"third_build_d": "clickable run 'cd third && ./clean.sh && mkdir build && cd build && cmake .. && make' --arch amd64 ",
"third_clean": "cd third && ./clean.sh",
"style": "astyle --options=.astylerc \"plugins/*.cpp,*.h\" && qmlfmt -w tests && qmlfmt -w qml"
"third_clean": "cd third && rm -rf local && ./clean.sh",
"style": "astyle --options=.astylerc 'plugins/*.cpp,*.h' && qmlfmt -w tests && qmlfmt -w qml"
},
"dependencies_build": [
"texinfo",

View File

@ -5,16 +5,27 @@
#include <QQuickView>
#include <QtQml>
#ifdef TEST_RUNNER
#include <QtQuickTest/quicktest.h>
#endif
int main(int argc, char *argv[])
{
new QGuiApplication(argc, argv);
QGuiApplication::setApplicationName("utpass.qrouland");
#ifndef TEST_RUNNER
qDebug() << "Starting app from main.cpp";
new QGuiApplication(argc, argv);
QGuiApplication::setApplicationName("utpass.qrouland");
auto *view = new QQuickView();
view->setSource(QUrl(QStringLiteral("qml/Main.qml")));
view->show();
return QGuiApplication::exec();
#else
qDebug() << "Starting tests from main.cpp";
return quick_test_main(argc, argv, "Tests", "tests/unit");
#endif
}

View File

@ -1,3 +1,2 @@
add_subdirectory(Gpg)
add_subdirectory(Pass)

View File

@ -1,47 +0,0 @@
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(PLUGIN "Gpg")
set(
SRC
plugin.cpp
gpg.cpp
)
set(CMAKE_AUTOMOC ON)
add_library(${PLUGIN} MODULE ${SRC})
set_target_properties(${PLUGIN} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN})
qt5_use_modules(${PLUGIN} Qml Quick DBus)
set(EXTERNAL_LIBS "${CMAKE_SOURCE_DIR}/third/local/${ARCH_TRIPLET}")
set(THIRD_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
INCLUDE_DIRECTORIES(${EXTERNAL_LIBS}/include)
add_library(GpgError STATIC IMPORTED)
set_property(TARGET GpgError PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libgpg-error.a")
add_library(GpgAssuan STATIC IMPORTED)
set_property(TARGET GpgAssuan PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libassuan.a")
add_library(Gpgme STATIC IMPORTED)
set_property(TARGET Gpgme PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libgpgme.a")
add_library(Gpgmepp STATIC IMPORTED)
set_property(TARGET Gpgmepp PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libgpgmepp.a")
add_library(QGpgme STATIC IMPORTED)
set_property(TARGET QGpgme PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libqgpgme.a")
target_link_libraries(${PLUGIN} QGpgme Gpgmepp Gpgme GpgAssuan GpgError)
execute_process(
COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
OUTPUT_VARIABLE ARCH_TRIPLET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(QT_IMPORTS_DIR "/lib/${ARCH_TRIPLET}")
install(TARGETS ${PLUGIN} DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN}/)
install(FILES qmldir DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN}/)

View File

@ -1,24 +0,0 @@
#ifndef PASS_H
#define PASS_H
#include <QObject>
class Gpg : public QObject
{
Q_OBJECT
public:
Gpg();
~Gpg() override = default;
Q_INVOKABLE void listDir();
Q_INVOKABLE QString getKeyId(QString uid);
Q_INVOKABLE QStringList getAllKeysId();
Q_INVOKABLE bool importKey(QString path);
Q_INVOKABLE QString decrypt(QByteArray plainText);
Q_INVOKABLE QString decryptFile(QString path);
Q_INVOKABLE QByteArray encrypt(QString str);
Q_INVOKABLE bool encryptFile(QString str, QString path);
};
#endif

View File

@ -1,10 +0,0 @@
#include <QtQml>
#include "plugin.h"
#include "gpg.h"
void GpgPlugin::registerTypes(const char *uri)
{
//@uri Pass
qmlRegisterSingletonType<Gpg>(uri, 1, 0, "Gpg", [](QQmlEngine *, QJSEngine *) -> QObject * { return new Gpg; });
}

View File

@ -1,16 +0,0 @@
#ifndef GPGPLUGIN_H
#define GPGPLUGIN_H
#include <QQmlExtensionPlugin>
class GpgPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID
"org.qt-project.Qt.QQmlExtensionInterface")
public:
void registerTypes(const char *uri);
};
#endif

View File

@ -1,2 +0,0 @@
module Gpg
plugin Gpg

View File

@ -5,21 +5,48 @@ set(
SRC
plugin.cpp
pass.cpp
gpg.cpp
)
set(CMAKE_AUTOMOC ON)
add_library(${PLUGIN} MODULE ${SRC})
set_target_properties(${PLUGIN} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN})
qt5_use_modules(${PLUGIN} Qml Quick DBus)
execute_process(
COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH
OUTPUT_VARIABLE ARCH_TRIPLET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(ARCH_TRIPLET STREQUAL "")
set(ARCH_TRIPLET x86_64-linux-gnu)
endif()
add_library(${PLUGIN} MODULE ${SRC})
set_target_properties(${PLUGIN} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGIN})
qt5_use_modules(${PLUGIN} Qml Quick DBus)
set(EXTERNAL_LIBS "${CMAKE_SOURCE_DIR}/third/local/${ARCH_TRIPLET}")
set(THIRD_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
INCLUDE_DIRECTORIES(${EXTERNAL_LIBS}/include)
add_library(GpgError STATIC IMPORTED)
set_property(TARGET GpgError PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libgpg-error.a")
add_library(GpgAssuan STATIC IMPORTED)
set_property(TARGET GpgAssuan PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libassuan.a")
add_library(Gpgme STATIC IMPORTED)
set_property(TARGET Gpgme PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libgpgme.a")
add_library(Gpgmepp STATIC IMPORTED)
set_property(TARGET Gpgmepp PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libgpgmepp.a")
add_library(QGpgme STATIC IMPORTED)
set_property(TARGET QGpgme PROPERTY IMPORTED_LOCATION "${EXTERNAL_LIBS}/lib/libqgpgme.a")
target_link_libraries(${PLUGIN} QGpgme Gpgmepp Gpgme GpgAssuan GpgError)
set(QT_IMPORTS_DIR "/lib/${ARCH_TRIPLET}")
install(TARGETS ${PLUGIN} DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN}/)

View File

@ -2,6 +2,7 @@
#include <QFile>
#include <QDir>
#include <QtCore/QStandardPaths>
#include <memory>
#include "gpg.h"
#include "gpgme++/global.h"
@ -13,6 +14,7 @@
#include "qgpgme/importjob.h"
#include "gpgme++/importresult.h"
#include "qgpgme/decryptjob.h"
#include "qgpgme/encryptjob.h"
using namespace GpgME;
using namespace QGpgME;
@ -26,13 +28,7 @@ Gpg::Gpg()
qFatal("GpgME init fail");
}
QString gnuhome = QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation).append("/gpghome");
QDir dir(gnuhome);
if (!dir.exists())
dir.mkpath(".");
qputenv("GNUPGHOME", gnuhome.toStdString().c_str());
qDebug() << "GNUPGHOME is :" << qgetenv("GNUPGHOME");
setGpghome();
error = checkEngine(OpenPGP);
if (error) {
@ -43,86 +39,99 @@ Gpg::Gpg()
qDebug() << "GpgME Engine Version :" << engineInfo(OpenPGP).version();
}
void Gpg::listDir()
bool Gpg::setGpghome(QString path)
{
qDebug() << "hello world!";
QFileInfo file(path);
if (file.isFile()) {
qWarning() << "Not a directory GNUPGHOME not change";
return false;
}
if (file.isDir() and !file.isWritable()) {
qWarning() << "Not a writable directory GNUPGHOME not change";
return false;
}
QDir dir(path);
if (!dir.exists()) {
dir.mkpath(".");
}
m_gpghome = dir;
qputenv("GNUPGHOME", m_gpghome.absolutePath().toStdString().c_str());
qDebug() << "GNUPGHOME is :" << qgetenv("GNUPGHOME");
}
QString Gpg::decrypt(const QByteArray cipherText)
{
/*auto decJob = openpgp()->decryptJob();
auto ctx = DecryptJob::context(decJob);*/
/*
auto decJob = openpgp()->decryptJob();
auto ctx = DecryptJob::context(decJob);
/* TODO
* TestPassphraseProvider provider;
TestPassphraseProvider provider;
ctx->setPassphraseProvider(&provider);
ctx->setPinentryMode(Context::PinentryLoopback);*/
ctx->setPinentryMode(Context::PinentryLoopback);
/*QByteArray plainText;
QByteArray plainText;
decJob->exec(cipherText, plainText);
return QString::fromUtf8(plainText);*/
}
QString Gpg::decryptFile(QString path)
QString Gpg::decryptFromFile(QString path)
{
/*QFile file(path);
QFile file(path);
if (!file.open(QIODevice::ReadOnly)) {
qErrnoWarning("Can't open the File");
qWarning() << "Can't open the File";
return nullptr;
}
QByteArray plainText = file.readAll();
return this->decrypt(plainText);*/
return decrypt(plainText);
}
QByteArray Gpg::encrypt(const QString str)
QByteArray Gpg::encrypt(QString str, QString uid, bool ascii_armor, bool text_mode)
{
/*auto listjob = openpgp()->keyListJob(false, false, false);
std::vector<Key> keys;
auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"), false, keys);
qDebug() << "Encrypt to QByteArray";
auto keys = getKeys(uid);
auto job = openpgp()
->encryptJob(
true, //ASCII Armor
true //Textmode
);
->encryptJob(
ascii_armor,
text_mode
);
QByteArray cipherText;
auto result = job->exec(keys, QStringLiteral("Hello World").toUtf8(), Context::AlwaysTrust, cipherText);
return cipherText;*/
//auto result = job->exec(keys, str.toUtf8(), Context::AlwaysTrust, cipherText);
return cipherText;
}
bool Gpg::encryptFile(QString str, QString path)
bool Gpg::encryptToFile(QString str, QString path, const QString uid, bool ascii_armor,
bool text_mode)
{
/*QFile file(path);
qDebug() << "Encrypt to file " << path;
QFile file(path);
if (!file.open(QIODevice::WriteOnly)) {
qErrnoWarning("Can't open the File");
qWarning() << "Can't open the file to write it" ;
return false;
}
file.write(Pass::encrypt(str));
return true;*/
file.write(encrypt(str, uid, ascii_armor, text_mode));
return true;
}
QString Gpg::getKeyId(QString uid)
std::vector<Key> Gpg::getKeys(QString pattern_uid, bool remote, bool include_sigs, bool validate)
{
qDebug() << "Getting the key id " << uid;
auto *job = openpgp()->keyListJob(false, false, false);
qDebug() << "Getting the key " << pattern_uid;
auto *job = openpgp()->keyListJob(remote, include_sigs, validate);
std::vector<Key> keys;
auto result = job->exec(QStringList() << uid, false, keys);
auto result = job->exec(QStringList() << pattern_uid, false, keys);
delete job;
if (keys.empty()) {
qDebug() << "No key found for" << uid;
return nullptr;
}
const QString kId = QLatin1String(keys.front().keyID());
qDebug() << "Id key for " << uid << "is : " << kId;
return kId;
return keys;
}
QStringList Gpg::getAllKeysId()
QStringList Gpg::getAllKeysId(bool remote, bool include_sigs, bool validate)
{
qDebug() << "Show all available key";
auto job = openpgp()->keyListJob(false, false, false);
auto job = openpgp()->keyListJob(remote, remote, validate);
std::vector<Key> keys;
auto result = job->exec(QStringList(""), false, keys);
delete job;
@ -140,7 +149,7 @@ QStringList Gpg::getAllKeysId()
return r;
}
bool Gpg::importKey(QString path)
bool Gpg::importKeyFromFile(QString path)
{
qDebug() << "Importing the key file" << path;
QFile file(path);
@ -159,15 +168,5 @@ bool Gpg::importKey(QString path)
qWarning() << "Import go wrong";
return false;
}
qDebug() << "Key imported" << result.numImported();
qDebug() << "Key not imported" << result.notImported();
qDebug() << "Key unchanged" << result.numUnchanged();
qDebug() << "Result null" << result.isNull();
qDebug() << "newUserIDs" << result.newUserIDs();
for (const auto &key : result.imports())
qDebug() << "Key" << key.fingerprint();
return true;
return result.imports().size() == 1;
}

38
plugins/Pass/gpg.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef GPG_H
#define GPG_H
#include <memory>
#include "gpgme++/key.h"
class Gpg
{
private:
Gpg();
QDir m_gpghome;
public:
~Gpg();
static std::shared_ptr<Gpg> instance()
{
static std::shared_ptr<Gpg> s{new Gpg};
return s;
}
Gpg(Gpg const &) = delete;
void operator=(Gpg const &) = delete;
QString decrypt(QByteArray plainText);
QString decryptFromFile(QString path);
QByteArray encrypt(QString str, QString uid, bool ascii_armor = true, bool text_mode = true);
bool encryptToFile(QString str, QString path, const QString uid, bool ascii_armor = true,
bool text_mode = true);
bool importKeyFromFile(QString path);
std::vector<GpgME::Key> getKeys(QString pattern_uid, bool remote = false, bool include_sigs = false,
bool validate = false);
QStringList getAllKeysId(bool remote = false, bool include_sigs = false, bool validate = false);
bool setGpghome(QString path = QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation).append("/gpghome"));
};
#endif

View File

@ -4,17 +4,30 @@
#include <QtCore/QDir>
#include "pass.h"
#include "gpg.h"
Pass::Pass(){
pass_store = QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation).append("/.password-store");
QDir dir(pass_store);
Pass::Pass()
{
m_password_store = QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation).append("/.password-store");
QDir dir(m_password_store);
if (!dir.exists())
dir.mkpath(".");
qDebug() << "Password Store is :" << pass_store;
qDebug() << "Password Store is :" << m_password_store;
}
void Pass::speak()
bool Pass::gpgImportKeyFromFile(QString path)
{
qDebug() << "Starting app from main.cpp";
return Gpg::instance()->importKeyFromFile(path);
}
QStringList Pass::gpgListAllKeys()
{
return Gpg::instance()->getAllKeysId();
}
bool Pass::gpgSetGpghome(QString path)
{
return Gpg::instance()->setGpghome(path);
}

View File

@ -2,17 +2,19 @@
#define PASS_H
#include <QObject>
#include <memory>
class Pass : public QObject
{
Q_OBJECT
QString pass_store;
QString m_password_store;
public:
Pass();
~Pass() override = default;
Q_INVOKABLE void speak();
Q_INVOKABLE bool gpgImportKeyFromFile(QString path);
Q_INVOKABLE QStringList gpgListAllKeys();
Q_INVOKABLE bool gpgSetGpghome(QString path);
};
#endif

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: utpass.qrouland\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-03-22 16:39+0000\n"
"POT-Creation-Date: 2019-03-23 19:50+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"
@ -17,10 +17,6 @@ msgstr ""
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../qml/pages/Settings.qml:8 ../qml/pages/headers/MainHeader.qml:49
msgid "Settings"
msgstr ""
#: ../qml/pages/PasswordList.qml:16
msgid "Back"
msgstr ""
@ -29,7 +25,21 @@ msgstr ""
msgid "No password found in the current folder"
msgstr ""
#: ../qml/pages/Info.qml:10 ../qml/pages/headers/MainHeader.qml:56
#: ../qml/pages/Settings.qml:8 ../qml/pages/headers/MainHeader.qml:49
msgid "Settings"
msgstr ""
#: ../qml/pages/headers/MainHeader.qml:8 ../qml/pages/headers/StackHeader.qml:8
#: UTPass.desktop.in.h:1
msgid "UTPass"
msgstr ""
#: ../qml/pages/headers/MainHeader.qml:23
#: ../qml/pages/headers/MainHeader.qml:38
msgid "Search"
msgstr ""
#: ../qml/pages/headers/MainHeader.qml:56 ../qml/pages/Info.qml:10
msgid "Info"
msgstr ""
@ -56,13 +66,3 @@ msgstr ""
#: ../qml/pages/Info.qml:75
msgid "<font size=\"2\">Released under the terms of the GNU GPL v3</font>"
msgstr ""
#: ../qml/pages/headers/MainHeader.qml:8 ../qml/pages/headers/StackHeader.qml:8
#: UTPass.desktop.in.h:1
msgid "UTPass"
msgstr ""
#: ../qml/pages/headers/MainHeader.qml:23
#: ../qml/pages/headers/MainHeader.qml:38
msgid "Search"
msgstr ""

View File

@ -1,7 +1,6 @@
import QtQuick 2.4
import QtQuick.Layouts 1.1
import Ubuntu.Components 1.3
import Gpg 1.0
import "components"
@ -23,7 +22,6 @@ MainView {
"pages/PasswordList.qml")))
}
Component.onCompleted: {
Gpg.importKey("password-store/public.key")
Gpg.getAllKeysId()
}
}

View File

@ -2,30 +2,30 @@ pragma Singleton
import QtQuick 2.4
Item {
id: manifest
property string name : ""
property string description : ""
property string architecture : ""
property string title : ""
property string version : ""
property string maintainer : ""
property string framework : ""
id: manifest
property string name: ""
property string description: ""
property string architecture: ""
property string title: ""
property string version: ""
property string maintainer: ""
property string framework: ""
Component.onCompleted: {
var xhr = new XMLHttpRequest;
xhr.open("GET", "../../manifest.json");
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
var mJson = JSON.parse(xhr.responseText);
manifest.name = mJson.name
manifest.description = mJson.description
manifest.architecture = mJson.architecture
manifest.title = mJson.title
manifest.version = mJson.version
manifest.maintainer = mJson.maintainer
manifest.framework = mJson.framework
}
};
xhr.send();
}
var xhr = new XMLHttpRequest
xhr.open("GET", "../../manifest.json")
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
var mJson = JSON.parse(xhr.responseText)
manifest.name = mJson.name
manifest.description = mJson.description
manifest.architecture = mJson.architecture
manifest.title = mJson.title
manifest.version = mJson.version
manifest.maintainer = mJson.maintainer
manifest.framework = mJson.framework
}
}
xhr.send()
}
}

View File

@ -19,16 +19,17 @@ Page {
Flow {
spacing: units.gu(3)
anchors.fill: parent
Rectangle {
Rectangle {
width: parent.width
height: units.gu(1)
}
Text {
Text {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
verticalAlignment: Text.AlignVCenter
width: parent.width
height: units.gu(4)
text: i18n.tr('<b><font size="6">%1</font></b>').arg(Manifest.title)
text: i18n.tr('<b><font size="6">%1</font></b>').arg(
Manifest.title)
}
Rectangle {
width: parent.width
@ -40,40 +41,44 @@ Page {
anchors.horizontalCenter: parent.horizontalCenter
}
}
Text {
Text {
horizontalAlignment: Text.AlignHCenter
width: parent.width
height: units.gu(6)
text: i18n.tr('<font size="4">Maintainer<br>%1</font>').arg(Manifest.maintainer)
text: i18n.tr('<font size="4">Maintainer<br>%1</font>').arg(
Manifest.maintainer)
}
Text {
horizontalAlignment: Text.AlignHCenter
width: parent.width
height: units.gu(6)
text: i18n.tr('<font size="4">Version<br>%1</font><br>%2@%3').arg(Manifest.version).arg(Manifest.framework).arg(Manifest.architecture)
text: i18n.tr(
'<font size="4">Version<br>%1</font><br>%2@%3').arg(
Manifest.version).arg(Manifest.framework).arg(
Manifest.architecture)
}
}
Flow {
spacing: 2
Flow {
spacing: 2
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.left: parent.left
Link {
anchors.right: parent.right
anchors.left: parent.left
Link {
url: "https://github.com/QRouland/UTPass/issues"
text: i18n.tr('Suggest improvement(s) or report a bug(s)')
}
Link {
Link {
url: "https://github.com/QRouland/UTPass"
text: i18n.tr('Access to the source code')
}
Text {
width: parent.width
Text {
width: parent.width
height: units.gu(3)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: i18n.tr('<font size="2">Released under the terms of the GNU GPL v3</font>')
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: i18n.tr(
'<font size="2">Released under the terms of the GNU GPL v3</font>')
}
}
}
}
}

View File

@ -0,0 +1 @@
This not a key file

View File

@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFyNdOEBCADl2oWeYkmVBDWoWgZdkpbV5VRJJFATLsu5aHBuQO/C1mn2RlL2
jIpIzI5mwviAw9RN0KnLdHvp3n3JkJPZ8tB3Sk9SD8qhr6ae2DbIpySMscYC9+Go
t0mrGyB3w+Y5etfZ/1dRNx6/vYaWYIG6bKfJettt/zLJcjpkIKcrN4OKyN2wXz3y
EiAiJvMntdgLslURl93RyNuVR6UaE4TchtDqRc2KvXAxrf6NUYd4KxvUgUd0TFPs
s3SRs+cAcRmTzxv/c40sBw3z0B9rBB7T7oPgGUA6NhErvBwpF9MLN+6ucZ1HHLLH
dmCd7q2OT7wZ9L6zILmKvJcK13V4FyO9zOALABEBAAG0I1Rlc3QgKFRlc3QgZ3Bn
IGtleSkgPHRlc3RAdGVzdC5vcmc+iQFOBBMBCAA4FiEE6JXydyCXAQnkfMmTuV1W
R67EDnIFAlyNdOECGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQuV1WR67E
DnIchAgAvV5q4/Hktlu3RIgo8KkGksMOS5XhJrr6fZ8bUgqpwL3oEfZ3Se5aS7yN
5M7NT8foB2zK2moBICMYpxBxQoGjxFosv94FqX9+XMiRc2Di6MwLwKkWfu0HoPEi
e701iTo53r6K84TIKNrRsKyg6C/pRqNNwSp1YcvG11eUnG5teZMcb1xsMfx4O2/s
mcrySo0ZjAfYnh2poxf4yy9xTryPrDnaY/EFj+4uBMLH8jG3QQiAH1N6wHhi/vwj
FaaaBtRxcVU/obGDg2LHTVxItv81xzSbLf8JdIGOKjwFed+DjaoSlEzPnuaEZf/M
7mE6fiGbIhFgUlwEGomptZDC1fg3M7kBDQRcjXThAQgAmuSsbRoLfiSoij5CWiP4
UUvhIEt5d4KkMRRvuWXkJo4FWs2tmNWIb1tiXuKhX+puLjP06LwfEyNT1jz75pgO
tSQ0Yz55Hn25CWOcyWF/iIoIjjw3WhQ0a59Ajk8tVdVrTEhlcQ+m7dH1igyMO1vv
iH1eTu+TXqWDF1+oYTZH0iTMYreCNbz2RcFHZQKdWK8GI1DE/qeKLHf+XYGTVQH4
fRnGaX7T5DdnklHKVGi4iILOKn5aofTIg14roS9yfDMK6vmNr7BkzqAe9+WfYC0K
TU3hX1z5SrjnYnBb531MaaCotUEI3DbNeoNsuH3Hx0WLHR1Q55Hh+KAxhMUKTR4P
uwARAQABiQE2BBgBCAAgFiEE6JXydyCXAQnkfMmTuV1WR67EDnIFAlyNdOECGwwA
CgkQuV1WR67EDnKjKwgA3yexUAoTe9sDRKO710MSWhPAn3DZ8qMo8EqmNegG86PO
/mD6BPKo9503pqGGXYoFBcqsmFX07uvy0evCsqO15xuDWwOhNX5fm2LeSsNEkhhC
2wvJVQPdekj9KmOrRRRcr6DlR0Yl7+BJX1+zF8tYwtU4tiY+bCOVRoa1KvTXUwcy
sRTQ9xWguCP8Ai1GyZS0P8lEU0nCS2KrgU/XKQVW7o2OtBiywJbmVCDw15vIq3kN
akRrU5DvYCelUjjzgj+HC3MEE5fV4UsuFLKw3QMmekzFfa6OagRb/FYYZ5ZL+tGI
cf2W57AJOHpgYvxqrY5M1UfKLf8kCYPt3AG0XiD5mw==
=OHyE
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -1,10 +1,39 @@
import QtTest 1.0
import Ubuntu.Test 1.0
import Gpg 1.0
import Pass 1.0
UbuntuTestCase {
name: "GpgTests"
function test_empty_gnuhome() {
Gpg::getListIds().empty()
}
name: "GpgTests"
function initTestCase() {
Pass.gpgSetGpghome("tests/tmp/gnuhome")
}
function test_empty_gnuhome() {
var listKeys = Pass.gpgListAllKeys()
verify(listKeys.length == 0)
}
function test_import_key_form_file_data() {
return [{
"tag": "public1.key",
"path": "tests/unit/assets/public1.key",
"answer": true
}, {
"tag": "private1.key",
"path": "tests/unit/assets/private1.key",
"answer": true
}, {
"tag": "bad path",
"path": "this/is/a/bad/path",
"answer": false
}, {
"tag": "bad key",
"path": "tests/unit/assets/not.key",
"answer": false
}]
}
function test_import_key_form_file(data) {
compare(Pass.gpgImportKeyFromFile(data.path), data.answer)
}
}