Mercurial > hg > syntilista
diff src/main.cpp @ 142:36c9cb759326
Implement simple SQLite database backup at program exit using Qt HTTP/HTTPS
and a PHP script on the remote server. Needs more work, testing and better
error handling.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 24 Aug 2017 15:44:33 +0300 |
parents | 783417da6da3 |
children | 75a4faa219a9 |
line wrap: on
line diff
--- a/src/main.cpp Thu Aug 24 13:16:09 2017 +0300 +++ b/src/main.cpp Thu Aug 24 15:44:33 2017 +0300 @@ -11,7 +11,6 @@ #include <QSettings> #include <QPrintDialog> #include <QPrintPreviewDialog> -#include <QProgressDialog> #include <QStandardPaths> #include "main.h" #include "ui_mainwindow.h" @@ -246,8 +245,15 @@ settings.uiPos = tmpst.value("pos", QPoint(100, 100)).toPoint(); settings.uiSize = tmpst.value("size", QSize(1000, 600)).toSize(); settings.uiScale = tmpst.value("scale", 1.0f).toDouble(); - settings.dbBackupURL = tmpst.value("dbBackupURL", "").toString(); - settings.dbBackupSecret = tmpst.value("dbBackupSecret", "").toString(); + settings.dbBackupURL = tmpst.value("dbBackupURL", QString()).toString(); + settings.dbBackupSecret = tmpst.value("dbBackupSecret", QString()).toString(); + + // Check commandline arguments for configuring backup settings + if (argc >= 4 && strcmp(argv[1], "config") == 0) + { + settings.dbBackupURL = QString(argv[2]); + settings.dbBackupSecret = QString(argv[3]); + } // // Create logfile and data directory @@ -319,7 +325,6 @@ { // Setup UI ui->setupUi(this); - backupDialog = NULL; // Restore window size and position move(settings.uiPos); @@ -431,6 +436,139 @@ // Commit and close database QSqlDatabase::database().commit(); QSqlDatabase::database().close(); + + // Back up the database + backupDatabase(); +} + + +void SyntilistaMainWindow::backupDatabase() +{ + QString dbFilename = settings.dataPath + QDir::separator() + APP_SQLITE_FILE; + QString backupFilename = APP_SQLITE_FILE; + backupReply = NULL; + backupDialog = NULL; + + if (settings.dbBackupURL == QString() || settings.dbBackupURL == "") + { + slLog("ERROR", QStringLiteral("Database backup URL not set in configuration.")); + return; + } + + if (settings.dbBackupSecret == QString() || settings.dbBackupSecret == "") + { + slLog("ERROR", QStringLiteral("Database backup secret key not set in configuration.")); + return; + } + + // Check for network access + QNetworkAccessManager *manager = new QNetworkAccessManager(); + if (manager->networkAccessible() != QNetworkAccessManager::Accessible) + { + slLog("ERROR", QStringLiteral("Network not available, cannot backup the database.")); + return; + } + + // Attempt to open the database file + QFile *file = new QFile(dbFilename); + if (!file->open(QIODevice::ReadOnly)) + { + slLog("ERROR", QStringLiteral("Failed to open database file '%1' for backup.").arg(dbFilename)); + return; + } + + // Okay, we seem to be "go" .. + slLog("INFO", + QStringLiteral("Attempting database backup from '%1' to '%2'."). + arg(dbFilename).arg(settings.dbBackupURL)); + + // Create the HTTP POST request + QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + + // The "secret" key as POST parameter + QHttpPart postPart; + postPart.setHeader(QNetworkRequest::ContentDispositionHeader, + QVariant("form-data; name=\"secret\";")); + postPart.setBody(QByteArray(settings.dbBackupSecret.toUtf8())); + + // Actual data as binary octet-stream + QHttpPart dataPart; + dataPart.setHeader(QNetworkRequest::ContentTypeHeader, + QVariant("binary/octet-stream")); + + dataPart.setHeader(QNetworkRequest::ContentDispositionHeader, + QVariant("form-data; name=\"file\"; filename=\""+ backupFilename +"\"")); + + dataPart.setBodyDevice(file); + file->setParent(multiPart); // we cannot delete the QFile object now, so delete it with the multiPart + + multiPart->append(postPart); + multiPart->append(dataPart); + + // Attempt to POST the whole thing + QUrl url(settings.dbBackupURL); + QNetworkRequest request(url); + backupReply = manager->post(request, multiPart); + multiPart->setParent(backupReply); + + connect( + backupReply, + SIGNAL(finished()), + this, + SLOT(backupFinished())); + + connect( + backupReply, + SIGNAL(uploadProgress(qint64, qint64)), + this, + SLOT(backupProgress(qint64, qint64))); + + // Create progress dialog + backupDialog = new QProgressDialog( + tr("Varmuuskopioidaan tietokantaa ..."), + QString(), + 0, + 100, + this); + + backupDialog->setAttribute(Qt::WA_DeleteOnClose); + backupDialog->setAutoClose(false); + backupDialog->setWindowModality(Qt::ApplicationModal); + backupDialog->exec(); +} + + +void SyntilistaMainWindow::backupProgress(qint64 bytesSent, qint64 bytesTotal) +{ + if (bytesTotal > 0) + { + slLog("INFO", + QStringLiteral("Backup sent %1 / %2 bytes."). + arg(bytesSent). + arg(bytesTotal)); + + backupDialog->setValue((bytesSent * 100) / bytesTotal); + } +} + + +void SyntilistaMainWindow::backupError(QNetworkReply::NetworkError code) +{ + slLog("ERROR", + QStringLiteral("Backup failed with network error %1.\n"). + arg(code) + ); +} + + +void SyntilistaMainWindow::backupFinished() +{ + if (backupReply) + { + slLog("PAF", QString::fromUtf8(backupReply->readAll())); + } + slLog("INFO", "Backup finished."); + backupDialog->close(); }