Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Install Qt6
uses: jurplel/install-qt-action@v3
with:
version: 6.8.*
version: 6.9.2
aqtversion: '==3.1.*'
host: 'linux'
target: 'desktop'
Expand All @@ -44,6 +44,7 @@ jobs:
sudo apt install jags
sudo apt install libminizip-dev # required by freexl
sudo apt install librdata-dev
sudo apt install libsodium-dev
git clone https://github.com/jasp-stats/freexl.git
cd freexl && ./configure && make && sudo make install

Expand Down
6 changes: 3 additions & 3 deletions CommonData/archivereader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ void ArchiveReader::openEntry(const string &archivePath, const string &entryPath

if (_archiveExists)
{
_archive = archive_read_new();
_archive = archive_read_new();
archive_read_support_filter_all(_archive);
archive_read_support_format_all(_archive);

Expand All @@ -66,8 +66,8 @@ void ArchiveReader::openEntry(const string &archivePath, const string &entryPath

if (r == ARCHIVE_OK)
{
_isOpen = true;
bool success = false;
_isOpen = true;
bool success = false;

archive_entry * entry;
while (archive_read_next_header(_archive, &entry) == ARCHIVE_OK)
Expand Down
7 changes: 3 additions & 4 deletions CommonData/archivereader.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
class ArchiveReader
{
public:
ArchiveReader(){}
ArchiveReader(const std::string &archivePath, const std::string &entryPath);
ArchiveReader(){};
ArchiveReader(const std::string &archivePath, const std::string &entryPath);
ArchiveReader(ArchiveReader && other) = default;

~ArchiveReader();
Expand Down Expand Up @@ -127,7 +127,7 @@ class ArchiveReader
*/
std::string extension() const;

static std::vector<std::string> getEntryPaths(const std::string &archivePath, const std::string &entryBaseDirectory = std::string());
static std::vector<std::string> getEntryPaths(const std::string &archivePath, const std::string &entryBaseDirectory = std::string());

private:

Expand All @@ -141,7 +141,6 @@ class ArchiveReader
std::string _archivePath,
_entryPath;


};

#endif // ARCHIVEREADER_H
723 changes: 723 additions & 0 deletions CommonData/base64.h

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Desktop/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ target_include_directories(
$<$<BOOL:${FLATPAK_USED}>:/app/include/QtWebEngineQuick>
$<$<BOOL:${FLATPAK_USED}>:/app/include/QtWebEngineCore>
${LIBFREEXL_INCLUDE_DIRS}
${libsodium_INCLUDE_DIR}
)

target_include_directories(
Expand Down Expand Up @@ -175,6 +176,7 @@ target_link_libraries(
OpenSSL::Crypto
# FreeXL
${LIBFREEXL_LIBRARIES}
${libsodium_LIBRARIES}
$<$<NOT:$<BOOL:${LINUX}>>:freexl::freexl>
# ReadStat -----------------------------------
${LIBREADSTAT_LIBRARIES}
Expand Down
109 changes: 109 additions & 0 deletions Desktop/components/JASP/Widgets/EncryptionSettingsWindow.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import QtQuick
import QtQuick.Controls as QC
import QtQuick.Layouts
import JASP.Widgets
import JASP.Controls

Window
{
id: encryptWindow

width: contentColumn.implicitWidth + 50 * jaspTheme.uiScale
height: contentColumn.implicitHeight + 50 * jaspTheme.uiScale


// default property alias content: contentInfo.children
// property string labelcolor: "#F99800"
// property string closebuttoncolor: jaspTheme.blue

visible: encryptionModel.visible
title: qsTr("Enter Encryption Settings")

color: jaspTheme.white

signal closeModel();

onCloseModel:
{
encryptionModel.visible = false
encryptionModel.submit();
encryptWindow.close()
}

onClosing: closeModel()

onVisibleChanged: {
passwordInput.displayValue = ""
privateKey.displayValue = ""
publicKey.displayValue = ""
showAdvancedCheckbox.checked = false
jaspSubmission.checked = false
passwordInput.forceActiveFocus();
}

Shortcut { onActivated: closeModel(); sequences: ["Ctrl+Q", "Ctrl+W", Qt.Key_Close]; }

Connections
{
target: mainWindow
function onCloseWindows() { closeModel(); }
}

Column {
id: contentColumn
spacing: jaspTheme.groupContentPadding
anchors.centerIn: parent
anchors.margins: jaspTheme.contentMargin * 2

TextField {
id: passwordInput
text: qsTr("Password:")
width: 300 * preferencesModel.uiScale
control.echoMode: TextInput.Password
control.Keys.onReturnPressed: (event)=> { submitButton.onClicked() }
}

CheckBox {
id: jaspSubmission
text: qsTr("JASP Team Submission.")
}

CheckBox {
id: showAdvancedCheckbox
text: "Advanced Settings"
}

Group {
id: advancedSettings
visible: showAdvancedCheckbox.checked

TextField {
id: privateKey
label: "Private key (base64):"
placeholderText: ""
control.echoMode: TextInput.Password
}

TextField {
id: publicKey
label: "Receiver Public key (base64):"
placeholderText: ""
}
}

Button {
id: submitButton
text: qsTr("Submit")
width: parent.width
onClicked: {
encryptionModel.encryptionActive = true;
encryptionModel.password = passwordInput.displayValue;
encryptionModel.jaspSubmission = jaspSubmission.checked;
encryptionModel.publickey = publicKey.displayValue;
encryptionModel.privatekey = privateKey.displayValue
closeModel();
}
}

}
}
3 changes: 2 additions & 1 deletion Desktop/data/asyncloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "utils.h"
#include "osf/onlinedatamanager.h"
#include "log.h"
#include "exporters/exporter.h"

using namespace std;

Expand Down Expand Up @@ -122,7 +123,7 @@ void AsyncLoader::saveTask(FileEvent *event)
DataSetPackage::pkg()->doWalCheckPoint();

Exporter *exporter = event->exporter();
if (exporter) exporter->saveDataSet(fq(tempPath), boost::bind(&AsyncLoader::progressHandler, this, _1));
if (exporter) exporter->saveDataSet(fq(tempPath), boost::bind(&AsyncLoader::progressHandler, this, _1));
else throw runtime_error("No Exporter found!");

int attempts = 1;
Expand Down
2 changes: 1 addition & 1 deletion Desktop/data/exporters/dataexporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class DataExporter : public Exporter
public:
DataExporter(bool includeComputeColumns);
~DataExporter() override;
void saveDataSet(const std::string &path, std::function<void (int)> progressCallback) override;
void saveDataSet(const std::string &path, std::function<void (int)> progressCallback) override;

bool _includeComputeColumns;

Expand Down
3 changes: 2 additions & 1 deletion Desktop/data/exporters/exporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "timers.h"
#include "common.h"
#include "utils.h"
#include "data/fileevent.h"

///
/// Base class for all exporters
Expand All @@ -42,7 +43,7 @@ class Exporter

public:
virtual ~Exporter();
virtual void saveDataSet(const std::string &path, std::function<void (int)> progressCallback) = 0;
virtual void saveDataSet(const std::string &path, std::function<void (int)> progressCallback) = 0;

Utils::FileType getDefaultFileType();
Utils::FileTypeVector getAllowedFileTypes();
Expand Down
30 changes: 28 additions & 2 deletions Desktop/data/exporters/jaspexporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <archive_entry.h>
#include <json/json.h>
#include <fstream>
#include "data/jaspencryptiondata.h"
#include "data/jaspencrypt.h"
#include "version.h"
#include "tempfiles.h"
#include "log.h"
Expand All @@ -33,6 +35,8 @@
#include "appinfo.h"
#include "gui/preferencesmodel.h"

#include <utilities/desktopcommunicator.h>


const Version JASPExporter::jaspArchiveVersion = Version("5.0.0");
time_t JASPExporter::_now;
Expand All @@ -52,10 +56,18 @@ void JASPExporter::saveDataSet(const std::string &path, std::function<void(int)>
a = archive_write_new();
archive_write_set_format_zip(a);

std::filesystem::path tmpPath = path;
bool encrypt = JaspEncryptionData::getInstance()->encryptionActive();
if(encrypt) {
if(!JaspEncryptionData::getInstance()->paramsSet())
DesktopCommunicator::singleton()->queryEncryptionSettings();
tmpPath = std::filesystem::temp_directory_path() / ("_tmp_unlock_" + std::filesystem::path(path).filename().generic_string());
}

#ifdef _WIN32
if (archive_write_open_filename_w(a, tq(path).toStdWString().c_str()) != ARCHIVE_OK)
if (archive_write_open_filename_w(a, QString(tmpPath.c_str()).toStdWString().c_str()) != ARCHIVE_OK)
#else
if (archive_write_open_filename(a, path.c_str()) != ARCHIVE_OK)
if (archive_write_open_filename(a, tmpPath.c_str()) != ARCHIVE_OK)
#endif
throw std::runtime_error(std::string("File could not be opened because of ") + archive_error_string(a));

Expand All @@ -68,6 +80,20 @@ void JASPExporter::saveDataSet(const std::string &path, std::function<void(int)>
throw std::runtime_error("File could not be closed.");

archive_write_free(a);
if(encrypt) {
Json::Value root;
try {
auto privKey = JaspEncryptionData::getInstance()->getPrivatekey();
if(privKey.length()) //check if user want to use privkey or password to encrypt
JASPEncrypt::encrypt(tmpPath, path, privKey, root, JaspEncryptionData::getInstance()->getPublicKeyResponse(), JaspEncryptionData::getInstance()->getPasswordSaltResponse(), true);
else
JASPEncrypt::encrypt(tmpPath, path, JaspEncryptionData::getInstance()->getPassword(), root, JaspEncryptionData::getInstance()->getPublicKeyResponse());
} catch (std::exception& e) {
Log::log() << "Encryption failed: " << e.what() << std::endl;
throw std::runtime_error("Encryption failed. Click 'Save As' and save as normal Jasp File. \n\n" + std::string(" Technical Reason: ") + std::string(e.what()));
}
std::filesystem::remove(tmpPath);
}

//Make sure it is now always considered "loading" in DataSetPackage
DataSetPackage::pkg()->setLoaded(true);
Expand Down
2 changes: 1 addition & 1 deletion Desktop/data/exporters/jaspexporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class JASPExporter: public Exporter
static const Version dataArchiveVersion;

JASPExporter();
void saveDataSet(const std::string &path, std::function<void (int)> progressCallback) override;
void saveDataSet(const std::string &path, std::function<void (int)> progressCallback) override;

private:
static void saveManifest( archive * a);
Expand Down
2 changes: 1 addition & 1 deletion Desktop/data/exporters/resultexporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ResultExporter: public Exporter
{
public:
ResultExporter();
void saveDataSet(const std::string &path, std::function<void (int)> progressCallback) OVERRIDE;
void saveDataSet(const std::string &path, std::function<void (int)> progressCallback) OVERRIDE;

private:
bool prepareForExport();
Expand Down
6 changes: 6 additions & 0 deletions Desktop/data/fileevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
// <http://www.gnu.org/licenses/>.
//

#include "fileevent.h"
#include "exporters/exporter.h"
#include "exporters/dataexporter.h"
#include "exporters/resultexporter.h"
#include "exporters/jaspexporter.h"

#include <QTimer>
#include "fileevent.h"
#include "processinfo.h"
Expand Down
5 changes: 3 additions & 2 deletions Desktop/data/fileevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@

#include <QObject>
#include <QMetaType>

#include "exporters/exporter.h"
#include "json/json.h"
#include "utilenums.h"

class Exporter;

///
/// This class is used to handle the communication to and from the asynchronous loading/synching/saving file processes.
/// These can be chained to have a Close come after a save once the latter is done.
Expand Down
Loading
Loading