diff --git a/core/qthelper.cpp b/core/qthelper.cpp index e5a9285aa..8fbfc0cbc 100644 --- a/core/qthelper.cpp +++ b/core/qthelper.cpp @@ -1351,27 +1351,34 @@ fraction_t string_to_fraction(const char *str) return fraction; } -int getCloudURL(QString &filename) +// Sadly, the standard C++ library's regexp support is mediocre at best. +static void sanitize_email(std::string &email) { - QString email = QString(prefs.cloud_storage_email); - email.replace(QRegularExpression("[^a-zA-Z0-9@._+-]"), ""); - if (email.isEmpty() || empty_string(prefs.cloud_storage_password)) - return report_error("Please configure Cloud storage email and password in the preferences"); - if (email != prefs.cloud_storage_email_encoded) { - free((void *)prefs.cloud_storage_email_encoded); - prefs.cloud_storage_email_encoded = copy_qstring(email); + size_t j = 0; + for (char c: email) { + if (isalnum(c) || c == '@' || c == '.' || + c == '_' || c == '+' || c == '-') + email[j++] = c; } - filename = QString(QString(prefs.cloud_base_url) + "git/%1[%1]").arg(email); - if (verbose) - qDebug() << "returning cloud URL" << filename; - return 0; + email.resize(j); } -extern "C" char *cloud_url() +std::optional getCloudURL() { - QString filename; - getCloudURL(filename); - return copy_qstring(filename); + std::string email(prefs.cloud_storage_email); + sanitize_email(email); + if (email.empty() || empty_string(prefs.cloud_storage_password)) { + report_error("Please configure Cloud storage email and password in the preferences"); + return {}; + } + if (email != prefs.cloud_storage_email_encoded) { + free((void *)prefs.cloud_storage_email_encoded); + prefs.cloud_storage_email_encoded = strdup(email.c_str()); + } + std::string filename = std::string(prefs.cloud_base_url) + "git/" + email + "[" + email + "]"; + if (verbose) + report_info("returning cloud URL %s", filename.c_str()); + return filename; } extern "C" void subsurface_mkdir(const char *dir) diff --git a/core/qthelper.h b/core/qthelper.h index c06846a58..ef1b4f337 100644 --- a/core/qthelper.h +++ b/core/qthelper.h @@ -20,6 +20,8 @@ enum watertypes {FRESHWATER, BRACKISHWATER, EN13319WATER, SALTWATER, DC_WATERTYP #ifdef __cplusplus #include +#include +#include #include "core/gettextfromc.h" class QImage; @@ -41,7 +43,7 @@ void write_hashes(); QString thumbnailFileName(const QString &filename); void learnPictureFilename(const QString &originalName, const QString &localName); QString localFilePath(const QString &originalFilename); -int getCloudURL(QString &filename); +std::optional getCloudURL(); // move to prefs.h, probably. bool parseGpsText(const QString &gps_text, double *latitude, double *longitude); void init_proxy(); QStringList getWaterTypesAsString(); @@ -127,7 +129,6 @@ void updateWindowTitle(); void subsurface_mkdir(const char *dir); void copy_image_and_overwrite(const char *cfileName, const char *path, const char *cnewName); const char *local_file_path(struct picture *picture); -char *cloud_url(); char *hashfile_name_string(); enum deco_mode decoMode(bool in_planner); void parse_seabear_header(const char *filename, struct xml_params *params); diff --git a/core/subsurfacestartup.cpp b/core/subsurfacestartup.cpp index 443552243..e91a340bc 100644 --- a/core/subsurfacestartup.cpp +++ b/core/subsurfacestartup.cpp @@ -46,25 +46,23 @@ extern "C" void print_version() extern "C" void print_files() { struct git_info info; - const char *filename; + std::optional filename; printf("\nFile locations:\n\n"); printf("Cloud email:%s\n", prefs.cloud_storage_email); if (!empty_string(prefs.cloud_storage_email) && !empty_string(prefs.cloud_storage_password)) { - filename = cloud_url(); - - is_git_repository(filename, &info); - } else { - /* strdup so the free below works in either case */ - filename = strdup("No valid cloud credentials set.\n"); + filename = getCloudURL(); + if (filename) + is_git_repository(filename->c_str(), &info); } + if (!filename) + filename = std::string("No valid cloud credentials set.\n"); if (!info.localdir.empty()) { printf("Local git storage: %s\n", info.localdir.c_str()); } else { printf("Unable to get local git directory\n"); } - printf("Cloud URL: %s\n", filename); - free((void *)filename); + printf("Cloud URL: %s\n", filename->c_str()); char *tmp = hashfile_name_string(); printf("Image filename table: %s\n", tmp); free(tmp); diff --git a/desktop-widgets/mainwindow.cpp b/desktop-widgets/mainwindow.cpp index 02aadcdfe..6a42ab49f 100644 --- a/desktop-widgets/mainwindow.cpp +++ b/desktop-widgets/mainwindow.cpp @@ -404,17 +404,17 @@ void MainWindow::on_actionCloudstorageopen_triggered() if (!okToClose(tr("Please save or cancel the current dive edit before opening a new file."))) return; - QString filename; - if (getCloudURL(filename)) + auto filename = getCloudURL(); + if (!filename) return; if (verbose) - qDebug() << "Opening cloud storage from:" << filename; + report_info("Opening cloud storage from: %s", filename->c_str()); closeCurrentFile(); showProgressBar(); - QByteArray fileNamePtr = QFile::encodeName(filename); + QByteArray fileNamePtr = QFile::encodeName(QString::fromStdString(*filename)); if (!parse_file(fileNamePtr.data(), &divelog)) setCurrentFile(fileNamePtr.toStdString()); process_loaded_dives(); @@ -435,23 +435,23 @@ static bool saveToCloudOK() void MainWindow::on_actionCloudstoragesave_triggered() { - QString filename; if (!saveToCloudOK()) return; - if (getCloudURL(filename)) + auto filename = getCloudURL(); + if (!filename) return; if (verbose) - qDebug() << "Saving cloud storage to:" << filename; + report_info("Saving cloud storage to: %s", filename->c_str()); mainTab->stealFocus(); // Make sure that any currently edited field is updated before saving. showProgressBar(); - int error = save_dives(qPrintable(filename)); + int error = save_dives(filename->c_str()); hideProgressBar(); if (error) return; - setCurrentFile(filename.toStdString()); + setCurrentFile(*filename); Command::setClean(); } diff --git a/mobile-widgets/qmlmanager.cpp b/mobile-widgets/qmlmanager.cpp index eb608fe31..f2224e1ab 100644 --- a/mobile-widgets/qmlmanager.cpp +++ b/mobile-widgets/qmlmanager.cpp @@ -567,11 +567,11 @@ void QMLManager::finishSetup() // Initialize cloud credentials. git_local_only = !prefs.cloud_auto_sync; - QString url; + std::optional url; if (!qPrefCloudStorage::cloud_storage_email().isEmpty() && !qPrefCloudStorage::cloud_storage_password().isEmpty() && - getCloudURL(url) == 0) { - openLocalThenRemote(url); + (url = getCloudURL())) { + openLocalThenRemote(QString::fromStdString(*url)); } else if (!existing_filename.empty() && qPrefCloudStorage::cloud_verification_status() != qPrefCloudStorage::CS_UNKNOWN) { rememberOldStatus(); @@ -781,13 +781,13 @@ void QMLManager::deleteAccount() void QMLManager::loadDivesWithValidCredentials() { - QString url; - if (getCloudURL(url)) { + auto url = getCloudURL(); + if (!url) { setStartPageText(RED_FONT + tr("Cloud storage error: %1").arg(consumeError()) + END_FONT); revertToNoCloudIfNeeded(); return; } - QByteArray fileNamePrt = QFile::encodeName(url); + QByteArray fileNamePrt = QFile::encodeName(QString::fromStdString(*url)); struct git_info info; int error; diff --git a/subsurface-desktop-main.cpp b/subsurface-desktop-main.cpp index da843913c..d15f946f5 100644 --- a/subsurface-desktop-main.cpp +++ b/subsurface-desktop-main.cpp @@ -89,9 +89,9 @@ int main(int argc, char **argv) if (!defaultFile.isEmpty()) files.push_back(QString(prefs.default_filename)); } else if (prefs.default_file_behavior == CLOUD_DEFAULT_FILE) { - QString cloudURL; - if (getCloudURL(cloudURL) == 0) - files.push_back(cloudURL); + auto cloudURL = getCloudURL(); + if (cloudURL) + files.push_back(QString::fromStdString(*cloudURL)); } } MainWindow *m = MainWindow::instance(); diff --git a/subsurface-downloader-main.cpp b/subsurface-downloader-main.cpp index c4b7d6ba9..f5f131941 100644 --- a/subsurface-downloader-main.cpp +++ b/subsurface-downloader-main.cpp @@ -84,9 +84,9 @@ int main(int argc, char **argv) if (!defaultFile.isEmpty()) files.push_back(QString(prefs.default_filename)); } else if (prefs.default_file_behavior == CLOUD_DEFAULT_FILE) { - QString cloudURL; - if (getCloudURL(cloudURL) == 0) - files.push_back(cloudURL); + auto cloudURL = getCloudURL(); + if (cloudURL) + files.push_back(QString::fromStdString(*cloudURL)); } } if (!files.isEmpty()) {