Browse Source

Merge pull request #4 from DenioD/chat

Chat
pull/130/head
Strider 4 years ago
committed by GitHub
parent
commit
ae2a65e4ee
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      .gdb_history
  2. 2
      README.md
  3. 8
      application.qrc
  4. 6
      lib/Cargo.lock
  5. 2
      lib/Cargo.toml
  6. 2
      peda-session-SilentDragonLite.txt
  7. BIN
      res/getAddrBlack.png
  8. BIN
      res/getAddrWhite.png
  9. BIN
      res/lock_orange.png
  10. BIN
      res/silentdragonlite_id.qm
  11. 2002
      res/silentdragonlite_id.ts
  12. BIN
      res/unknownBlack.png
  13. BIN
      res/unknownWhite.png
  14. BIN
      res/unkownBlack.png
  15. 7
      res/unlocked.svg
  16. BIN
      res/upload.png
  17. 8
      res/upload.svg
  18. 7
      silentdragon-lite.pro
  19. 40
      src/Chat/Chat.cpp
  20. 48
      src/Crypto/FileEncryption.cpp
  21. 6
      src/Crypto/FileEncryption.h
  22. 60
      src/Crypto/passwd.cpp
  23. 14
      src/Crypto/passwd.h
  24. 9
      src/DataStore/ChatDataStore.cpp
  25. 7
      src/FileSystem/FileSystem.cpp
  26. 4
      src/FileSystem/FileSystem.h
  27. 47
      src/Model/ChatItem.cpp
  28. 11
      src/Model/ChatItem.h
  29. 7
      src/Model/ContactItem.cpp
  30. 5
      src/Model/ContactItem.h
  31. 3
      src/addressbook.cpp
  32. 9
      src/addressbook.h
  33. 273
      src/chatmodel.cpp
  34. 10
      src/chatmodel.h
  35. 118
      src/contactmodel.cpp
  36. 4
      src/contactmodel.h
  37. 33
      src/contactrequest.ui
  38. 118
      src/controller.cpp
  39. 8
      src/controller.h
  40. 121
      src/encryption.ui
  41. 156
      src/hushrequest.ui
  42. 528
      src/mainwindow.cpp
  43. 22
      src/mainwindow.h
  44. 23
      src/mainwindow.ui
  45. 2
      src/memodialog.ui
  46. 197
      src/removeencryption.ui
  47. 52
      src/requestContactDialog.ui
  48. 252
      src/requestdialog.ui
  49. 2
      src/sendtab.cpp
  50. 184
      src/startupencryption.ui

6
.gdb_history

@ -48,3 +48,9 @@ b FileSystem::writeContacts
r
n
q
r
b FileEncryption::encrypt
r
s
n
q

2
README.md

@ -26,7 +26,7 @@ SilentDragonLite does automatic note and utxo management, which means it doesn't
## Compiling from source
* SilentDragonLite is written in C++ 14, and can be compiled with g++/clang++/visual c++.
* It also depends on Qt5, which you can get from [here](https://www.qt.io/download).
* You'll need Rust v1.37 +
* You'll need Rust v1.41 +
## Building on Linux

8
application.qrc

@ -33,12 +33,9 @@
<file>res/add_contact.png</file>
<file>res/notification.png</file>
<file>res/rahmen-message.png</file>
<file>res/upload.png</file>
<file>res/upload.svg</file>
<file>res/message-icon.svg</file>
<file>res/lock.svg</file>
<file>res/lock.png</file>
<file>res/lock_green.png</file>
<file>res/lock_orange.png</file>
<file>res/unlocked.png</file>
<file>res/getAddrWhite.png</file>
<file>res/send-white.png</file>
@ -48,6 +45,8 @@
<file>res/sendBlack.png</file>
<file>res/requestBlack.png</file>
<file>res/addContactBlack.png</file>
<file>res/unknownBlack.png</file>
<file>res/unknownWhite.png</file>
</qresource>
<qresource prefix="/img">
@ -65,6 +64,7 @@
<file>res/silentdragonlite_it.qm</file>
<file>res/silentdragonlite_hr.qm</file>
<file>res/silentdragonlite_fa.qm</file>
<file>res/silentdragonlite_id.qm</file>
</qresource>
<qresource prefix="/css">
<file>res/css/blue.css</file>

6
lib/Cargo.lock

@ -1177,7 +1177,7 @@ version = "0.1.0"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=fb07cae93c706cce929beef98690109e5f2d7592)",
"silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=d196ad938a22810c0b6b4164e6bf8f1db0409763)",
]
[[package]]
@ -1640,7 +1640,7 @@ dependencies = [
[[package]]
name = "silentdragonlitelib"
version = "0.1.0"
source = "git+https://github.com/DenioD/silentdragonlite-cli?rev=fb07cae93c706cce929beef98690109e5f2d7592#fb07cae93c706cce929beef98690109e5f2d7592"
source = "git+https://github.com/DenioD/silentdragonlite-cli?rev=d196ad938a22810c0b6b4164e6bf8f1db0409763#d196ad938a22810c0b6b4164e6bf8f1db0409763"
dependencies = [
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bellman 0.1.0 (git+https://github.com/MyHush/librustzcash.git?rev=1a0204113d487cdaaf183c2967010e5214ff9e37)",
@ -2631,7 +2631,7 @@ dependencies = [
"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35"
"checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0"
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
"checksum silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=fb07cae93c706cce929beef98690109e5f2d7592)" = "<none>"
"checksum silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=d196ad938a22810c0b6b4164e6bf8f1db0409763)" = "<none>"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85"

2
lib/Cargo.toml

@ -11,4 +11,4 @@ crate-type = ["staticlib"]
[dependencies]
libc = "0.2.58"
lazy_static = "1.4.0"
silentdragonlitelib = { git = "https://github.com/DenioD/silentdragonlite-cli", rev = "fb07cae93c706cce929beef98690109e5f2d7592" }
silentdragonlitelib = { git = "https://github.com/DenioD/silentdragonlite-cli", rev = "d196ad938a22810c0b6b4164e6bf8f1db0409763" }

2
peda-session-SilentDragonLite.txt

@ -1,2 +1,2 @@
break FileSystem::writeContacts
break FileEncryption::encrypt

BIN
res/getAddrBlack.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

BIN
res/getAddrWhite.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 12 KiB

BIN
res/lock_orange.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

BIN
res/silentdragonlite_id.qm

Binary file not shown.

2002
res/silentdragonlite_id.ts

File diff suppressed because it is too large

BIN
res/unknownBlack.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
res/unknownWhite.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
res/unkownBlack.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

7
res/unlocked.svg

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg fill="#EB4F38" width="16px" height="16px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"><path d="M4631.2,5015.7c-634.2-57.5-1212.8-212.7-1755.1-475.2c-546.1-264.4-894.8-513.5-1339.3-959.9c-446.4-446.4-676.4-766.4-948.4-1322.1c-231.8-469.4-367.9-914-454.1-1465.8c-46-308.5-46-1032.7,1.9-1341.2c90.1-586.3,239.5-1057.6,488.6-1548.1c254.8-496.3,494.3-822,912-1239.7c438.8-440.7,764.5-674.4,1302.9-938.9c343-168.6,567.1-252.9,915.9-344.9c1452.4-383.2,2981.4-76.6,4209.5,839.2c233.8,176.3,756.8,699.3,933.1,933.1C9909.8-1493,10170.4,202.7,9610.9,1779.6c-168.6,475.2-484.8,1032.7-812.4,1437c-187.8,231.8-609.3,640-837.3,810.5C7286.8,4532.9,6530,4849,5685,4979.3C5491.5,5008.1,4817,5033,4631.2,5015.7z M5483.8,4622.9C7206.3,4450.5,8697,3264.5,9273.7,1605.2C9540,836.9,9593.7-44.5,9419.3-855c-176.3-818.1-615.1-1615.2-1224.3-2222.6c-714.7-716.6-1619-1159.2-2630.7-1293.3c-293.2-38.3-845-38.3-1138.1,0C2906.7-4171.6,1600-3240.4,933.2-1880.1c-320,651.4-461.8,1272.2-461.8,2013.8c0,730,139.9,1331.6,461.8,1990.8C1370.1,3015.4,2102,3747.3,2993,4184.2C3788.1,4571.2,4583.3,4713,5483.8,4622.9z"/><path d="M4589,2237.5c-431.1-103.5-768.3-486.7-814.3-927.4c-13.4-136,9.6-197.3,92-231.8c107.3-44.1,208.8,40.2,208.8,172.4c0,151.4,107.3,373.6,243.3,502c208.8,197.3,513.5,258.7,791.3,162.9c180.1-63.2,385.1-268.2,452.2-452.2c24.9-63.2,34.5-172.4,42.2-406.2l7.7-321.9H4431.9H3249.7l-46-47.9l-47.9-46v-1439v-1438.9l47.9-46l46-47.9h1592.2h1592.2l46,47.9l47.9,46v1438.9v1439l-47.9,46c-44.1,46-55.6,47.9-302.7,47.9h-258.7l-9.6,341c-7.7,287.4-15.3,358.3-49.8,457.9c-97.7,272.1-298.9,498.2-548,618.9C5068,2270.1,4832.3,2296.9,4589,2237.5z M6221.5-797.5v-1226.2H4841.9H3462.4v1226.2V428.8h1379.5h1379.5V-797.5z"/><path d="M4688.6,97.3c-36.4-11.5-111.1-65.2-162.9-118.8c-136-134.1-174.4-279.7-120.7-454.1c26.8-92,145.6-231.8,226.1-264.4l57.5-23v-402.4c0-398.5,0-400.4,47.9-446.4c61.3-63.2,149.4-63.2,210.8,0c47.9,46,47.9,47.9,47.9,446.4V-763l57.5,23c80.5,32.6,199.3,172.4,226.1,264.4c53.6,174.4,15.3,320-120.7,454.1C5023.9,114.5,4866.8,152.9,4688.6,97.3z M4947.3-232.3c95.8-93.9,28.7-258.7-105.4-258.7c-36.4,0-76.6,17.3-105.4,47.9c-30.7,28.7-47.9,69-47.9,105.4c0,36.4,17.2,76.6,47.9,105.4c28.7,30.7,69,47.9,105.4,47.9S4918.6-201.6,4947.3-232.3z"/></g></g>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

BIN
res/upload.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

8
res/upload.svg

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 218.8 283.5" style="enable-background:new 0 0 218.8 283.5;" xml:space="preserve">
<g>
<path d="M109.4,0L0,109.4h62.5v93.8h93.8v-93.8h62.5L109.4,0z M0,234.4v31.3h218.8v-31.3H0z M0,234.4"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 476 B

7
silentdragon-lite.pro

@ -83,7 +83,8 @@ SOURCES += \
src/Chat/Helper/ChatIDGenerator.cpp \
src/Chat/Chat.cpp \
src/FileSystem/FileSystem.cpp \
src/Crypto/FileEncryption.cpp
src/Crypto/FileEncryption.cpp \
src/Crypto/passwd.cpp
HEADERS += \
src/firsttimewizard.h \
@ -121,6 +122,7 @@ HEADERS += \
FORMS += \
src/contactrequest.ui \
src/encryption.ui \
src/hushrequest.ui \
src/mainwindow.ui \
src/migration.ui \
src/newseed.ui \
@ -132,6 +134,7 @@ FORMS += \
src/confirm.ui \
src/privkey.ui \
src/memodialog.ui \
src/startupencryption.ui \
src/viewalladdresses.ui \
src/connection.ui \
src/addressbook.ui \
@ -141,6 +144,7 @@ FORMS += \
src/requestContactDialog.ui \
src/newrecurring.ui \
src/requestdialog.ui \
src/removeencryption.ui \
src/recurringmultiple.ui \
src/chatbubbleme.ui \
src/chatbubblepartner.ui
@ -155,6 +159,7 @@ TRANSLATIONS = res/silentdragonlite_es.ts \
res/silentdragonlite_hr.ts \
res/silentdragonlite_sr.ts \
res/silentdragonlite_fa.ts \
res/silentdragonlite_id.ts \
res/silentdragonlite_tr.ts
include(singleapplication/singleapplication.pri)

40
src/Chat/Chat.cpp

@ -7,43 +7,43 @@
Chat::Chat() {}
ChatMemoEdit::ChatMemoEdit(QWidget* parent) : QTextEdit(parent) {
QObject::connect(this, &QTextEdit::textChanged, this, &ChatMemoEdit::updateDisplay);
QObject::connect(this, &QTextEdit::textChanged, this, &ChatMemoEdit::updateDisplayChat);
}
void ChatMemoEdit::updateDisplay() {
void ChatMemoEdit::updateDisplayChat() {
QString txt = this->toPlainText();
if (lenDisplayLabel)
lenDisplayLabel->setText(QString::number(txt.toUtf8().size()) + "/" + QString::number(maxlen));
if (lenDisplayLabelchat)
lenDisplayLabelchat->setText(QString::number(txt.toUtf8().size()) + "/" + QString::number(maxlenchat));
if (txt.toUtf8().size() <= maxlen) {
if (txt.toUtf8().size() <= maxlenchat) {
// Everything is fine
if (sendChatButton)
sendChatButton->setEnabled(true);
if (lenDisplayLabel)
lenDisplayLabel->setStyleSheet("");
if (lenDisplayLabelchat)
lenDisplayLabelchat->setStyleSheet("");
}
else {
// Overweight
if (sendChatButton)
sendChatButton->setEnabled(false);
if (lenDisplayLabel)
lenDisplayLabel->setStyleSheet("color: red;");
if (lenDisplayLabelchat)
lenDisplayLabelchat->setStyleSheet("color: red;");
}
}
void ChatMemoEdit::setMaxLen(int len) {
this->maxlen = len;
updateDisplay();
void ChatMemoEdit::setMaxLenChat(int len) {
this->maxlenchat = len;
updateDisplayChat();
}
void ChatMemoEdit::SetSendChatButton(QPushButton* button) {
this->sendChatButton = button;
}
void ChatMemoEdit::setLenDisplayLabel(QLabel* label) {
this->lenDisplayLabel = label;
void ChatMemoEdit::setLenDisplayLabelChat(QLabel* label) {
this->lenDisplayLabelchat = label;
}
void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label)
@ -55,7 +55,6 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label)
{
for (auto &c : DataStore::getChatDataStore()->getAllMemos())
{
//////Render only Memos for selected contacts. Do not render empty Memos //// Render only memos where cid=cid
if (
(p.getName() == ui->contactNameMemo->text().trimmed()) &&
@ -67,7 +66,8 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label)
Items->setData(OUTGOING, Qt::UserRole + 1);
chat->appendRow(Items);
ui->listChat->setModel(chat);
ui->listChat->setModel(chat);
}
else
@ -86,6 +86,8 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label)
Items1->setData(INCOMING, Qt::UserRole + 1);
chat->appendRow(Items1);
ui->listChat->setModel(chat);
}
else
{
@ -93,5 +95,7 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label)
ui->listChat->setModel(chat);
}
}
}
}
}
}

48
src/Crypto/FileEncryption.cpp

@ -7,42 +7,48 @@ void FileEncryption::showConfig()
int FileEncryption::encrypt(QString target_file, QString source_file, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES])
{
unsigned char buf_in[FILEENCRYPTION_CHUNK_SIZE];
unsigned char buf_out[FILEENCRYPTION_CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES];
unsigned char plain_data[FILEENCRYPTION_CHUNK_SIZE];
unsigned char cipher_data[FILEENCRYPTION_CHUNK_SIZE + crypto_secretstream_xchacha20poly1305_ABYTES];
unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
crypto_secretstream_xchacha20poly1305_state st;
FILE *fp_t, *fp_s;
unsigned long long out_len;
crypto_secretstream_xchacha20poly1305_state state;
FILE *target, *source;
unsigned long long cipher_len;
size_t rlen;
int eof;
unsigned char tag;
fp_s = fopen(source_file.toStdString().c_str(), "rb");
fp_t = fopen(target_file.toStdString().c_str(), "wb");
crypto_secretstream_xchacha20poly1305_init_push(&st, header, key);
fwrite(header, 1, sizeof header, fp_t);
if(!FileEncryption::exists(source_file.toStdString()))
{
qDebug() << "File not exits" << source_file;
return -1;
}
source = fopen(source_file.toStdString().c_str(), "rb");
target = fopen(target_file.toStdString().c_str(), "wb");
crypto_secretstream_xchacha20poly1305_init_push(&state, header, key);
fwrite(header, 1, sizeof header, target);
do
{
rlen = fread(buf_in, 1, sizeof buf_in, fp_s);
eof = feof(fp_s);
rlen = fread(plain_data, 1, sizeof plain_data, source);
eof = feof(source);
tag = eof ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0;
crypto_secretstream_xchacha20poly1305_push(
&st,
buf_out,
&out_len,
buf_in,
&state,
cipher_data,
&cipher_len,
plain_data,
rlen,
NULL,
0,
tag
);
fwrite(buf_out, 1, (size_t) out_len, fp_t);
fwrite(cipher_data, 1, (size_t) cipher_len, target);
}
while (! eof);
fclose(fp_t);
fclose(fp_s);
fclose(target);
fclose(source);
return 0;
}
@ -59,6 +65,12 @@ int FileEncryption::decrypt(QString target_file, QString source_file, const unsi
int ret = -1;
unsigned char tag;
if(!FileEncryption::exists(source_file.toStdString()))
{
qDebug() << "File not exits" << source_file;
return -1;
}
fp_s = fopen(source_file.toStdString().c_str(), "rb");
fp_t = fopen(target_file.toStdString().c_str(), "wb");
fread(header, 1, sizeof header, fp_s);

6
src/Crypto/FileEncryption.h

@ -3,11 +3,17 @@
#include <stdio.h>
#include <sodium.h>
#include <QString>
#include <fstream>
#define FILEENCRYPTION_CHUNK_SIZE 4096
class FileEncryption
{
private:
inline static bool exists (const std::string& name) {
std::ifstream f(name.c_str());
return f.good();
}
public:
static void showConfig();
static int encrypt(QString target_file, QString source_file, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]);

60
src/Crypto/passwd.cpp

@ -0,0 +1,60 @@
#include "passwd.h"
void PASSWD::show_hex_buff(unsigned char buf[])
{
int i;
for (uint8_t i=0; i < crypto_secretstream_xchacha20poly1305_KEYBYTES; i++)
printf("%02X ", buf[i]);
printf("\n");
}
const unsigned char* PASSWD::key(QString password)
{
int length = password.length();
char *sequence = NULL;
sequence = new char[length+1];
strncpy(sequence, password.toLocal8Bit(), length +1);
#define MESSAGE ((const unsigned char *) sequence)
#define MESSAGE_LEN length
unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES];
crypto_hash_sha256(hash, MESSAGE, MESSAGE_LEN);
qDebug()<<"Generating SaltHash from password: " <<sequence;
/////////we use the Hash of the Password as Salt, not perfect but still a good solution.
#define PASSWORD sequence
#define KEY_LEN crypto_box_SEEDBYTES
unsigned char key[KEY_LEN];
if (crypto_pwhash
(key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */
}
qDebug()<<"Generating cryptographic key from password: " <<sequence;
// crypto_generichash(blacke2hash, sizeof hash, MESSAGE, MESSAGE_LEN, NULL, 0);
//for(uint8_t i = 0; i < crypto_secretstream_xchacha20poly1305_KEYBYTES/2; i++)
// hash[i] = blacke2hash[i];
// for(uint8_t i = crypto_secretstream_xchacha20poly1305_KEYBYTES/2; i < crypto_secretstream_xchacha20poly1305_KEYBYTES; i++)
// hash[i] = sha256hash[i];
// delete[] sha256hash;
//delete[] blacke2hash;
qDebug()<<"secret key generated:\n";
PASSWD::show_hex_buff(key);
return key;
}

14
src/Crypto/passwd.h

@ -0,0 +1,14 @@
#ifndef PASSWD_H
#define PASSWD_H
#include <stdio.h>
#include <sodium.h>
#include <QString>
class PASSWD
{
public:
static void show_hex_buff(unsigned char buf[]);
static const unsigned char* key(QString);
};
#endif

9
src/DataStore/ChatDataStore.cpp

@ -3,6 +3,8 @@
#include "ChatDataStore.h"
#include "addressbook.h"
#include "chatmodel.h"
ChatDataStore* ChatDataStore::getInstance()
{
@ -53,15 +55,14 @@ std::map<QString, ChatItem> ChatDataStore::getAllNewContactRequests()
{
std::map<QString, ChatItem> filteredItems;
for(auto &c: this->data)
for(auto &c: this->data)
{
if (
(c.second.isOutgoing() == false) &&
(c.second.getType() == "Cont") &&
(c.second.getContact() == "")
(c.second.isContact() == false)
)
{
filteredItems[c.first] = c.second;
}

7
src/FileSystem/FileSystem.cpp

@ -1,7 +1,11 @@
#include "FileSystem.h"
// Copyright 2019-2020 The Hush developers
// GPLv3
#include "FileSystem.h"
#include <QString>
#include <QList>
#include "../Crypto/passwd.h"
#include "addressbook.h"
FileSystem::FileSystem()
{
@ -98,7 +102,6 @@ QList<ContactItem> FileSystem::readContactsOldFormat(QString file)
qDebug() << "Detected old addressbook format";
QList<QList<QString>> stuff;
in >> stuff;
//qDebug() << "Stuff: " << stuff;
for (int i=0; i < stuff.size(); i++)
{
ContactItem contact = ContactItem(stuff[i][0],stuff[i][1], stuff[i][2], stuff[i][3],stuff[i][4]);

4
src/FileSystem/FileSystem.h

@ -1,3 +1,5 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
@ -13,7 +15,7 @@ class FileSystem
static bool instanced;
static FileSystem* instance;
FileSystem();
public:
static FileSystem* getInstance();
QList<ContactItem> readContacts(QString file);

47
src/Model/ChatItem.cpp

@ -5,7 +5,7 @@
ChatItem::ChatItem() {}
ChatItem::ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, int confirmations)
ChatItem::ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, int confirmations, bool notarize, bool iscontact)
{
_timestamp = timestamp;
_address = address;
@ -17,9 +17,11 @@ ChatItem::ChatItem(long timestamp, QString address, QString contact, QString mem
_txid = txid;
_confirmations = confirmations;
_outgoing = false;
_notarize = notarize;
_iscontact = iscontact;
}
ChatItem::ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, int confirmations, bool outgoing)
ChatItem::ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, int confirmations, bool outgoing, bool notarize, bool iscontact)
{
_timestamp = timestamp;
_address = address;
@ -31,6 +33,9 @@ ChatItem::ChatItem(long timestamp, QString address, QString contact, QString mem
_txid = txid;
_confirmations = confirmations;
_outgoing = outgoing;
_notarize = notarize;
_iscontact = iscontact;
}
long ChatItem::getTimestamp()
@ -81,6 +86,16 @@ bool ChatItem::isOutgoing()
return _outgoing;
}
bool ChatItem::isNotarized()
{
return _notarize;
}
bool ChatItem::isContact()
{
return _iscontact;
}
void ChatItem::setTimestamp(long timestamp)
{
_timestamp = timestamp;
@ -128,6 +143,15 @@ void ChatItem::toggleOutgo()
{
_outgoing = true;
}
void ChatItem::notarized()
{
_notarize = false;
}
void ChatItem::contact(bool iscontact)
{
_iscontact = iscontact;
}
QString ChatItem::toChatLine()
@ -136,14 +160,25 @@ QString ChatItem::toChatLine()
QString lock;
myDateTime.setTime_t(_timestamp);
if (_confirmations == 0){
if (_notarize == true)
{
lock = "<b> <img src=':/icons/res/lock_orange.png'><b>";
}else{
lock = "<b> <img src=':/icons/res/unlocked.png'><b>";
}else{
}
if ((_confirmations > 0) && (_notarize == false))
{
lock = "<b> <img src=':/icons/res/lock_green.png'><b>";
}
}
qDebug()<<_notarize;
QString line = QString("<small>") + myDateTime.toString("dd.MM.yyyy hh:mm");
line += QString(lock) + QString("</small>");
line += QString("<p>") + _memo.toHtmlEscaped() + QString("</p>");

11
src/Model/ChatItem.h

@ -20,11 +20,13 @@ class ChatItem
QString _txid;
int _confirmations;
bool _outgoing = false;
bool _notarize = false;
bool _iscontact = false;
public:
ChatItem();
ChatItem(long timestamp, QString address, QString contact, QString memo,QString requestZaddr, QString type, QString cid, QString txid, int confirmations);
ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, int confirmations, bool outgoing);
ChatItem(long timestamp, QString address, QString contact, QString memo,QString requestZaddr, QString type, QString cid, QString txid, int confirmations, bool notarize, bool iscontact);
ChatItem(long timestamp, QString address, QString contact, QString memo, QString requestZaddr, QString type, QString cid, QString txid, int confirmations, bool outgoing, bool notarize, bool iscontact);
long getTimestamp();
QString getAddress();
QString getContact();
@ -35,6 +37,9 @@ class ChatItem
QString getTxid();
int getConfirmations();
bool isOutgoing();
bool isdouble();
bool isNotarized();
bool isContact();
void setTimestamp(long timestamp);
void setAddress(QString address);
void setContact(QString contact);
@ -45,6 +50,8 @@ class ChatItem
void setTxid(QString txid);
void setConfirmations(int confirmations);
void toggleOutgo();
void notarized();
void contact(bool iscontact);
QString toChatLine();
json toJson();
~ChatItem();

7
src/Model/ContactItem.cpp

@ -1,4 +1,9 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#include "ContactItem.h"
#include "chatmodel.h"
#include "Model/ChatItem.h"
#include "controller.h"
ContactItem::ContactItem() {}
@ -8,7 +13,7 @@ ContactItem::ContactItem(QString name, QString partnerAddress, QString myAddress
_myAddress = myAddress;
_partnerAddress = partnerAddress;
_cid = cid;
_avatar = avatar;
_avatar = avatar;
}
QString ContactItem::getName() const

5
src/Model/ContactItem.h

@ -1,8 +1,11 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#ifndef CONTACTITEM_H
#define CONTACTITEM_H
#include <vector>
#include <QString>
#include "mainwindow.h"
using json = nlohmann::json;
class ContactItem
@ -13,7 +16,7 @@ private:
QString _name;
QString _cid;
QString _avatar;
public:
ContactItem();
ContactItem(QString name, QString partnerAddress, QString myAddress, QString cid, QString avatar);

3
src/addressbook.cpp

@ -40,7 +40,10 @@ void AddressBookModel::loadData()
QSettings().value(
"addresstablegeometry"
).toByteArray()
);
}
void AddressBookModel::addNewLabel(QString label, QString addr, QString myAddr, QString cid, QString avatar)

9
src/addressbook.h

@ -23,6 +23,7 @@ public:
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
private:
@ -32,7 +33,8 @@ private:
QTableView* parent;
//QList<QPair<QString, QString>> labels;
QList<ContactItem> labels;
QStringList headers;
QStringList headers;
};
class AddressBook {
@ -63,6 +65,10 @@ public:
QString get_avatar_name();
void set_avatar_name(QString avatar_name);
@ -76,6 +82,7 @@ private:
QString writeableFile();
QList<ContactItem> allLabels;
static AddressBook* instance;
};

273
src/chatmodel.cpp

@ -8,7 +8,6 @@
#include "ui_mainwindow.h"
#include "ui_requestContactDialog.h"
#include "addressbook.h"
#include "ui_memodialog.h"
#include "ui_contactrequest.h"
#include <QtWidgets>
#include <QUuid>
@ -54,7 +53,6 @@ void ChatModel::clear()
void ChatModel::addMessage(ChatItem item)
{
QString key = ChatIDGenerator::getInstance()->generateID(item); //this->generateChatItemID(item);
// qDebug() << "inserting chatitem with id: " << key;
this->chatItems[key] = item;
}
@ -74,8 +72,26 @@ void ChatModel::showMessages()
}
void ChatModel::addAddressbylabel(QString address, QString label)
{
this->AddressbyLabelMap[address] = label;
}
QString ChatModel::Addressbylabel(QString address)
{
for(auto& pair : this->AddressbyLabelMap)
{
}
if(this->AddressbyLabelMap.count(address) > 0)
{
return this->AddressbyLabelMap[address];
}
return QString("0xdeadbeef");
}
void MainWindow::renderContactRequest(){
Ui_requestDialog requestContact;
@ -83,27 +99,53 @@ void MainWindow::renderContactRequest(){
requestContact.setupUi(&dialog);
Settings::saveRestore(&dialog);
QString icon;
auto theme = Settings::getInstance()->get_theme_name();
if (theme == "dark" || theme == "midnight") {
icon = ":/icons/res/unknownWhite.png";
}else{
icon = ":/icons/res/unknownBlack.png";
}
QPixmap unknownWhite(icon);
QIcon addnewAddrIcon(unknownWhite);
QStandardItemModel* contactRequest = new QStandardItemModel();
for (auto &c : DataStore::getChatDataStore()->getAllNewContactRequests())
{
QStandardItem* Items = new QStandardItem(c.second.getAddress());
QStandardItem* Items = new QStandardItem(QString("Unknown Sender"));
contactRequest->appendRow(Items);
requestContact.requestContact->setModel(contactRequest);
Items->setData(QIcon(addnewAddrIcon),Qt::DecorationRole);
requestContact.requestContact->setIconSize(QSize(40,50));
requestContact.requestContact->setUniformItemSizes(true);
requestContact.requestContact->show();
requestContact.zaddrnew->setVisible(false);
requestContact.zaddrnew->setText(c.second.getAddress());
}
QStandardItemModel* contactRequestOld = new QStandardItemModel();
for (auto &p : AddressBook::getInstance()->getAllAddressLabels())
for (auto &c : DataStore::getChatDataStore()->getAllOldContactRequests())
{
if (p.getPartnerAddress() == c.second.getRequestZaddr())
{
QStandardItem* Items = new QStandardItem(c.second.getAddress());
QStandardItem* Items = new QStandardItem(p.getName());
contactRequestOld->appendRow(Items);
requestContact.requestContactOld->setModel(contactRequestOld);
requestContact.zaddrold->setVisible(false);
requestContact.zaddrold->setText(c.second.getAddress());
requestContact.requestContactOld->show();
}else{}
}
@ -116,7 +158,7 @@ void MainWindow::renderContactRequest(){
QString label_contact = index.data(Qt::DisplayRole).toString();
QStandardItemModel* contactMemo = new QStandardItemModel();
if ((c.second.isOutgoing() == false) && (label_contact == c.second.getAddress()) && (c.second.getType() != "Cont"))
if ((c.second.isOutgoing() == false) && (requestContact.zaddrnew->text() == c.second.getAddress()) && (c.second.getType() != "Cont"))
{
@ -139,11 +181,11 @@ void MainWindow::renderContactRequest(){
QObject::connect(requestContact.requestContactOld, &QTableView::clicked, [&] () {
for (auto &c : DataStore::getChatDataStore()->getAllRawChatItems()){
QModelIndex index = requestContact.requestContactOld->currentIndex();
QString label_contactold = index.data(Qt::DisplayRole).toString();
/* QModelIndex index = requestContact.requestContactOld->currentIndex();
QString label_contactold = index.data(Qt::DisplayRole).toString();*/
QStandardItemModel* contactMemo = new QStandardItemModel();
if ((c.second.isOutgoing() == false) && (label_contactold == c.second.getAddress()) && (c.second.getType() != "Cont"))
if ((c.second.isOutgoing() == false) && (requestContact.zaddrold->text() == c.second.getAddress()) && (c.second.getType() != "Cont"))
{
@ -220,6 +262,11 @@ void ChatModel::addrequestZaddr(QString tx, QString requestZaddr)
this->requestZaddrMap[tx] = requestZaddr;
}
void ChatModel::addconfirmations(QString tx, int confirmation)
{
this->confirmationsMap[tx] = confirmation;
}
QString ChatModel::getCidByTx(QString tx)
{
for(auto& pair : this->cidMap)
@ -235,6 +282,21 @@ QString ChatModel::getCidByTx(QString tx)
return QString("0xdeadbeef");
}
QString ChatModel::getConfirmationByTx(QString tx)
{
for(auto& pair : this->confirmationsMap)
{
}
if(this->confirmationsMap.count(tx) > 0)
{
return this->confirmationsMap[tx];
}
return QString("0xdeadbeef");
}
QString ChatModel::getrequestZaddrByTx(QString tx)
{
for(auto& pair : this->requestZaddrMap)
@ -260,6 +322,11 @@ void ChatModel::killrequestZaddrCache()
this->requestZaddrMap.clear();
}
void ChatModel::killConfirmationCache()
{
this->confirmationsMap.clear();
}
QString MainWindow::createHeaderMemo(QString type, QString cid, QString zaddr, int version=0, int headerNumber=1)
{
@ -334,14 +401,12 @@ void MainWindow::sendChat() {
// Create a Tx from the values on the send tab. Note that this Tx object
// might not be valid yet.
// Memos can only be used with zAddrs. So check that first
// for(auto &c : AddressBook::getInstance()->getAllAddressLabels())
QString Name = ui->contactNameMemo->text();
int sizename = Name.size();
qDebug()<< sizename;
if (ui->contactNameMemo->text().trimmed().isEmpty() || ui->memoTxtChat->toPlainText().trimmed().isEmpty()) {
// auto addr = "";
// if (! Settings::isZAddress(AddressBook::addressFromAddressLabel(addr->text()))) {
QMessageBox msg(QMessageBox::Critical, tr("You have to select a contact and insert a Memo"),
tr("You have selected no Contact from Contactlist,\n") + tr("\nor your Memo is empty"),
QMessageBox::Ok, this);
@ -350,6 +415,20 @@ void MainWindow::sendChat() {
return;
}
int max = 512;
QString chattext = ui->memoTxtChat->toPlainText();
int size = chattext.size();
if (size > max){
QMessageBox msg(QMessageBox::Critical, tr("Your Message is too long"),
tr("You can only write messages with 512 character maximum \n") + tr("\n Please reduce your message to 512 character."),
QMessageBox::Ok, this);
msg.exec();
return;
}
Tx tx = createTxFromChatPage();
QString error = doSendChatTxValidations(tx);
@ -384,10 +463,11 @@ void MainWindow::sendChat() {
}
connD->status->setText(tr("Please wait..."));
connD->statusDetail->setText(tr("Your Message will be send"));
connD->statusDetail->setText(tr("Your Message will be sent"));
d->show();
ui->memoTxtChat->clear();
// And send the Tx
rpc->executeTransaction(tx,
@ -396,6 +476,7 @@ void MainWindow::sendChat() {
connD->status->setText(tr("Done!"));
connD->statusDetail->setText(txid);
QTimer::singleShot(1000, [=]() {
d->accept();
@ -406,7 +487,7 @@ void MainWindow::sendChat() {
});
// Force a UI update so we get the unconfirmed Tx
// rpc->refresh(true);
rpc->refresh(true);
ui->memoTxtChat->clear();
},
@ -425,6 +506,8 @@ void MainWindow::sendChat() {
QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
}
);
// rpc->refresh(true);
}
QString MainWindow::doSendChatTxValidations(Tx tx) {
@ -450,7 +533,7 @@ QString MainWindow::doSendChatTxValidations(Tx tx) {
auto available = rpc->getModel()->getAvailableBalance();
if (available < total) {
return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 3 confirmations before they can be spent")
return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent")
.arg(available.toDecimalhushString(), total.toDecimalhushString());
}
@ -499,7 +582,7 @@ void::MainWindow::addContact()
});
QObject::connect(request.sendRequestButton, &QPushButton::clicked, this, &MainWindow::saveandsendContact);
QObject::connect(request.onlyAdd, &QPushButton::clicked, this, &MainWindow::saveContact);
// QObject::connect(request.onlyAdd, &QPushButton::clicked, this, &MainWindow::saveContact);
dialog.exec();
@ -510,96 +593,7 @@ void::MainWindow::addContact()
void MainWindow::saveandsendContact()
{
this->ContactRequest();
QString addr = contactRequest.getReceiverAddress();
QString newLabel = contactRequest.getLabel();
QString myAddr = contactRequest.getSenderAddress();
QString cid = contactRequest.getCid();
QString avatar = contactRequest.getAvatar();
contactRequest.clear();
if (addr.isEmpty() || newLabel.isEmpty())
{
QMessageBox::critical(
this,
QObject::tr("Address or Label Error"),
QObject::tr("Address or Label cannot be empty"),
QMessageBox::Ok
);
return;
}
// Test if address is valid.
if (!Settings::isValidAddress(addr))
{
QMessageBox::critical(
this,
QObject::tr("Address Format Error"),
QObject::tr("%1 doesn't seem to be a valid hush address.").arg(addr),
QMessageBox::Ok
);
return;
}
///////Todo: Test if label allready exist!
////// Success, so show it
AddressBook::getInstance()->addAddressLabel(newLabel, addr, myAddr, cid, avatar);
QMessageBox::information(
this,
QObject::tr("Added Contact"),
QObject::tr("successfully added your new contact").arg(newLabel),
QMessageBox::Ok
);
return;
}
void MainWindow::saveContact()
{
QString addr = contactRequest.getReceiverAddress();
QString newLabel = contactRequest.getLabel();
QString myAddr = contactRequest.getSenderAddress();
QString cid = contactRequest.getCid();
QString avatar = contactRequest.getAvatar();
if (addr.isEmpty() || newLabel.isEmpty())
{
QMessageBox::critical(
this,
QObject::tr("Address or Label Error"),
QObject::tr("Address or Label cannot be empty"),
QMessageBox::Ok
);
return;
}
// Test if address is valid.
if (!Settings::isValidAddress(addr))
{
QMessageBox::critical(
this,
QObject::tr("Address Format Error"),
QObject::tr("%1 doesn't seem to be a valid hush address.").arg(addr),
QMessageBox::Ok
);
return;
}
///////Todo: Test if label allready exist!
////// Success, so show it
AddressBook::getInstance()->addAddressLabel(newLabel, addr, myAddr, cid, avatar);
QMessageBox::information(
this,
QObject::tr("Added Contact"),
QObject::tr("successfully added your new contact").arg(newLabel),
QMessageBox::Ok
);
return;
}
// Create a Tx for a contact Request
@ -647,6 +641,22 @@ void MainWindow::ContactRequest() {
return;
}
int max = 512;
QString chattext = contactRequest.getMemo();;
int size = chattext.size();
if (size > max){
// auto addr = "";
// if (! Settings::isZAddress(AddressBook::addressFromAddressLabel(addr->text()))) {
QMessageBox msg(QMessageBox::Critical, tr("Your Message is too long"),
tr("You can only write messages with 512 character maximum \n") + tr("\n Please reduce your message to 512 character."),
QMessageBox::Ok, this);
msg.exec();
return;
}
Tx tx = createTxForSafeContactRequest();
QString error = doSendRequestTxValidations(tx);
@ -681,7 +691,7 @@ void MainWindow::ContactRequest() {
}
connD->status->setText(tr("Please wait..."));
connD->statusDetail->setText(tr("Your Contact will be send"));
connD->statusDetail->setText(tr("Your contact request will be sent"));
d->show();
ui->memoTxtChat->clear();
@ -701,7 +711,46 @@ void MainWindow::ContactRequest() {
delete d;
});
QString addr = contactRequest.getReceiverAddress();
QString newLabel = contactRequest.getLabel();
QString myAddr = contactRequest.getSenderAddress();
QString cid = contactRequest.getCid();
QString avatar = contactRequest.getAvatar();
if (addr.isEmpty() || newLabel.isEmpty())
{
QMessageBox::critical(
this,
QObject::tr("Address or Label Error"),
QObject::tr("Address or Label cannot be empty"),
QMessageBox::Ok
);
return;
}
// Test if address is valid.
if (!Settings::isValidAddress(addr))
{
QMessageBox::critical(
this,
QObject::tr("Address Format Error"),
QObject::tr("%1 doesn't seem to be a valid hush address.").arg(addr),
QMessageBox::Ok
);
return;
}
///////Todo: Test if label allready exist!
////// Success, so show it
AddressBook::getInstance()->addAddressLabel(newLabel, addr, myAddr, cid, avatar);
QMessageBox::information(
this,
QObject::tr("Added Contact"),
QObject::tr("successfully added your new contact").arg(newLabel),
QMessageBox::Ok
);
return;
// Force a UI update so we get the unconfirmed Tx
// rpc->refresh(true);
ui->memoTxtChat->clear();
@ -750,9 +799,11 @@ QString MainWindow::doSendRequestTxValidations(Tx tx) {
auto available = rpc->getModel()->getAvailableBalance();
if (available < total) {
return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 5 confirmations before they can be spent")
return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent")
.arg(available.toDecimalhushString(), total.toDecimalhushString());
}
return "";
}

10
src/chatmodel.h

@ -20,6 +20,7 @@
#include "Chat/Helper/ChatDelegator.h"
#include "Chat/Helper/ChatIDGenerator.h"
namespace Ui {
class MainWindow;
}
@ -32,7 +33,9 @@ class ChatModel
MainWindow* main;
std::map<QString, QString> cidMap;
std::map<QString, QString> requestZaddrMap;
std::map<QString, QString> confirmationsMap;
std::map<int, std::tuple<QString, QString, QString>> sendrequestMap;
std::map<QString, QString> AddressbyLabelMap;
public:
ChatModel() {};
@ -45,16 +48,21 @@ class ChatModel
void triggerRequest();
void showMessages();
void clear();
void addAddressbylabel(QString addr, QString label);
void addMessage(ChatItem item);
void addMessage(QString timestamp, ChatItem item);
void addCid(QString tx, QString cid);
void addrequestZaddr(QString tx, QString requestZaddr);
void addconfirmations(QString tx, int confirmation);
void addSendRequest(int i, QString myAddr, QString cid, QString addr );
QString getCidByTx(QString tx);
QString getrequestZaddrByTx(QString tx);
QString getConfirmationByTx(QString tx);
QString Addressbylabel(QString addr);
void killCidCache();
void killConfirmationCache();
void killrequestZaddrCache();
};
#endif

118
src/contactmodel.cpp

@ -5,11 +5,18 @@
#include "addressbook.h"
#include "mainwindow.h"
#include "chatmodel.h"
#include "requestdialog.h"
#include "ui_requestdialog.h"
#include "ui_hushrequest.h"
#include "settings.h"
#include "controller.h"
void ContactModel::renderContactList(QListView* view)
{
QStandardItemModel* contact = new QStandardItemModel();
for(auto &c : AddressBook::getInstance()->getAllAddressLabels())
{
@ -18,14 +25,119 @@ void ContactModel::renderContactList(QListView* view)
QStandardItem* Items1 = new QStandardItem(c.getName());
Items1->setData(QIcon(avatar),Qt::DecorationRole);
contact->appendRow(Items1);
view->setModel(contact);
view->setIconSize(QSize(60,70));
view->setUniformItemSizes(true);
view->setDragDropMode(QAbstractItemView::DropOnly);
view->show();
}
}
void MainWindow::showRequesthush() {
Ui_hushrequest req;
QDialog d(this);
req.setupUi(&d);
Settings::saveRestore(&d);
QString label = ui->contactNameMemo->text();
for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
{
if (p.getName() == label)
{
QString addr = p.getPartnerAddress();
QString myzaddr = p.getMyAddress();
req.txtFrom->setText(addr);
req.lblAddressInfo->setText(myzaddr);
// Amount textbox
req.txtAmount->setValidator(this->getAmountValidator());
QObject::connect(req.txtAmount, &QLineEdit::textChanged, [=] (auto text) {
CAmount amount = CAmount::fromDecimalString(text);
if (Settings::getInstance()->get_currency_name() == "USD") {
req.txtAmountUSD->setText(amount.toDecimalUSDString());
} else if (Settings::getInstance()->get_currency_name() == "EUR") {
req.txtAmountUSD->setText(amount.toDecimalEURString());
} else if (Settings::getInstance()->get_currency_name() == "BTC") {
req.txtAmountUSD->setText(amount.toDecimalBTCString());
} else if (Settings::getInstance()->get_currency_name() == "CNY") {
req.txtAmountUSD->setText(amount.toDecimalCNYString());
} else if (Settings::getInstance()->get_currency_name() == "RUB") {
req.txtAmountUSD->setText(amount.toDecimalRUBString());
} else if (Settings::getInstance()->get_currency_name() == "CAD") {
req.txtAmountUSD->setText(amount.toDecimalCADString());
} else if (Settings::getInstance()->get_currency_name() == "SGD") {
req.txtAmountUSD->setText(amount.toDecimalSGDString());
} else if (Settings::getInstance()->get_currency_name() == "CHF") {
req.txtAmountUSD->setText(amount.toDecimalCHFString());
} else if (Settings::getInstance()->get_currency_name() == "INR") {
req.txtAmountUSD->setText(amount.toDecimalINRString());
} else if (Settings::getInstance()->get_currency_name() == "GBP") {
req.txtAmountUSD->setText(amount.toDecimalGBPString());
} else if (Settings::getInstance()->get_currency_name() == "AUD") {
req.txtAmountUSD->setText(amount.toDecimalBTCString());
}
});
CAmount amount = CAmount::fromDecimalString(req.txtAmount->text());
if (Settings::getInstance()->get_currency_name() == "USD") {
req.txtAmountUSD->setText(amount.toDecimalUSDString());
} else if (Settings::getInstance()->get_currency_name() == "EUR") {
req.txtAmountUSD->setText(amount.toDecimalEURString());
} else if (Settings::getInstance()->get_currency_name() == "BTC") {
req.txtAmountUSD->setText(amount.toDecimalBTCString());
} else if (Settings::getInstance()->get_currency_name() == "CNY") {
req.txtAmountUSD->setText(amount.toDecimalCNYString());
} else if (Settings::getInstance()->get_currency_name() == "RUB") {
req.txtAmountUSD->setText(amount.toDecimalRUBString());
} else if (Settings::getInstance()->get_currency_name() == "CAD") {
req.txtAmountUSD->setText(amount.toDecimalCADString());
} else if (Settings::getInstance()->get_currency_name() == "SGD") {
req.txtAmountUSD->setText(amount.toDecimalSGDString());
} else if (Settings::getInstance()->get_currency_name() == "CHF") {
req.txtAmountUSD->setText(amount.toDecimalCHFString());
} else if (Settings::getInstance()->get_currency_name() == "INR") {
req.txtAmountUSD->setText(amount.toDecimalINRString());
} else if (Settings::getInstance()->get_currency_name() == "GBP") {
req.txtAmountUSD->setText(amount.toDecimalGBPString());
} else if (Settings::getInstance()->get_currency_name() == "AUD") {
req.txtAmountUSD->setText(amount.toDecimalBTCString());
}
req.txtMemo->setAcceptButton(req.buttonBox->button(QDialogButtonBox::Ok));
req.txtMemo->setLenDisplayLabel(req.lblMemoLen);
req.txtMemo->setMaxLen(400);
req.txtFrom->setFocus();
}
}
if (d.exec() == QDialog::Accepted) {
// Construct a hush Payment URI with the data and pay it immediately.
CAmount amount = CAmount::fromDecimalString(req.txtAmount->text());
QString memoURI = "hush:" + req.lblAddressInfo->text()
+ "?amt=" + amount.toDecimalString()
+ "&memo=" + QUrl::toPercentEncoding(req.txtMemo->toPlainText());
QString sendURI = "hush:" + AddressBook::addressFromAddressLabel(req.txtFrom->text())
+ "?amt=0.0001"
+ "&memo=" + QUrl::toPercentEncoding(memoURI);
// If the disclosed address in the memo doesn't have a balance, it will automatically fallback to the default
// sapling address
this->payhushURI(sendURI, req.lblAddressInfo->text());
}
}
}

4
src/contactmodel.h

@ -5,13 +5,17 @@
#include "Model/ContactItem.h"
#include <QListWidget>
#include "mainwindow.h"
class ContactModel
{
public:
ContactModel() {}
void renderContactList(QListView* view);
};
#endif

33
src/contactrequest.ui

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>777</width>
<width>780</width>
<height>427</height>
</rect>
</property>
@ -233,7 +233,7 @@
</property>
</spacer>
</item>
<item row="7" column="1" colspan="3">
<item row="7" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Insert a memo for your request&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -318,36 +318,11 @@
</property>
</spacer>
</item>
<item row="9" column="2">
<widget class="QPushButton" name="onlyAdd">
<property name="maximumSize">
<size>
<width>152</width>
<height>25</height>
</size>
</property>
<property name="baseSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Only add this contact</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="9" column="3" colspan="2">
<widget class="QPushButton" name="sendRequestButton">
<property name="maximumSize">
<size>
<width>188</width>
<width>300</width>
<height>25</height>
</size>
</property>
@ -358,7 +333,7 @@
</size>
</property>
<property name="text">
<string>Add Contact &amp; send request</string>
<string>Add Contact and send request</string>
</property>
<property name="autoDefault">
<bool>false</bool>

118
src/controller.cpp

@ -237,12 +237,15 @@ void Controller::getInfoThenRefresh(bool force)
zrpc->fetchInfo([=] (const json& reply) {
prevCallSucceeded = true;
int curBlock = reply["latest_block_height"].get<json::number_integer_t>();
int longestchain = reply["longestchain"].get<json::number_integer_t>();
int notarized = reply["notarized"].get<json::number_integer_t>();
bool doUpdate = force || (model->getLatestBlock() != curBlock);
int difficulty = reply["difficulty"].get<json::number_integer_t>();
int blocks_until_halving= 340000 - curBlock;
int halving_days = (blocks_until_halving * 150) / (60*60*24) ;
bool doUpdate = force || (model->getLatestBlock() != curBlock);
int longestchain = reply["longestchain"].get<json::number_integer_t>();
int notarized = reply["notarized"].get<json::number_integer_t>();
model->setLatestBlock(curBlock);
if (
Settings::getInstance()->get_currency_name() == "EUR" ||
@ -258,7 +261,11 @@ void Controller::getInfoThenRefresh(bool force)
);
ui->longestchain->setText(
"Block: " + QLocale(QLocale::German).toString(longestchain)
);
ui->difficulty->setText(
QLocale(QLocale::German).toString(difficulty)
);
@ -540,8 +547,12 @@ void Controller::getInfoThenRefresh(bool force)
refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans()
refreshTransactions();
}
int lag = longestchain - notarized ;
this->setLag(lag);
}, [=](QString err) {
// hushd has probably disappeared.
this->noConnection();
// Prevent multiple dialog boxes, because these are called async
@ -562,6 +573,20 @@ void Controller::getInfoThenRefresh(bool force)
});
}
int Controller::getLag()
{
return _lag;
}
void Controller::setLag(int lag)
{
_lag = lag;
}
void Controller::refreshAddresses()
{
if (!zrpc->haveConnection())
@ -871,12 +896,33 @@ void Controller::refreshTransactions() {
CAmount amount = CAmount::fromqint64(-1* o["value"].get<json::number_unsigned_t>());
// Check for Memos
if (confirmations == 0) {
chatModel->addconfirmations(txid, confirmations);
}
if ((confirmations == 1) && (chatModel->getConfirmationByTx(txid) != QString("0xdeadbeef"))){
DataStore::getChatDataStore()->clear();
chatModel->killConfirmationCache();
this->refresh(true);
}
QString memo;
if (!o["memo"].is_null()) {
memo = QString::fromStdString(o["memo"]);
QString cid;
bool isNotarized;
if (confirmations > getLag())
{
isNotarized = true;
}else{
isNotarized = false;
}
qDebug()<<"Conf : " << confirmations;
ChatItem item = ChatItem(
datetime,
@ -888,15 +934,17 @@ void Controller::refreshTransactions() {
cid,
txid,
confirmations,
true
true,
isNotarized,
false
);
// qDebug()<<"Memo : " <<memo;
// qDebug()<<"Confirmation :" << confirmations;
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
}
}
items.push_back(TransactionItemDetail{address, amount, memo});
total_amount = total_amount + amount;
}
@ -944,6 +992,28 @@ void Controller::refreshTransactions() {
QString cid;
int position;
QString requestZaddr;
bool isContact;
for (auto &p : AddressBook::getInstance()->getAllAddressLabels())
{
if (p.getPartnerAddress() == requestZaddr)
{
chatModel->addAddressbylabel(address, requestZaddr);
} else{}
if (chatModel->Addressbylabel(address) != QString("0xdeadbeef")){
isContact = true;
}else{
isContact = false;
}
if (!it["memo"].is_null()) {
@ -958,7 +1028,8 @@ void Controller::refreshTransactions() {
chatModel->addCid(txid, cid);
chatModel->addrequestZaddr(txid, requestZaddr);
}
}
if (chatModel->getCidByTx(txid) != QString("0xdeadbeef")){
@ -973,8 +1044,20 @@ void Controller::refreshTransactions() {
requestZaddr = chatModel->getrequestZaddrByTx(txid);
}else{
requestZaddr = "";
}
}
position = it["position"].get<json::number_integer_t>();
bool isNotarized;
if (confirmations > getLag())
{
isNotarized = true;
}else{
isNotarized = false;
}
ChatItem item = ChatItem(
datetime,
address,
@ -985,16 +1068,17 @@ void Controller::refreshTransactions() {
cid,
txid,
confirmations,
false
false,
isNotarized,
isContact
);
// qDebug()<< "Position : " << position;
// qDebug()<<"Confirmation :" << confirmations;
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
}
}
}
}
qDebug()<<"get Lag" << getLag();
// Calculate the total unspent amount that's pending. This will need to be
// shown in the UI so the user can keep track of pending funds

8
src/controller.h

@ -1,3 +1,6 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
#ifndef RPCCLIENT_H
#define RPCCLIENT_H
@ -37,7 +40,10 @@ public:
Connection* getConnection() { return zrpc->getConnection(); }
void setConnection(Connection* c);
void refresh(bool force = false);
void refreshAddresses();
void refreshAddresses();
int getLag();
void setLag(int lag);
int _lag;
void checkForUpdate(bool silent = true);
void refreshZECPrice();

121
src/encryption.ui

@ -14,71 +14,104 @@
<string>Encrypt Your Wallet</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0" colspan="2">
<widget class="Line" name="line_2">
<item row="0" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Vertical</enum>
</property>
</widget>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_3">
<item row="1" column="0" colspan="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Encryption Password:</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:14pt; color:#ef2929;&quot;&gt;WARNING:&lt;/span&gt; If you forget your passphrase the only way to recover the wallet is from the seed phrase. If you dont have Backup your seed phrase, please do it now!&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Confirm Password:</string>
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" rowspan="2" colspan="3">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="txtConfirmPassword">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
<item row="4" column="2" rowspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;16 letters minimum&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<item row="5" column="0" colspan="2">
<widget class="QLabel" name="lblPasswordMatch">
<property name="styleSheet">
<string notr="true">color: red;</string>
</property>
<property name="text">
<string>Passwords don't match</string>
<string>Passphrase don't match</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Encryption Passphrase:</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QLineEdit" name="txtPassword">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="7" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Confirm Passphrase:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>WARNING: If you forget your password, the only way to recover the wallet is from the seed phrase.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<item row="7" column="1" colspan="2">
<widget class="QLineEdit" name="txtConfirmPassword">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</widget>
</item>
<item row="8" column="0" colspan="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
@ -95,32 +128,6 @@
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<tabstops>

156
src/hushrequest.ui

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>hushrequest</class>
<widget class="QDialog" name="hushrequest">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>663</width>
<height>529</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="lblPixmap">
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblHeader">
<property name="text">
<string>Request payment from a Sapling address. You'll send a hush 0.0001 transaction to the address with a hush payment URI. The memo will be included in the transaction when the address pays you.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblAddress">
<property name="text">
<string>Request From</string>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>541</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="txtFrom">
<property name="text">
<string>zaddr</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblAmount">
<property name="text">
<string>Amount in </string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLineEdit" name="txtAmount">
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="placeholderText">
<string>Amount</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="txtAmountUSD">
<property name="text">
<string>Amount USD</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Memo</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="lblMemoLen">
<property name="text">
<string notr="true">0 / 512</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="MemoEdit" name="txtMemo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>My Address</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="lblAddressInfo">
<property name="text">
<string>The recipient will see this address in the &quot;to&quot; field when they pay your request.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MemoEdit</class>
<extends>QPlainTextEdit</extends>
<header>memoedit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

528
src/mainwindow.cpp

@ -21,15 +21,36 @@
#include "ui_requestContactDialog.h"
#include "chatmodel.h"
#include "requestdialog.h"
#include "ui_startupencryption.h"
#include "ui_removeencryption.h"
#include "websockets.h"
#include "sodium.h"
#include "sodium/crypto_generichash_blake2b.h"
#include <QRegularExpression>
#include "FileSystem/FileSystem.h"
#include "Crypto/passwd.h"
#include "Crypto/FileEncryption.h"
using json = nlohmann::json;
#ifdef Q_OS_WIN
auto dirwallet = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet.dat");
auto dirwalletenc = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet-enc.dat");
auto dirwalletbackup = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet.datBackup");
#endif
#ifdef Q_OS_UNIX
auto dirwallet = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".silentdragonlite/silentdragonlite-wallet.dat");
auto dirwalletenc = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".silentdragonlite/silentdragonlite-wallet-enc.dat");
auto dirwalletbackup = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".silentdragonlite/silentdragonlite-wallet.datBackup");
#endif
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
// Include css
QString theme_name;
try
@ -47,12 +68,19 @@ MainWindow::MainWindow(QWidget *parent) :
ui->setupUi(this);
logger = new Logger(this, QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite-wallet.log"));
// Check for encryption
if(fileExists(dirwalletenc))
{
this->removeWalletEncryptionStartUp();
}
ui->memoTxtChat->setAutoFillBackground(false);
ui->memoTxtChat->setPlaceholderText("Send Message");
ui->memoTxtChat->setTextColor(Qt::white);
// Status Bar
setupStatusBar();
@ -180,6 +208,12 @@ MainWindow::MainWindow(QWidget *parent) :
createWebsocket(wormholecode);
}
}
bool MainWindow::fileExists(QString path)
{
QFileInfo check_file(path);
return (check_file.exists() && check_file.isFile());
}
void MainWindow::createWebsocket(QString wormholecode) {
qDebug() << "Listening for app connections on port 8777";
@ -234,6 +268,10 @@ void MainWindow::doClose() {
closeEvent(nullptr);
}
void MainWindow::doClosePw() {
closeEventpw(nullptr);
}
void MainWindow::closeEvent(QCloseEvent* event) {
QSettings s;
@ -243,6 +281,78 @@ void MainWindow::closeEvent(QCloseEvent* event) {
s.sync();
// Let the RPC know to shut down any running service.
rpc->shutdownhushd();
// Check is encryption is ON for SDl
if(fileExists(dirwalletenc))
{
// delete old file before
//auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QFile fileoldencryption(dirwalletenc);
fileoldencryption.remove();
// Encrypt our wallet.dat
QString str = this->getPassword();
// QString str = ed.txtPassword->text(); // data comes from user inputs
int length = str.length();
char *sequence = NULL;
sequence = new char[length+1];
strncpy(sequence, str.toLocal8Bit(), length +1);
#define MESSAGE ((const unsigned char *) sequence)
#define MESSAGE_LEN length
unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES];
crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN);
#define PASSWORD sequence
#define KEY_LEN crypto_box_SEEDBYTES
/////////we use the Hash of the Password as Salt, not perfect but still a good solution.
unsigned char key[KEY_LEN];
if (crypto_pwhash
(key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */
}
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
// auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QString source_file = dir.filePath("addresslabels.dat");
QString target_enc_file = dir.filePath("addresslabels.dat.enc");
QString sourceWallet_file = dirwallet;
QString target_encWallet_file = dirwalletenc;
FileEncryption::encrypt(target_enc_file, source_file, key);
FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, key);
///////////////// we rename the plaintext wallet.dat to Backup, for testing.
QFile wallet(dirwallet);
QFile address(dir.filePath("addresslabels.dat"));
wallet.remove();
address.remove();
}
// Bubble up
if (event)
QMainWindow::closeEvent(event);
}
void MainWindow::closeEventpw(QCloseEvent* event) {
// Let the RPC know to shut down any running service.
rpc->shutdownhushd();
@ -253,124 +363,299 @@ void MainWindow::closeEvent(QCloseEvent* event) {
void MainWindow::encryptWallet() {
// Check if wallet is already encrypted
auto encStatus = rpc->getModel()->getEncryptionStatus();
if (encStatus.first) {
QMessageBox::information(this, tr("Wallet is already encrypted"),
tr("Your wallet is already encrypted with a password.\nPlease use 'Remove Wallet Encryption' if you want to remove the wallet encryption."),
QMessageBox::Ok
);
return;
}
QDialog d(this);
Ui_encryptionDialog ed;
ed.setupUi(&d);
// Handle edits on the password box
auto fnPasswordEdited = [=](const QString&) {
// Enable the OK button if the passwords match.
QString password = ed.txtPassword->text();
if (!ed.txtPassword->text().isEmpty() &&
ed.txtPassword->text() == ed.txtConfirmPassword->text()) {
ed.txtPassword->text() == ed.txtConfirmPassword->text() && password.size() >= 16) {
ed.lblPasswordMatch->setText("");
ed.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
} else {
ed.lblPasswordMatch->setText(tr("Passwords don't match"));
ed.lblPasswordMatch->setText(tr("Passphrase don't match or You have entered too few letters (16 minimum)"));
ed.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
}
};
QObject::connect(ed.txtConfirmPassword, &QLineEdit::textChanged, fnPasswordEdited);
QObject::connect(ed.txtPassword, &QLineEdit::textChanged, fnPasswordEdited);
ed.txtPassword->setText("");
ed.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
if (d.exec() == QDialog::Accepted)
{
auto fnShowError = [=](QString title, const json& res) {
QMessageBox::critical(this, title,
tr("Error was:\n") + QString::fromStdString(res.dump()),
QMessageBox::Ok
);
};
QString str = ed.txtPassword->text(); // data comes from user inputs
int length = str.length();
this->setPassword(str);
if (d.exec() == QDialog::Accepted) {
rpc->encryptWallet(ed.txtPassword->text(), [=](json res) {
if (isJsonResultSuccess(res)) {
// Save the wallet
rpc->saveWallet([=] (json reply) {
if (isJsonResultSuccess(reply)) {
QMessageBox::information(this, tr("Wallet Encrypted"),
tr("Your wallet was successfully encrypted! The password will be needed to send funds or export private keys."),
QMessageBox::Ok
);
} else {
fnShowError(tr("Wallet Encryption Failed"), reply);
}
});
char *sequence = NULL;
sequence = new char[length+1];
strncpy(sequence, str.toLocal8Bit(), length +1);
// And then refresh the UI
rpc->refresh(true);
} else {
fnShowError(tr("Wallet Encryption Failed"), res);
}
});
#define MESSAGE ((const unsigned char *) sequence)
#define MESSAGE_LEN length
unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES];
crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN);
#define PASSWORD sequence
#define KEY_LEN crypto_box_SEEDBYTES
/////////we use the Hash of the Password as Salt, not perfect but still a good solution.
unsigned char key[KEY_LEN];
if (crypto_pwhash
(key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */
}
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QString source_file = dir.filePath("addresslabels.dat");
QString target_enc_file = dir.filePath("addresslabels.dat.enc");
QString sourceWallet_file = dirwallet;
QString target_encWallet_file = dirwalletenc;
FileEncryption::encrypt(target_enc_file, source_file, key);
FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, key);
QFile wallet(dirwallet);
QFile address(dir.filePath("addresslabels.dat"));
wallet.rename(dirwalletbackup);
address.rename(dir.filePath("addresslabels.datBackup"));
}
}
void MainWindow::removeWalletEncryption() {
// Check if wallet is already encrypted
auto encStatus = rpc->getModel()->getEncryptionStatus();
if (!encStatus.first) {
QMessageBox::information(this, tr("Wallet is not encrypted"),
tr("Your wallet is not encrypted with a password."),
QDialog d(this);
Ui_removeencryption ed;
ed.setupUi(&d);
auto fnPasswordEdited = [=](const QString&) {
QString password = ed.txtPassword->text();
// Enable the OK button if the passwords match.
if (!ed.txtPassword->text().isEmpty() &&
ed.txtPassword->text() == ed.txtConfirmPassword->text() && password.size() >= 16) {
ed.lblPasswordMatch->setText("");
ed.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
} else {
ed.lblPasswordMatch->setText(tr("Passwords don't match"));
ed.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
}
};
QObject::connect(ed.txtConfirmPassword, &QLineEdit::textChanged, fnPasswordEdited);
QObject::connect(ed.txtPassword, &QLineEdit::textChanged, fnPasswordEdited);
if (d.exec() == QDialog::Accepted)
{
QString str = ed.txtPassword->text(); // data comes from user inputs
int length = str.length();
char *sequence = NULL;
sequence = new char[length+1];
strncpy(sequence, str.toLocal8Bit(), length +1);
#define MESSAGE ((const unsigned char *) sequence)
#define MESSAGE_LEN length
unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES];
crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN);
#define PASSWORD sequence
#define KEY_LEN crypto_box_SEEDBYTES
/////////we use the Hash of the Password as Salt, not perfect but still a good solution.
unsigned char key[KEY_LEN];
if (crypto_pwhash
(key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */
}
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QString target_encwallet_file = dirwalletenc;
QString target_decwallet_file = dirwallet;
QString target_encaddr_file = dir.filePath("addresslabels.dat.enc");
QString target_decaddr_file = dir.filePath("addresslabels.dat");
FileEncryption::decrypt(target_decwallet_file, target_encwallet_file, key);
FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, key);
QFile filencrypted(dirwalletenc);
QFile wallet(dirwallet);
if (wallet.size() > 0)
{
QMessageBox::information(this, tr("Wallet decryption Success"),
QString("Successfully delete the encryption"),
QMessageBox::Ok
);
filencrypted.remove();
}else{
qDebug()<<"verschlüsselung gescheitert ";
QMessageBox::critical(this, tr("Wallet Encryption Failed"),
QString("False password, please try again"),
QMessageBox::Ok
);
return;
this->removeWalletEncryption();
}
}
}
bool ok;
QString password = QInputDialog::getText(this, tr("Wallet Password"),
tr("Please enter your wallet password"), QLineEdit::Password, "", &ok);
void MainWindow::removeWalletEncryptionStartUp() {
QDialog d(this);
Ui_startup ed;
ed.setupUi(&d);
// If cancel was pressed, just return
if (!ok) {
return;
}
// Handle edits on the password box
auto fnPasswordEdited = [=](const QString&) {
QString password = ed.txtPassword->text();
// Enable the OK button if the passwords match.
if (!ed.txtPassword->text().isEmpty() &&
ed.txtPassword->text() == ed.txtConfirmPassword->text() && password.size() >= 16) {
ed.lblPasswordMatch->setText("");
ed.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
} else {
ed.lblPasswordMatch->setText(tr("Passwords don't match or under-lettered"));
ed.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
}
if (password.isEmpty()) {
QMessageBox::critical(this, tr("Wallet Decryption Failed"),
tr("Please enter a password to decrypt your wallet!"),
QMessageBox::Ok
);
return;
}
};
rpc->removeWalletEncryption(password, [=] (json res) {
if (isJsonResultSuccess(res)) {
// Save the wallet
rpc->saveWallet([=] (json reply) {
if(isJsonResultSuccess(reply)) {
QMessageBox::information(this, tr("Wallet Encryption Removed"),
tr("Your wallet was successfully decrypted! You will no longer need a password to send funds or export private keys."),
QMessageBox::Ok
);
} else {
QMessageBox::critical(this, tr("Wallet Decryption Failed"),
QString::fromStdString(reply["error"].get<json::string_t>()),
QMessageBox::Ok
);
}
});
QObject::connect(ed.txtConfirmPassword, &QLineEdit::textChanged, fnPasswordEdited);
QObject::connect(ed.txtPassword, &QLineEdit::textChanged, fnPasswordEdited);
if (d.exec() == QDialog::Accepted)
{
QString str = ed.txtPassword->text(); // data comes from user inputs
int length = str.length();
this->setPassword(str);
char *sequence = NULL;
sequence = new char[length+1];
strncpy(sequence, str.toLocal8Bit(), length +1);
#define MESSAGE ((const unsigned char *) sequence)
#define MESSAGE_LEN length
unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES];
crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN);
#define PASSWORD sequence
#define KEY_LEN crypto_box_SEEDBYTES
/////////we use the Hash of the Password as Salt, not perfect but still a good solution.
unsigned char key[KEY_LEN];
if (crypto_pwhash
(key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */
}
{
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QString target_encwallet_file = dirwalletenc;
QString target_decwallet_file = dirwallet;
QString target_encaddr_file = dir.filePath("addresslabels.dat.enc");
QString target_decaddr_file = dir.filePath("addresslabels.dat");
FileEncryption::decrypt(target_decwallet_file, target_encwallet_file, key);
FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, key);
// And then refresh the UI
rpc->refresh(true);
} else {
QMessageBox::critical(this, tr("Wallet Decryption Failed"),
QString::fromStdString(res["error"].get<json::string_t>()),
}
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QFile wallet(dirwallet);
//QFile backup(dirHome.filePath(".silentdragonlite/silentdragonlite-wallet.datBACKUP"));*/
if (wallet.size() > 0)
{
if (fileExists(dirwalletbackup))
{
QMessageBox::warning(this, tr("You have still Plaintextdata on your disk!"),
QString("WARNING: Delete it only if you have a backup of your Wallet Seed."),
QMessageBox::Ok
);
// backup.remove();
}
QMessageBox::information(this, tr("Wallet Encryption Success"),
QString("SDL is ready to Rock"),
QMessageBox::Ok
);
}else{
qDebug()<<"verschlüsselung gescheitert ";
QMessageBox::critical(this, tr("Wallet Encryption Failed"),
QString("false password please try again"),
QMessageBox::Ok
);
}
});
this->removeWalletEncryptionStartUp();
}
}else{
this->doClosePw();
}
}
QString MainWindow::getPassword()
{
return _password;
}
void MainWindow::setPassword(QString password)
{
_password = password;
}
void MainWindow::setupStatusBar() {
@ -923,6 +1208,7 @@ void MainWindow::setupTransactionsTab() {
ui->listChat->setMinimumSize(200,350);
ui->listChat->setItemDelegate(new ListViewDelegate());
ui->listChat->show();
ui->transactionsTable->setContextMenuPolicy(Qt::CustomContextMenu);
// Table right click
QObject::connect(ui->transactionsTable, &QTableView::customContextMenuRequested, [=] (QPoint pos) {
@ -1052,9 +1338,6 @@ void MainWindow::setupchatTab() {
ui->memoTxtChat->setTextColor("Black");
}
QObject::connect(ui->sendChatButton, &QPushButton::clicked, this, &MainWindow::sendChat);
QObject::connect(ui->safeContactRequest, &QPushButton::clicked, this, &MainWindow::addContact);
QObject::connect(ui->pushContact, &QPushButton::clicked, this , &MainWindow::renderContactRequest);
@ -1069,18 +1352,67 @@ void MainWindow::setupchatTab() {
for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
if (label_contact == p.getName()) {
// ui->ContactZaddr->setText(p.getPartnerAddress());
// ui->MyZaddr->setText(p.getMyAddress());
ui->contactNameMemo->setText(p.getName());
ui->memoTxtChat->clear();
rpc->refresh(true);
// updateChat();
ui->contactNameMemo->setText(p.getName());
rpc->refresh(true);
}
});
QMenu* contextMenu;
QAction* requestAction;
QAction* editAction;
QAction* HushAction;
QAction* requestHushAction;
QAction* subatomicAction;
contextMenu = new QMenu(ui->listContactWidget);
requestAction = new QAction("Send a contact request - coming soon",contextMenu);
editAction = new QAction("Delete this contact",contextMenu);
HushAction = new QAction("Send a friend some Hush - coming soon",contextMenu);
requestHushAction = new QAction("Request some Hush - coming soon",contextMenu);
subatomicAction = new QAction("Make a subatomic swap with a friend- coming soon",contextMenu);
ui->listContactWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
ui->listContactWidget->addAction(requestAction);
ui->listContactWidget->addAction(editAction);
ui->listContactWidget->addAction(HushAction);
ui->listContactWidget->addAction(requestHushAction);
ui->listContactWidget->addAction(subatomicAction);
QObject::connect(requestHushAction, &QAction::triggered, [=]() {
QModelIndex index = ui->listContactWidget->currentIndex();
QString label_contact = index.data(Qt::DisplayRole).toString();
for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
if (label_contact == p.getName()) {
ui->contactNameMemo->setText(p.getName());
rpc->refresh(true);
}
MainWindow::showRequesthush();
});
QObject::connect(editAction, &QAction::triggered, [=]() {
QModelIndex index = ui->listContactWidget->currentIndex();
QString label_contact = index.data(Qt::DisplayRole).toString();
for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
if (label_contact == p.getName()) {
QString label1 = p.getName();
QString addr = p.getPartnerAddress();
QString myzaddr = p.getMyAddress();
QString cid = p.getCid();
QString avatar = p.getAvatar();
AddressBook::getInstance()->removeAddressLabel(label1, addr, myzaddr, cid,avatar);
rpc->refreshContacts(
ui->listContactWidget);
rpc->refresh(true);
}
});
ui->memoTxtChat->setLenDisplayLabel(ui->memoSizeChat);
ui->memoTxtChat->setLenDisplayLabelChat(ui->memoSizeChat);
}
@ -1089,13 +1421,11 @@ void MainWindow::updateChat()
{
rpc->refreshChat(ui->listChat,ui->memoSizeChat);
rpc->refresh(true);
}
void MainWindow::updateContacts()
{
//rpc->refreshContacts(ui->listContactWidget);
}
void MainWindow::addNewZaddr(bool sapling) {

22
src/mainwindow.h

@ -51,6 +51,8 @@ public:
QString doSendChatTxValidations(Tx tx);
QString doSendRequestTxValidations(Tx tx);
QString getCid();
QString getPassword();
void setPassword(QString Password);
void replaceWormholeClient(WormholeClient* newClient);
bool isWebsocketListening();
@ -58,8 +60,9 @@ public:
void stopWebsocket();
void saveContact();
void saveandsendContact();
void setMaxLen(int len);
void updateDisplay();
void showRequesthush();
// void setmaxlenChat(int len);
// void updateDisplay();
void balancesReady();
@ -86,6 +89,7 @@ public:
Logger* logger;
void doClose();
void doClosePw();
QString createHeaderMemo(QString type, QString cid, QString zaddr, int version, int headerNumber);
public slots:
@ -100,7 +104,9 @@ private slots:
private:
bool fileExists(QString path);
void closeEvent(QCloseEvent* event);
void closeEventpw(QCloseEvent* event);
void setupSendTab();
@ -119,6 +125,7 @@ private:
void setupStatusBar();
void clearSendForm();
QString _password;
Tx createTxFromSendPage();
bool confirmTx(Tx tx, RecurringPaymentInfo* rpi);
@ -129,6 +136,7 @@ private:
void encryptWallet();
void removeWalletEncryption();
void removeWalletEncryptionStartUp();
void cancelButton();
void sendButton();
@ -192,14 +200,14 @@ class ChatMemoEdit : public QTextEdit
public:
ChatMemoEdit(QWidget* parent);
void setMaxLen(int len);
void setLenDisplayLabel(QLabel* label);
void setMaxLenChat(int len);
void setLenDisplayLabelChat(QLabel* label);
void SetSendChatButton(QPushButton* button);
void updateDisplay();
void updateDisplayChat();
private:
int maxlen = 512;
QLabel* lenDisplayLabel = nullptr;
int maxlenchat = 512;
QLabel* lenDisplayLabelchat = nullptr;
QPushButton* sendChatButton = nullptr;
};

23
src/mainwindow.ui

@ -1378,7 +1378,10 @@
<bool>true</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
@ -1386,6 +1389,9 @@
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectItems</enum>
</property>
</widget>
<widget class="QLabel" name="label_39">
<property name="geometry">
@ -1419,10 +1425,16 @@
<set>QTextEdit::AutoNone</set>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::FixedColumnWidth</enum>
<enum>QTextEdit::FixedPixelWidth</enum>
</property>
<property name="lineWrapColumnOrWidth">
<number>80</number>
<number>600</number>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextEditorInteraction</set>
</property>
</widget>
<widget class="QLabel" name="contactNameMemo">
@ -1505,6 +1517,9 @@
<height>521</height>
</rect>
</property>
<property name="toolTip">
<string>The locks shows you the status of the message. Red lock = unconfirmed, green lock = min. 1 confirmations, orange lock = message is notarized</string>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
@ -1515,7 +1530,7 @@
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::AllEditTriggers</set>
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>

2
src/memodialog.ui

@ -74,7 +74,7 @@
<customwidget>
<class>MemoEdit</class>
<extends>QPlainTextEdit</extends>
<header>memoedit.h</header>
<header location="global">memoedit.h</header>
</customwidget>
</customwidgets>
<resources/>

197
src/removeencryption.ui

@ -0,0 +1,197 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>removeencryption</class>
<widget class="QDialog" name="removeencryption">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Remove your Wallet encryption</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>50</x>
<y>260</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>260</x>
<y>170</y>
<width>133</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;16 letters minimum&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>10</x>
<y>229</y>
<width>157</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>Confirm Passphrase:</string>
</property>
</widget>
<widget class="Line" name="line_2">
<property name="geometry">
<rect>
<x>10</x>
<y>164</y>
<width>382</width>
<height>3</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QLineEdit" name="txtConfirmPassword">
<property name="geometry">
<rect>
<x>173</x>
<y>229</y>
<width>219</width>
<height>25</height>
</rect>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>56</y>
<width>382</width>
<height>56</height>
</rect>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:14pt; color:#ef2929;&quot;&gt;WARNING:&lt;/span&gt; If yo remove your encryption, all your Data is Plaintext on your Disk!&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="Line" name="line">
<property name="geometry">
<rect>
<x>10</x>
<y>260</y>
<width>382</width>
<height>3</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>10</x>
<y>198</y>
<width>157</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>Encryption Passphrase:</string>
</property>
</widget>
<widget class="QLabel" name="lblPasswordMatch">
<property name="geometry">
<rect>
<x>10</x>
<y>175</y>
<width>243</width>
<height>17</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">color: red;</string>
</property>
<property name="text">
<string>Passphrase don't match</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
<widget class="QLineEdit" name="txtPassword">
<property name="geometry">
<rect>
<x>173</x>
<y>198</y>
<width>219</width>
<height>25</height>
</rect>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>removeencryption</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>removeencryption</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

52
src/requestContactDialog.ui

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>812</width>
<width>850</width>
<height>495</height>
</rect>
</property>
@ -27,7 +27,7 @@
</property>
</widget>
</item>
<item row="0" column="3" colspan="2">
<item row="0" column="2" colspan="3">
<widget class="QLabel" name="label_3">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Memo of the request&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -97,12 +97,12 @@
</property>
</widget>
</item>
<item row="3" column="0" rowspan="6" colspan="2">
<item row="3" column="0" rowspan="8">
<widget class="QListView" name="requestContactOld">
<property name="minimumSize">
<size>
<width>256</width>
<height>192</height>
<height>190</height>
</size>
</property>
<property name="mouseTracking">
@ -119,14 +119,21 @@
</property>
</widget>
</item>
<item row="3" column="2" colspan="2">
<item row="3" column="1" colspan="3">
<widget class="QLabel" name="label_4">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Details of the request&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="3">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Request from :</string>
</property>
</widget>
</item>
<item row="3" column="4" colspan="3">
<item row="4" column="4" colspan="3">
<widget class="QLineEdit" name="requestZaddr">
<property name="minimumSize">
<size>
@ -142,14 +149,14 @@
</property>
</widget>
</item>
<item row="4" column="2">
<item row="5" column="1" colspan="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>My Zaddr :</string>
</property>
</widget>
</item>
<item row="4" column="4" colspan="3">
<item row="5" column="4" colspan="3">
<widget class="QLineEdit" name="requestMyAddr">
<property name="minimumSize">
<size>
@ -165,24 +172,24 @@
</property>
</widget>
</item>
<item row="5" column="2" colspan="2">
<item row="6" column="1" colspan="3">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Give a Nickname:</string>
</property>
</widget>
</item>
<item row="5" column="4" colspan="2">
<item row="6" column="4" colspan="2">
<widget class="QLineEdit" name="requestLabel"/>
</item>
<item row="6" column="2" colspan="3">
<item row="7" column="1" colspan="4">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;right&quot;&gt;Choose a avatar for your contact :&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="7" column="2" colspan="2">
<item row="8" column="1" rowspan="2" colspan="3">
<widget class="QComboBox" name="comboBoxAvatar">
<property name="minimumSize">
<size>
@ -328,7 +335,7 @@
</item>
</widget>
</item>
<item row="7" column="5" rowspan="2">
<item row="8" column="5" rowspan="2">
<widget class="QPushButton" name="cancel">
<property name="maximumSize">
<size>
@ -353,7 +360,7 @@
</property>
</widget>
</item>
<item row="7" column="6" rowspan="2">
<item row="8" column="6" rowspan="2">
<widget class="QPushButton" name="pushButton">
<property name="maximumSize">
<size>
@ -369,17 +376,24 @@
</property>
</widget>
</item>
<item row="8" column="3" colspan="2">
<widget class="QLabel" name="requestCID">
<item row="10" column="1">
<widget class="QLabel" name="zaddrold">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="10" column="3">
<widget class="QLabel" name="zaddrnew">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="2" colspan="5">
<widget class="QLabel" name="label_4">
<item row="10" column="2">
<widget class="QLabel" name="requestCID">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Details of the request&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string/>
</property>
</widget>
</item>

252
src/requestdialog.ui

@ -14,37 +14,10 @@
<string>Payment Request</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="18" column="1" colspan="3">
<widget class="AddressCombo" name="cmbMyAddress"/>
</item>
<item row="2" column="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnAddressBook">
<property name="text">
<string>AddressBook</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="21" column="0" colspan="4">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="10" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string/>
</property>
</widget>
</item>
@ -55,171 +28,198 @@
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QLabel" name="label_2">
<item row="15" column="3">
<widget class="QLabel" name="lblAddressInfo">
<property name="text">
<string>My Address</string>
<string>The recipient will see this address in the &quot;to&quot; field when they pay your request.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="1" colspan="3">
<widget class="QLabel" name="lblSaplingWarning">
<property name="styleSheet">
<string notr="true">color: red;</string>
</property>
<property name="text">
<string/>
<item row="12" column="1" colspan="3">
<widget class="MemoEdit" name="txtMemo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="lblAmount">
<item row="0" column="1">
<widget class="QLabel" name="lblPixmap">
<property name="text">
<string>Amount in </string>
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="label">
<item row="18" column="1" colspan="3">
<widget class="AddressCombo" name="cmbMyAddress"/>
</item>
<item row="14" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="24" column="2" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="5" column="1" colspan="3">
<widget class="QLabel" name="lblSaplingWarning">
<property name="styleSheet">
<string notr="true">color: red;</string>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLabel" name="label_4">
<item row="11" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string/>
<string>Memo</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="3">
<widget class="QLineEdit" name="txtFrom">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="20" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
<property name="placeholderText">
<string>z address</string>
</spacer>
</item>
<item row="11" column="3">
<widget class="QLabel" name="lblMemoLen">
<property name="text">
<string notr="true">0 / 512</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="Line" name="line_3">
<item row="13" column="1" colspan="3">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="12" column="1" colspan="3">
<widget class="MemoEdit" name="txtMemo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="9" column="1">
<widget class="QLabel" name="txtAmountUSD">
<property name="text">
<string>Amount USD</string>
</property>
</widget>
</item>
<item row="7" column="1" colspan="3">
<widget class="QLineEdit" name="txtAmount">
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="placeholderText">
<string>Amount</string>
</property>
</widget>
</item>
<item row="13" column="1" colspan="3">
<widget class="Line" name="line_2">
<item row="21" column="0" colspan="4">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="15" column="3">
<widget class="QLabel" name="lblAddressInfo">
<item row="2" column="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnAddressBook">
<property name="text">
<string>AddressBook</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2" colspan="2">
<widget class="QLabel" name="lblHeader">
<property name="text">
<string>The recipient will see this address in the &quot;to&quot; field when they pay your request.</string>
<string>Request payment from a Sapling address. You'll send a hush 0.0001 transaction to the address with a hush payment URI. The memo will be included in the transaction when the address pays you.</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="11" column="3">
<widget class="QLabel" name="lblMemoLen">
<property name="text">
<string notr="true">0 / 512</string>
<item row="4" column="1" colspan="3">
<widget class="QLineEdit" name="txtFrom">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="placeholderText">
<string>z address</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="txtAmountUSD">
<item row="15" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Amount USD</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<string>My Address</string>
</property>
</widget>
</item>
<item row="20" column="1">
<spacer name="verticalSpacer">
<item row="24" column="2" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item row="11" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Memo</string>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblPixmap">
<property name="text">
<string>TextLabel</string>
</property>
<item row="7" column="1" colspan="3">
<widget class="QLineEdit" name="txtAmount">
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="placeholderText">
<string>Amount</string>
</property>
</widget>
</item>
<item row="0" column="2" colspan="2">
<widget class="QLabel" name="lblHeader">
<item row="6" column="1">
<widget class="QLabel" name="lblAmount">
<property name="text">
<string>Request payment from a Sapling address. You'll send a hush 0.0001 transaction to the address with a hush payment URI. The memo will be included in the transaction when the address pays you.</string>
<string>Amount in </string>
</property>
<property name="wordWrap">
<bool>true</bool>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>

2
src/sendtab.cpp

@ -937,7 +937,7 @@ QString MainWindow::doSendTxValidations(Tx tx) {
auto available = rpc->getModel()->getAvailableBalance();
if (available < total) {
return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 5 confirmations before they can be spent")
return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent")
.arg(available.toDecimalhushString(), total.toDecimalhushString());
}

184
src/startupencryption.ui

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>startup</class>
<widget class="QDialog" name="startup">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>SDL Startup Decryption</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>50</x>
<y>260</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>10</x>
<y>229</y>
<width>127</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>Confirm Password:</string>
</property>
</widget>
<widget class="Line" name="line_2">
<property name="geometry">
<rect>
<x>10</x>
<y>166</y>
<width>382</width>
<height>3</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QLineEdit" name="txtConfirmPassword">
<property name="geometry">
<rect>
<x>162</x>
<y>229</y>
<width>230</width>
<height>25</height>
</rect>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>58</y>
<width>382</width>
<height>56</height>
</rect>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If you have forgotten your password, restore your wallet with your seed!&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="Line" name="line">
<property name="geometry">
<rect>
<x>10</x>
<y>260</y>
<width>382</width>
<height>3</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>10</x>
<y>198</y>
<width>146</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>Encryption Password:</string>
</property>
</widget>
<widget class="QLabel" name="lblPasswordMatch">
<property name="geometry">
<rect>
<x>10</x>
<y>175</y>
<width>382</width>
<height>17</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">color: red;</string>
</property>
<property name="text">
<string>Passwords don't match</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
<widget class="QLineEdit" name="txtPassword">
<property name="geometry">
<rect>
<x>162</x>
<y>198</y>
<width>230</width>
<height>25</height>
</rect>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>startup</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>startup</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
Loading…
Cancel
Save