diff -Nru datovka-4.8.3/AUTHORS datovka-4.9.3/AUTHORS --- datovka-4.8.3/AUTHORS 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/AUTHORS 2017-09-06 11:49:23.000000000 +0000 @@ -13,8 +13,8 @@ * PROJECT COORDINATOR: ---------------------- +- Ladislav Lhotka - Ondrej Sury -- Bedrich Kosata * APPLICATION DEVELOPERS: ------------------------- @@ -25,3 +25,7 @@ -------------------------- - Martin Straka - Karel Slany + +* FORMER PROJECT MEMBERS: +------------------------- +- Bedrich Kosata diff -Nru datovka-4.8.3/ChangeLog datovka-4.9.3/ChangeLog --- datovka-4.8.3/ChangeLog 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/ChangeLog 2017-09-06 11:49:23.000000000 +0000 @@ -1,3 +1,45 @@ +4.9.3 / 2017-09-06 + * Fixed a problem when message list was not updated after account + synchronisation when a message was selected. + * Fixed a bug when database location may have been saved even though the + databases reside in default location. This problem was visible especially + on Windows. + +4.9.2 / 2017-08-28 + * Changed tag dialogue to contain two views when editing tag assignment. + * Using the prefix 'ODZ_' for sent and 'DDZ_' for received data messages when + uploading them into records management service. + * Default documentation location can be changed when running qmake using the + TEXT_FILES_INST_DIR variable. + * Full-text data-box search does not block the search dialogue. + * Full-text data-box search can be interrupted and restarted again without + closing the dialogue. + * Separated core and GUI code. Removed models from database interface. + * Added new CLI option '--get-msg-ids'. + * Command-line application without GUI can be built separately. This + executable is going to be distributed in Windows packages together with the + GUI application. + +4.9.1 / 2017-07-26 + * Added experimental support for new data-box and user types that are going + to be introduced into the ISDS production environment and which are already + present in the ISDS testing environment. + Version 0.10.7 of libisds is required to build the application. + * Updated building scripts for the Windows application to automatically pull + Qt dependencies into the package. + * Fixed issue when records management data have not been erased from message + model after the service has been deactivated. + * Fixed issues with records management logo not being displayed in message + list immediately after the service has been set up. + * Alphabetically sorting nodes of records management hierarchy. + * Sub-nodes of matching element are also displayed when filtering hierarchy of + records management service. + * Removed inactive mojeid-datovka code from the sources. + +4.9.0 / 2017-06-30 + * Added API and support for sending messages into records management services. + * Removed explicit clear buttons from filter fields. + 4.8.3 / 2017-06-13 * Fixed problems with remembering location of saved attachment files. * Directory structure can be created when exporting correspondence overview. @@ -207,7 +249,7 @@ * Messages can be imported from a existing older database file. * Fixed problem when entering wrong password for the first time, then the application remembered the wrong password. - * Fixed problem when the application saved the account password even thou it + * Fixed problem when the application saved the account password even though it shouldn't be saved. * When saving files then the sender name can be used. * Fixed problem with saving messages that contain illegal characters. Illegal diff -Nru datovka-4.8.3/datovka-cli.pro.noauto datovka-4.9.3/datovka-cli.pro.noauto --- datovka-4.8.3/datovka-cli.pro.noauto 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/datovka-cli.pro.noauto 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,167 @@ + +QT += core network sql +CONFIG += console + +TEMPLATE = app +APP_NAME = datovka-cli + +include(pri/version.pri) +include(pri/check_qt_version.pri) + +sufficientQtVersion(5, 2, 3, 2) + +DEFINES += \ + DEBUG=1 \ + VERSION=\\\"$${VERSION}\\\" + +QMAKE_CXXFLAGS = \ + -g -O0 -std=c++11 \ + -Wall -Wextra -pedantic \ + -Wdate-time -Wformat -Werror=format-security + +INCLUDEPATH += \ + . + +LIBS = \ + -lisds + +isEqual(STATIC, 1) { + warning(Linking statically.) +} else { + INCLUDEPATH += \ + /usr/include/libxml2 +} + +!isEmpty(PORTABLE_APPLICATION) { + warning(Building portable version.) + DEFINES += PORTABLE_APPLICATION=1 + TARGET = $${APP_NAME}-portable +} + +!isEmpty(DISABLE_VERSION_CHECK_BY_DEFAULT) { + warning(Disabling version check by default.) + DEFINES += DISABLE_VERSION_CHECK_BY_DEFAULT=1 +} + +win32 { + RC_FILE += res/icon.rc + + DEFINES += WIN32=1 + + INCLUDEPATH = \ + src \ + mingw32built/include/libxml2 \ + mingw32built/include/ + + LIBS = \ + $${_PRO_FILE_PWD_}/mingw32built/bin/libisds-5.dll \ + $${_PRO_FILE_PWD_}/mingw32built/bin/libeay32.dll + + SOURCES += src/compat/compat_win.c + + HEADERS += src/compat/compat_win.h +} else { + LIBS += \ + -lcrypto +} + +SOURCES += \ + src/about.cpp \ + src/cli/cli.cpp \ + src/cli/cli_login.cpp \ + src/cli/cli_parser.cpp \ + src/common.cpp \ + src/crypto/crypto.c \ + src/crypto/crypto_threads.cpp \ + src/initialisation.cpp \ + src/io/account_db.cpp \ + src/io/db_tables.cpp \ + src/io/dbs.cpp \ + src/io/file_downloader.cpp \ + src/io/filesystem.cpp \ + src/io/isds_helper.cpp \ + src/io/isds_login.cpp \ + src/io/isds_sessions.cpp \ + src/io/message_db.cpp \ + src/io/message_db_set.cpp \ + src/io/message_db_set_container.cpp \ + src/io/message_db_set_delegated.cpp \ + src/io/records_management_db.cpp \ + src/io/sqlite/db.cpp \ + src/io/sqlite/table.cpp \ + src/io/tag_db.cpp \ + src/isds/isds_conversion.cpp \ + src/model_interaction/account_interaction.cpp \ + src/localisation/localisation.cpp \ + src/log/log.cpp \ + src/log/log_c.cpp \ + src/main_cli.cpp \ + src/settings/account.cpp \ + src/settings/accounts.cpp \ + src/settings/preferences.cpp \ + src/settings/proxy.cpp \ + src/single/single_instance.cpp \ + src/worker/message_emitter.cpp \ + src/worker/pool.cpp \ + src/worker/task.cpp \ + src/worker/task_download_message.cpp \ + src/worker/task_download_message_list.cpp \ + src/worker/task_download_owner_info.cpp \ + src/worker/task_download_password_info.cpp \ + src/worker/task_download_user_info.cpp \ + src/worker/task_search_owner.cpp + +HEADERS += \ + src/about.h \ + src/cli/cli.h \ + src/cli/cli_login.h \ + src/cli/cli_parser.h \ + src/common.h \ + src/crypto/crypto.h \ + src/crypto/crypto_funcs.h \ + src/crypto/crypto_threads.h \ + src/initialisation.h \ + src/io/account_db.h \ + src/io/db_tables.h \ + src/io/dbs.h \ + src/io/file_downloader.h \ + src/io/filesystem.h \ + src/io/isds_helper.h \ + src/io/isds_login.h \ + src/io/isds_sessions.h \ + src/io/message_db.h \ + src/io/message_db_set.h \ + src/io/message_db_set_container.h \ + src/io/records_management_db.h \ + src/io/sqlite/db.h \ + src/io/sqlite/table.h \ + src/io/tag_db.h \ + src/isds/isds_conversion.h \ + src/model_interaction/account_interaction.h \ + src/localisation/localisation.h \ + src/log/log_c.h \ + src/log/log_common.h \ + src/log/log.h \ + src/settings/account.h \ + src/settings/accounts.h \ + src/settings/preferences.h \ + src/settings/proxy.h \ + src/single/single_instance.h \ + src/worker/message_emitter.h \ + src/worker/pool.h \ + src/worker/task.h \ + src/worker/task_download_message.h \ + src/worker/task_download_message_list.h \ + src/worker/task_download_owner_info.h \ + src/worker/task_download_password_info.h \ + src/worker/task_download_user_info.h \ + src/worker/task_search_owner.h + +FORMS += + +RESOURCES += \ + +TRANSLATIONS += locale/datovka_en.ts \ + locale/datovka_cs.ts + +OTHER_FILES += diff -Nru datovka-4.8.3/datovka.pro datovka-4.9.3/datovka.pro --- datovka-4.8.3/datovka.pro 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/datovka.pro 2017-09-06 11:49:23.000000000 +0000 @@ -4,13 +4,14 @@ # #------------------------------------------------- -QT += core gui network sql +QT += core gui network svg sql widgets QT += printsupport TEMPLATE = app APP_NAME = datovka -# VERSION must contain only three dot-separated numbers because of OS X deployment. -VERSION = 4.8.3 + +include(pri/version.pri) +include(pri/check_qt_version.pri) # Generate localisation. Must be run manually. #system(lrelease datovka.pro) @@ -25,40 +26,9 @@ system(copy $$[QT_INSTALL_DATA]/translations/qtbase_cs.qm locale/qtbase_cs.qm) } - -# Required Qt versions -REQUIRED_MAJOR = 5 -REQUIRED_MINOR = 3 # Qt 5.2.1 contains a bug causing the application to crash on some drop events. # Version 5.3.2 should be fine. -ADVISED_MINOR = 3 -ADVISED_PATCH = 2 - -lessThan(QT_MAJOR_VERSION, $${REQUIRED_MAJOR}) { - error(Qt version $${REQUIRED_MAJOR}.$${REQUIRED_MINOR} is required.) -} else { - QT += widgets -} - -isEqual(QT_MAJOR_VERSION, $${REQUIRED_MAJOR}) { - lessThan(QT_MINOR_VERSION, $${REQUIRED_MINOR}) { - error(Qt version $${REQUIRED_MAJOR}.$${REQUIRED_MINOR} is required.) - } - - lessThan(QT_MINOR_VERSION, $${ADVISED_MINOR}) { - warning(Qt version at least $${REQUIRED_MAJOR}.$${ADVISED_MINOR}.$${ADVISED_PATCH} is suggested.) - } else { - isEqual(QT_MINOR_VERSION, $${ADVISED_MINOR}) { - lessThan(QT_PATCH_VERSION, $${ADVISED_PATCH}) { - warning(Qt version at least $${REQUIRED_MAJOR}.$${ADVISED_MINOR}.$${ADVISED_PATCH} is suggested.) - } - } - } -} else { - warning(The current Qt version $${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION} may not work.) -} - -#LIBISDS_PREFIX = "$$HOME/third_party/built" +sufficientQtVersion(5, 3, 3, 2) DEFINES += \ DEBUG=1 \ @@ -72,7 +42,9 @@ BINDIR="$${PREFIX}/bin" DATADIR="$${PREFIX}/share" - TEXT_FILES_INST_DIR = "$${DATADIR}/doc/$${APP_NAME}" + isEmpty(TEXT_FILES_INST_DIR) { + TEXT_FILES_INST_DIR = "$${DATADIR}/doc/$${APP_NAME}" + } LOCALE_INST_DIR = "$${DATADIR}/$${APP_NAME}/localisations" application.target = $${APP_NAME} @@ -113,8 +85,7 @@ additional.path = "$${TEXT_FILES_INST_DIR}" additional.files = \ AUTHORS \ - COPYING \ - README + COPYING DEFINES += DATADIR=\\\"$$DATADIR\\\" \ PKGDATADIR=\\\"$$PKGDATADIR\\\" \ @@ -141,6 +112,7 @@ QMAKE_CXXFLAGS = \ -g -O0 -std=c++11 \ -Wall -Wextra -pedantic \ + -Wdate-time -Wformat -Werror=format-security \ -Isrc/views INCLUDEPATH += \ @@ -255,14 +227,17 @@ } SOURCES += \ + src/about.cpp \ src/cli/cli.cpp \ src/cli/cli_login.cpp \ + src/cli/cli_parser.cpp \ src/common.cpp \ src/crypto/crypto.c \ src/crypto/crypto_threads.cpp \ src/delegates/tag_item.cpp \ src/delegates/tags_delegate.cpp \ src/dimensions/dimensions.cpp \ + src/graphics/graphics.cpp \ src/gui/datovka.cpp \ src/gui/dlg_about.cpp \ src/gui/dlg_account_from_db.cpp \ @@ -274,11 +249,10 @@ src/gui/dlg_ds_search.cpp \ src/gui/dlg_import_zfo.cpp \ src/gui/dlg_import_zfo_result.cpp \ - src/gui/dlg_login_mojeid.cpp \ + src/gui/dlg_msg_box_informative.cpp \ src/gui/dlg_msg_search.cpp \ src/gui/dlg_preferences.cpp \ src/gui/dlg_proxysets.cpp \ - src/gui/dlg_search_mojeid.cpp \ src/gui/dlg_send_message.cpp \ src/gui/dlg_signature_detail.cpp \ src/gui/dlg_tag.cpp \ @@ -286,6 +260,7 @@ src/gui/dlg_timestamp_expir.cpp \ src/gui/dlg_view_zfo.cpp \ src/gui/dlg_yes_no_checkbox.cpp \ + src/initialisation.cpp \ src/io/account_db.cpp \ src/io/db_tables.cpp \ src/io/dbs.cpp \ @@ -301,15 +276,16 @@ src/io/message_db_set_container.cpp \ src/io/message_db_set_delegated.cpp \ src/io/message_db_single.cpp \ + src/io/records_management_db.cpp \ src/io/sqlite/db.cpp \ src/io/sqlite/table.cpp \ src/io/tag_db.cpp \ - src/io/tag_db_container.cpp \ - src/io/wd_sessions.cpp \ + src/isds/isds_conversion.cpp \ src/localisation/localisation.cpp \ src/log/log.cpp \ src/log/log_c.cpp \ src/main.cpp \ + src/model_interaction/account_interaction.cpp \ src/model_interaction/attachment_interaction.cpp \ src/models/accounts_model.cpp \ src/models/combo_box_model.cpp \ @@ -319,9 +295,25 @@ src/models/sort_filter_proxy_model.cpp \ src/models/table_model.cpp \ src/models/tags_model.cpp \ + src/records_management/conversion.cpp \ + src/records_management/gui/dlg_records_management.cpp \ + src/records_management/gui/dlg_records_management_stored.cpp \ + src/records_management/gui/dlg_records_management_upload.cpp \ + src/records_management/io/records_management_connection.cpp \ + src/records_management/json/entry_error.cpp \ + src/records_management/json/helper.cpp \ + src/records_management/json/service_info.cpp \ + src/records_management/json/stored_files.cpp \ + src/records_management/json/upload_file.cpp \ + src/records_management/json/upload_hierarchy.cpp \ + src/records_management/models/upload_hierarchy_model.cpp \ + src/records_management/models/upload_hierarchy_proxy_model.cpp \ + src/records_management/widgets/svg_view.cpp \ + src/settings/account.cpp \ src/settings/accounts.cpp \ src/settings/preferences.cpp \ src/settings/proxy.cpp \ + src/settings/records_management.cpp \ src/single/single_instance.cpp \ src/views/attachment_table_view.cpp \ src/views/lowered_table_view.cpp \ @@ -330,8 +322,6 @@ src/views/table_home_end_filter.cpp \ src/views/table_key_press_filter.cpp \ src/views/table_space_selection_filter.cpp \ - src/web/net.cpp \ - src/web/json.cpp \ src/worker/message_emitter.cpp \ src/worker/pool.cpp \ src/worker/task.cpp \ @@ -339,30 +329,27 @@ src/worker/task_change_pwd.cpp \ src/worker/task_download_credit_info.cpp \ src/worker/task_download_message.cpp \ - src/worker/task_download_message_mojeid.cpp \ src/worker/task_download_message_list.cpp \ - src/worker/task_download_message_list_mojeid.cpp \ src/worker/task_download_owner_info.cpp \ src/worker/task_download_password_info.cpp \ src/worker/task_download_user_info.cpp \ src/worker/task_erase_message.cpp \ - src/worker/task_get_account_list_mojeid.cpp \ src/worker/task_import_message.cpp \ src/worker/task_import_zfo.cpp \ src/worker/task_keep_alive.cpp \ + src/worker/task_records_management_stored_messages.cpp \ src/worker/task_search_owner.cpp \ src/worker/task_search_owner_fulltext.cpp \ src/worker/task_send_message.cpp \ - src/worker/task_send_message_mojeid.cpp \ src/worker/task_split_db.cpp \ - src/worker/task_sync_mojeid.cpp \ - src/worker/task_tag_sync_mojeid.cpp \ src/worker/task_vacuum_db_set.cpp \ src/worker/task_verify_message.cpp HEADERS += \ + src/about.h \ src/cli/cli.h \ src/cli/cli_login.h \ + src/cli/cli_parser.h \ src/common.h \ src/crypto/crypto.h \ src/crypto/crypto_funcs.h \ @@ -370,6 +357,7 @@ src/delegates/tag_item.h \ src/delegates/tags_delegate.h \ src/dimensions/dimensions.h \ + src/graphics/graphics.h \ src/gui/datovka.h \ src/gui/dlg_about.h \ src/gui/dlg_account_from_db.h \ @@ -381,11 +369,10 @@ src/gui/dlg_ds_search.h \ src/gui/dlg_import_zfo.h \ src/gui/dlg_import_zfo_result.h \ - src/gui/dlg_login_mojeid.h \ + src/gui/dlg_msg_box_informative.h \ src/gui/dlg_msg_search.h \ src/gui/dlg_preferences.h \ src/gui/dlg_proxysets.h \ - src/gui/dlg_search_mojeid.h \ src/gui/dlg_send_message.h \ src/gui/dlg_signature_detail.h \ src/gui/dlg_tag.h \ @@ -393,6 +380,7 @@ src/gui/dlg_timestamp_expir.h \ src/gui/dlg_view_zfo.h \ src/gui/dlg_yes_no_checkbox.h \ + src/initialisation.h \ src/io/account_db.h \ src/io/db_tables.h \ src/io/dbs.h \ @@ -407,15 +395,16 @@ src/io/message_db_set.h \ src/io/message_db_set_container.h \ src/io/message_db_single.h \ + src/io/records_management_db.h \ src/io/sqlite/db.h \ src/io/sqlite/table.h \ src/io/tag_db.h \ - src/io/tag_db_container.h \ - src/io/wd_sessions.h \ + src/isds/isds_conversion.h \ src/localisation/localisation.h \ src/log/log_c.h \ src/log/log_common.h \ src/log/log.h \ + src/model_interaction/account_interaction.h \ src/model_interaction/attachment_interaction.h \ src/models/accounts_model.h \ src/models/combo_box_model.h \ @@ -425,9 +414,25 @@ src/models/sort_filter_proxy_model.h \ src/models/table_model.h \ src/models/tags_model.h \ + src/records_management/conversion.h \ + src/records_management/gui/dlg_records_management.h \ + src/records_management/gui/dlg_records_management_stored.h \ + src/records_management/gui/dlg_records_management_upload.h \ + src/records_management/io/records_management_connection.h \ + src/records_management/json/entry_error.h \ + src/records_management/json/helper.h \ + src/records_management/json/service_info.h \ + src/records_management/json/stored_files.h \ + src/records_management/json/upload_file.h \ + src/records_management/json/upload_hierarchy.h \ + src/records_management/models/upload_hierarchy_model.h \ + src/records_management/models/upload_hierarchy_proxy_model.h \ + src/records_management/widgets/svg_view.h \ + src/settings/account.h \ src/settings/accounts.h \ src/settings/preferences.h \ src/settings/proxy.h \ + src/settings/records_management.h \ src/single/single_instance.h \ src/views/attachment_table_view.h \ src/views/lowered_table_view.h \ @@ -436,9 +441,6 @@ src/views/table_home_end_filter.h \ src/views/table_key_press_filter.h \ src/views/table_space_selection_filter.h \ - src/web/net.h \ - src/web/net_consts.h \ - src/web/json.h \ src/worker/message_emitter.h \ src/worker/pool.h \ src/worker/task.h \ @@ -446,24 +448,19 @@ src/worker/task_change_pwd.h \ src/worker/task_download_credit_info.h \ src/worker/task_download_message.h \ - src/worker/task_download_message_mojeid.h \ src/worker/task_download_message_list.h \ - src/worker/task_download_message_list_mojeid.h \ src/worker/task_download_owner_info.h \ src/worker/task_download_password_info.h \ src/worker/task_download_user_info.h \ src/worker/task_erase_message.h \ - src/worker/task_get_account_list_mojeid.h \ src/worker/task_import_message.h \ src/worker/task_import_zfo.h \ src/worker/task_keep_alive.h \ + src/worker/task_records_management_stored_messages.h \ src/worker/task_search_owner.h \ src/worker/task_search_owner_fulltext.h \ src/worker/task_send_message.h \ - src/worker/task_send_message_mojeid.h \ src/worker/task_split_db.h \ - src/worker/task_sync_mojeid.h \ - src/worker/task_tag_sync_mojeid.h \ src/worker/task_vacuum_db_set.h \ src/worker/task_verify_message.h @@ -479,17 +476,18 @@ src/gui/ui/dlg_ds_search.ui \ src/gui/ui/dlg_import_zfo_result.ui \ src/gui/ui/dlg_import_zfo.ui \ - src/gui/ui/dlg_login_mojeid.ui \ src/gui/ui/dlg_msg_search.ui \ src/gui/ui/dlg_preferences.ui \ src/gui/ui/dlg_proxysets.ui \ - src/gui/ui/dlg_search_mojeid.ui \ src/gui/ui/dlg_send_message.ui \ src/gui/ui/dlg_signature_detail.ui \ src/gui/ui/dlg_tag.ui \ src/gui/ui/dlg_tags.ui \ src/gui/ui/dlg_timestamp_expir.ui \ - src/gui/ui/dlg_view_zfo.ui + src/gui/ui/dlg_view_zfo.ui \ + src/records_management/ui/dlg_records_management.ui \ + src/records_management/ui/dlg_records_management_stored.ui \ + src/records_management/ui/dlg_records_management_upload.ui RESOURCES += \ res/resources.qrc diff -Nru datovka-4.8.3/debian/changelog datovka-4.9.3/debian/changelog --- datovka-4.8.3/debian/changelog 2017-06-14 11:28:52.000000000 +0000 +++ datovka-4.9.3/debian/changelog 2017-09-07 13:19:10.000000000 +0000 @@ -1,3 +1,39 @@ +datovka (4.9.3-2) unstable; urgency=medium + + * Update czech l10n by running lrelease datovka.pro again + + -- Ondřej Surý Thu, 07 Sep 2017 15:19:10 +0200 + +datovka (4.9.3-1) unstable; urgency=medium + + * New upstream version 4.9.3 + + -- Ondřej Surý Thu, 07 Sep 2017 11:51:30 +0200 + +datovka (4.9.2-1) unstable; urgency=medium + + * New upstream version 4.9.2 + * Refresh patches for datovka 4.9.2 + + -- Ondřej Surý Tue, 05 Sep 2017 13:28:29 +0200 + +datovka (4.9.1-1) unstable; urgency=medium + + * New upstream version 4.9.1 + * Bump required version of libisds to 0.10.7 + * Rebase patches on top of Datovka 4.9.1 + + -- Ondřej Surý Thu, 27 Jul 2017 11:34:48 +0200 + +datovka (4.9.0-1) unstable; urgency=medium + + * New upstream version 4.9.0 + * Remove obsolete patch(es) + * Add libqt5svg5-dev to Build-Depends + * Add patch to remove upstream usage of -Wdate-time that breaks Ubuntu 14.04 LTS + + -- Ondřej Surý Mon, 10 Jul 2017 12:45:25 +0200 + datovka (4.8.3-2) unstable; urgency=medium * Fix the format-security errors diff -Nru datovka-4.8.3/debian/control datovka-4.9.3/debian/control --- datovka-4.8.3/debian/control 2017-06-14 11:28:52.000000000 +0000 +++ datovka-4.9.3/debian/control 2017-09-07 13:19:10.000000000 +0000 @@ -3,7 +3,8 @@ Priority: optional Maintainer: Ondřej Surý Build-Depends: debhelper (>= 9), - libisds-dev (>= 0.10.4), + libisds-dev (>= 0.10.7), + libqt5svg5-dev, libssl-dev, libxml2-dev, qtbase5-dev, @@ -15,7 +16,7 @@ Package: datovka Architecture: any -Depends: libisds5 (>= 0.10.4), +Depends: libisds5 (>= 0.10.7), libqt5sql5-sqlite, qttranslations5-l10n, ${misc:Depends}, Binary files /tmp/tmpe3CEIf/dc8GgEGq5K/datovka-4.8.3/debian/patches/0001-Add-lrelease-generated-files-into-the-debian-package.patch and /tmp/tmpe3CEIf/yNYspGPMCd/datovka-4.9.3/debian/patches/0001-Add-lrelease-generated-files-into-the-debian-package.patch differ diff -Nru datovka-4.8.3/debian/patches/0002-Allow-compilation-with-older-Qt5-versions.patch datovka-4.9.3/debian/patches/0002-Allow-compilation-with-older-Qt5-versions.patch --- datovka-4.8.3/debian/patches/0002-Allow-compilation-with-older-Qt5-versions.patch 2017-06-14 11:28:52.000000000 +0000 +++ datovka-4.9.3/debian/patches/0002-Allow-compilation-with-older-Qt5-versions.patch 2017-09-07 13:19:10.000000000 +0000 @@ -3,27 +3,19 @@ Subject: Allow compilation with older Qt5 versions --- - datovka.pro | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) + datovka.pro | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datovka.pro b/datovka.pro -index 024a568..5bef556 100644 +index fcbd558..9076b70 100644 --- a/datovka.pro +++ b/datovka.pro -@@ -35,14 +35,14 @@ ADVISED_MINOR = 3 - ADVISED_PATCH = 2 +@@ -28,7 +28,7 @@ win32 { - lessThan(QT_MAJOR_VERSION, $${REQUIRED_MAJOR}) { -- error(Qt version $${REQUIRED_MAJOR}.$${REQUIRED_MINOR} is required.) -+ warning(Qt version $${REQUIRED_MAJOR}.$${REQUIRED_MINOR} is required.) - } else { - QT += widgets - } + # Qt 5.2.1 contains a bug causing the application to crash on some drop events. + # Version 5.3.2 should be fine. +-sufficientQtVersion(5, 3, 3, 2) ++# sufficientQtVersion(5, 3, 3, 2) - isEqual(QT_MAJOR_VERSION, $${REQUIRED_MAJOR}) { - lessThan(QT_MINOR_VERSION, $${REQUIRED_MINOR}) { -- error(Qt version $${REQUIRED_MAJOR}.$${REQUIRED_MINOR} is required.) -+ warning(Qt version $${REQUIRED_MAJOR}.$${REQUIRED_MINOR} is required.) - } - - lessThan(QT_MINOR_VERSION, $${ADVISED_MINOR}) { + DEFINES += \ + DEBUG=1 \ diff -Nru datovka-4.8.3/debian/patches/0003-Disable-Wdate-time-to-fix-FTBFS-with-older-gcc.patch datovka-4.9.3/debian/patches/0003-Disable-Wdate-time-to-fix-FTBFS-with-older-gcc.patch --- datovka-4.8.3/debian/patches/0003-Disable-Wdate-time-to-fix-FTBFS-with-older-gcc.patch 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/debian/patches/0003-Disable-Wdate-time-to-fix-FTBFS-with-older-gcc.patch 2017-09-07 13:19:10.000000000 +0000 @@ -0,0 +1,49 @@ +From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= +Date: Tue, 16 Feb 2016 16:03:38 +0100 +Subject: Disable -Wdate-time to fix FTBFS with older gcc + +--- + datovka.pro | 2 +- + tests/records_management_app/rm_test_app.pro | 2 +- + tests/tests.pro | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/datovka.pro b/datovka.pro +index 9076b70..8f342a1 100644 +--- a/datovka.pro ++++ b/datovka.pro +@@ -112,7 +112,7 @@ unix:!macx { + QMAKE_CXXFLAGS = \ + -g -O0 -std=c++11 \ + -Wall -Wextra -pedantic \ +- -Wdate-time -Wformat -Werror=format-security \ ++ -Wformat -Werror=format-security \ + -Isrc/views + + INCLUDEPATH += \ +diff --git a/tests/records_management_app/rm_test_app.pro b/tests/records_management_app/rm_test_app.pro +index 16fa710..11857b1 100644 +--- a/tests/records_management_app/rm_test_app.pro ++++ b/tests/records_management_app/rm_test_app.pro +@@ -19,7 +19,7 @@ DEFINES += \ + QMAKE_CXXFLAGS = \ + -g -O0 -std=c++11 \ + -Wall -Wextra -pedantic \ +- -Wdate-time -Wformat -Werror=format-security ++ -Wformat -Werror=format-security + + INCLUDEPATH += \ + $${top_srcdir} +diff --git a/tests/tests.pro b/tests/tests.pro +index 92159e1..e36afef 100644 +--- a/tests/tests.pro ++++ b/tests/tests.pro +@@ -18,7 +18,7 @@ DEFINES += \ + QMAKE_CXXFLAGS = \ + -g -O0 -std=c++11 \ + -Wall -Wextra -pedantic \ +- -Wdate-time -Wformat -Werror=format-security ++ -Wformat -Werror=format-security + + INCLUDEPATH += \ + $${top_srcdir} diff -Nru datovka-4.8.3/debian/patches/0003-Fix-the-format-security-errors.patch datovka-4.9.3/debian/patches/0003-Fix-the-format-security-errors.patch --- datovka-4.8.3/debian/patches/0003-Fix-the-format-security-errors.patch 2017-06-14 11:28:52.000000000 +0000 +++ datovka-4.9.3/debian/patches/0003-Fix-the-format-security-errors.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= -Date: Wed, 14 Jun 2017 13:28:19 +0200 -Subject: Fix the format-security errors - ---- - datovka.pro | 1 + - src/gui/dlg_correspondence_overview.cpp | 8 ++++---- - 2 files changed, 5 insertions(+), 4 deletions(-) - -diff --git a/datovka.pro b/datovka.pro -index 5bef556..84c297a 100644 ---- a/datovka.pro -+++ b/datovka.pro -@@ -141,6 +141,7 @@ unix:!macx { - QMAKE_CXXFLAGS = \ - -g -O0 -std=c++11 \ - -Wall -Wextra -pedantic \ -+ -Wdate-time -Wformat -Werror=format-security \ - -Isrc/views - - INCLUDEPATH += \ -diff --git a/src/gui/dlg_correspondence_overview.cpp b/src/gui/dlg_correspondence_overview.cpp -index 761e1d0..a203c09 100644 ---- a/src/gui/dlg_correspondence_overview.cpp -+++ b/src/gui/dlg_correspondence_overview.cpp -@@ -507,28 +507,28 @@ void appendError(enum Exports::ExportFileType fileType, qint64 dmId, - { - switch (fileType) { - case Exports::ZFO_MESSAGE: -- qWarning( -+ qWarning("%s", - QString("DZ '%1' export error.").arg(dmId).toUtf8().constData()); - errList.append( - QObject::tr("Message '%1' does not contain data necessary for ZFO export.") - .arg(dmId)); - break; - case Exports::ZFO_DELIVERY: -- qWarning( -+ qWarning("%s", - QString("DZ '%1' export error").arg(dmId).toUtf8().constData()); - errList.append( - QObject::tr("Message '%1' does not contain acceptance info data necessary for ZFO export.") - .arg(dmId)); - break; - case Exports::PDF_ENVELOPE: -- qWarning( -+ qWarning("%s", - QString("OZ '%1' export error").arg(dmId).toUtf8().constData()); - errList.append( - QObject::tr("Message '%1' does not contain message envelope data necessary for PDF export.") - .arg(dmId)); - break; - case Exports::PDF_DELIVERY: -- qWarning( -+ qWarning("%s", - QString("DD '%1' export error").arg(dmId).toUtf8().constData()); - errList.append( - QObject::tr("Message '%1' does not contain acceptance info data necessary for PDF export.") diff -Nru datovka-4.8.3/debian/patches/series datovka-4.9.3/debian/patches/series --- datovka-4.8.3/debian/patches/series 2017-06-14 11:28:52.000000000 +0000 +++ datovka-4.9.3/debian/patches/series 2017-09-07 13:19:10.000000000 +0000 @@ -1,3 +1,3 @@ 0001-Add-lrelease-generated-files-into-the-debian-package.patch 0002-Allow-compilation-with-older-Qt5-versions.patch -0003-Fix-the-format-security-errors.patch +0003-Disable-Wdate-time-to-fix-FTBFS-with-older-gcc.patch diff -Nru datovka-4.8.3/locale/datovka_cs.ts datovka-4.9.3/locale/datovka_cs.ts --- datovka-4.8.3/locale/datovka_cs.ts 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/locale/datovka_cs.ts 2017-09-06 11:49:23.000000000 +0000 @@ -2,62 +2,34 @@ - AboutDialog - - - Version: - Verze: - - - - About Datovka - O Datovce - - - - Copyright © - Copyright © - - - - Licence - Licence - - - - Credits - Zásluhy - - - AccountModel - + Accounts Účty - + Recent Received Nedávno přijaté - + Recent Sent Nedávno odeslané - + All Vše - + Received Přijaté - + Sent Odeslané @@ -161,61 +133,142 @@ - ChangeDirectory + CLIParser - - Change data directory for current account - Změnit datové úložiště pro vybraný účet + + Data box application + Aplikace pro datové schránky - - Data for this account is currenly stored in: - Data pro tento účet jsou aktuálně uloženy v: + + Use <%1> subdirectory for configuration. + Použít <%1> podadresář pro konfiguraci. - - n/a - n/a + + + conf-subdir + conf-subdir - - Select a new directory where data should be stored: - Vyberte nový adresář, kde budou data uložena: + + On start load <%1> file. + Po spuštění načíst soubor <%1>. - - New data directory - Nový adresář pro data + + + conf + conf - - Choose - Vybrat + + On stop save <%1> file. + Po ukončení uložit soubor <%1>. - - Cannot used the original directory as destination! - Nemůžete použít původní adresář jako cílový! + + Log messages to <%1>. + Zaznamenávat výpisy do <%1>. - - Action - Akce + + file + soubor - - Move data to the new directory - Přesunout stávající data do nového adresáře + + Set verbosity of logged messages to <%1>. Default is %2. + Nastavit podrobnost ladicích zpráv na <%1>. Výchozí je %2. - - Copy data to the new directory - Kopírovat stávající data do nového adresáře + + + + + level + úroveň - - Start afresh in the new directory - Začít novou databázi v novém adresáři + + Enable debugging information. + Zapnout debugovací výpisy. + + + + Set debugging verbosity to <%1>. Default is %2. + Nastavit podrobnost ladicích informací na <%1>. Výchozí je %2. + + + + Service: connect to ISDS and login into data box. + Služba: připojit se k datové schránce. + + + + + + + + + + string-of-parameters + řetězec-parametrů + + + + Service: download list of received/sent messages from ISDS (synchronization). + Služba: stáhnout seznam přijatých a odeslaných zpráv z ISDS (sychronizace). + + + + Service: create and send a new message to ISDS. + Služba: vytvořit a odeslat novou zprávu do ISDS. + + + + Service: download complete message with signature and time stamp of MV. + Služba: stáhnout kompletní zprávu s podpisem a časovým razítkem MV. + + + + Service: download acceptance info of message with signature and time stamp of MV. + Služba: stáhnout informace o doručení zprávy s podpisem a časovým razítkem MV. + + + + Service: get information about user (role, privileges, ...). + Služba: stáhnout informace o uživateli (role, oprávnění, ...). + + + + Service: get information about owner and its data box. + Služba: stáhnout informace o vlastníkovi a jeho datové schránce. + + + + Service: get list of messages where attachment missing (local database only). + Služba: získat seznam zpráv bez přílohy (pouze lokální databaze). + + + + Service: find a data box via several parameters. + Služba: vyhledat datovou schránku na ISDS. + + + + Service: get list of message IDs (received/sent) from local database. + Služba: získat seznam identifikátorů zpráv (doručených/odeslaných) z místní databáze. + + + + [zfo-file] + [zfo-soubor] + + + + ZFO file to be viewed. + Zobrazovaný ZFO soubor. @@ -326,11 +379,6 @@ Filter: Filtr: - - - Clear - Vyčistit - CorrespondenceOverview @@ -531,37 +579,6 @@ - CreateAccountFromDb - - - Create account form database file - Vytvořit účet z existující databáze - - - - What do you want to create the account(s) from? - Jakým způsobem chce účet vytvořit? - - - - Database file(s) from directory - Databázové soubory z adresáře - - - - Selected database file(s) - Vybrat databázové soubory - - - - CreateAccountFromDbDialog - - - A new account will be created according to the name and the content of the database file. This account will operate over the selected database. Should such an account or database file already exist in Datovka then the association will fail. During the association no database file copy is created nor is the content of the database file modified. Nevertheless, we strongly advice you to back-up all important files before associating a database file. In order for the association to succeed you will need an active connection to the ISDS server. - Z názvu a obsahu vybraného databázového souboru se v Datovce vytvoří nový účet, který bude pracovat s vybranou databází. Pokud již tento účet či databáze v Datovce existují, nebude se účet znova vytvářet. Při vytváření účtu a jeho přiřazení k databázi se nevytváří žádná kopie databázového souboru ani se nemodifikuje jeho obsah, přesto silně doporučujeme databázový soubor projistotu pře importem zálohovat. Pro úspěšné přiřazení databáze k novému účtu je také zapotřebí aktivní připojení na server Datové schránky. - - - DbFlsTblModel @@ -579,7 +596,7 @@ Cesta k souboru - + unknown neznámý @@ -587,13 +604,13 @@ DbMsgsTblModel - - + + Attachments downloaded Přílohy staženy - + Processing state Stav vyřizování @@ -601,372 +618,526 @@ DlgAbout - + Portable version Přenosná verze - + Version Verze - + Free client for Czech eGov data boxes. Svobodný klient pro Datové schránky. - + Additional informations Další informace - + home page domovská stránka - + handbook příručka - + FAQ FAQ - + Support Podpora - - - DlgChangeDirectory - - Open Directory - Otevřít adresář + + + File '%1' either doesn't exist or is empty. + Soubor '%1' buď neexistuje nebo je prázdný. - - - DlgChangePwd - - Enter security code: - Zadejte bezpečnostní kód: + + About Datovka + O Datovce - - - Enter SMS code: - Zadejte SMS kód: + + Version: + Verze: - - Hide - Skrýt + + Copyright © + Copyright © - - Show - Ukázat + + Licence + Licence - - SMS code for account - SMS kód pro účet + + Credits + Zásluhy + + + DlgChangeDirectory - - Account "%1" requires authentication via security code for connection to databox. - Účet "%1" vyžaduje pro přihlášení k datové schránce autorizaci pomocí bezpečnostního kódu OTP. + + Open Directory + Otevřít adresář - - Security code will be sent you via Premium SMS. - Bezpečnostní kód Vám bude zaslán přes Prémiovou SMS. + + + + + + + + Change data directory for current account + Změnit adresář pro ukládání dat pro aktuální účet - - Do you want to send Premium SMS with security code into your mobile phone? - Chcete poslat Prémiovou SMS s bezpečnostním kódem do Vašeho mobilu? + + Database files for '%1' have been successfully moved to + +'%2'. + Databázové soubory pro '%1' byly úspěšně přesunuty do + +'%2'. - - Enter SMS security code - Zadejte SMS bezpečnostní kód + + Database files for '%1' could not be moved to + +'%2'. + Databázové soubory pro '%1' nemohly být přesunuty do + +'%2'. - - SMS security code for account "%1"<br/>has been sent on your mobile phone... - SMS bezpečnostní kód pro účet "%1"<br/>byl zaslán do Vašeho mobilu... + + Database files for '%1' have been successfully copied to + +'%2'. + Databázové soubory pro '%1' byly úspěšně překopírovány do + +'%2'. - - Enter SMS security code for account - Zadejte SMS bezpečnostní kód pro účet + + Database files for '%1' could not be copied to + +'%2'. + Databázové soubory pro '%1' nemohly být překopírovány do + +'%2'. - - Login error - Chyba přihlášení + + New database files for '%1' have been successfully created in + +'%2'. + Databázové soubory pro '%1' byly úspěšně vytvořeny v + +'%2'. - - An error occurred while preparing request for SMS with OTP security code. - Došlo k chybě v průběhu přípravy požadavku pro přihlášení pomocí SMS OTP. + + New database files for '%1' could not be created in + +'%2'. + Databázové soubory pro '%1' nemohly být vytvořeny v + +'%2'. - - Please try again later or you have to use the official web interface of Datové schránky for access to your data box. - Zkuste to později nebo použijte oficiální webové rozhraní pro Datové schránky. + + Data for this account is currenly stored in: + Data pro tento účet jsou aktuálně uloženy v: - - Password has been changed - Heslo bylo změněno + + n/a + n/a - - Password has been changed successfully on the server ISDS. - Heslo bylo na ISDS serveru uspěšně změněno. + + Select a new directory where data should be stored: + Vyberte nový adresář, kam budou data uložena: - - Restart the application. Also don't forget to remember the new password so you will still be able to log into your data box via the web interface. - Restartujte aplikaci. Nezapomeňte si také zapamatovat nové heslo, abyste je byli schopni použít pro přihlašování přes webové rozhraní. + + New data directory + Nový adresář pro data - - Error: - Chyba: + + Choose + Vybrat - - ISDS returns: - ISDS vrací: + + You cannot use the original directory as destination! + Nemůžete použít původní adresář jako cílový! - + + Action + Akce + + + + Move data to the new directory + Přesunout stávající data do nového adresáře + + + + Copy data to the new directory + Kopírovat stávající data do nového adresáře + + + + Start afresh in the new directory + Začít novou databázi v novém adresáři + + + + DlgChangePwd + + + Enter security code: + Zadejte bezpečnostní kód: + + + + + Enter SMS code: + Zadejte SMS kód: + + + + Hide + Skrýt + + + + Show + Ukázat + + + + SMS code for account + SMS kód pro účet + + + + Account "%1" requires authentication via security code for connection to databox. + Účet "%1" vyžaduje pro přihlášení k datové schránce autorizaci pomocí bezpečnostního kódu OTP. + + + + Security code will be sent you via Premium SMS. + Bezpečnostní kód Vám bude zaslán přes Prémiovou SMS. + + + + Do you want to send Premium SMS with security code into your mobile phone? + Chcete poslat Prémiovou SMS s bezpečnostním kódem do Vašeho mobilu? + + + + Enter SMS security code + Zadejte SMS bezpečnostní kód + + + + SMS security code for account "%1"<br/>has been sent on your mobile phone... + SMS bezpečnostní kód pro účet "%1"<br/>byl zaslán do Vašeho mobilu... + + + + Enter SMS security code for account + Zadejte SMS bezpečnostní kód pro účet + + + + Login error + Chyba přihlášení + + + + An error occurred while preparing request for SMS with OTP security code. + Došlo k chybě v průběhu přípravy požadavku pro přihlášení pomocí SMS OTP. + + + + Please try again later or you have to use the official web interface of Datové schránky for access to your data box. + Zkuste to později nebo použijte oficiální webové rozhraní pro Datové schránky. + + + + Password has been changed + Heslo bylo změněno + + + + Password has been changed successfully on the server ISDS. + Heslo bylo na ISDS serveru uspěšně změněno. + + + + Restart the application. Also don't forget to remember the new password so you will still be able to log into your data box via the web interface. + Restartujte aplikaci. Nezapomeňte si také zapamatovat nové heslo, abyste je byli schopni použít pro přihlašování přes webové rozhraní. + + + + Error: + Chyba: + + + + ISDS returns + ISDS vrací + + + An error occurred while password was changed. Nastala chyba v průběhu změny hesla. - + You have to fix the problem and try to again. Napravte chybu a zkuste to znovu. - + Password error Chybné heslo + DlgContacts + + + Enter sought expression + Zadete hledaný výraz + + + DlgCorrespondenceOverview - - + + messages: zpráv: - + Sent Odeslané - + Received Přijaté - - + + Correspondence overview Přehled korespondence - + From date: Od data: - + To date: Do data: - + Generated: Vygenerováno: - + Status Stav - + Message type Typ zprávy - + Delivery time Čas dodání - + Acceptance time Čas doručení - - + + Subject Předmět - - + + Sender Odesílatel - + Sender Address Adresa odesílatele - - + + Recipient Adresát - + Delivery Dodání - + Acceptance Doručení - + Recipient Address Adresa příjemce - + Our file mark Naše spisová značka - + Our reference number Naše číslo jednací - + Your file mark Vaše spisová značka - + Your reference number Vaše číslo jednací - + Select file to save correspondence overview Vybrat soubor pro uložení přehledu korespondence - + Correspondence Overview Export Error Chyba při exportu přehledu korespondence - + correspondence overview file was exported to HTML. soubor s přehledem korespondence byl exportován do HTML. - + correspondence overview file was exported to CSV. soubor s přehledem korespondence byl exportován do CSV. - + correspondence overview file was exported. soubor s přehledem korespondence byl exportován. - + Select directory for export of ZFO/PDF file(s) Vyberte adresář pro export ZFO/PDF souborů - + messages were successfully exported to ZFO/PDF. zpráv bylo úspěšně exportováno do ZFO/PDF. - + messages were successfully exported to ZFO. zpráv bylo úspěšně exportováno do ZFO. - + acceptance infos were successfully exported to ZFO. doručenek bylo exportováno do ZFO. - + message envelopes were successfully exported to PDF. obálek zpráv bylo úspěšně exportováno do PDF. - + acceptance infos were successfully exported to PDF. doručenek bylo exportováno do PDF. - + Export results Výsledky exportu - + Export of correspondence overview finished with these results: Export přehledu korespondence skončil s tímto výsledkem: - + Some errors occurred during export. Během exportu se vyskytly nějaké chyby. - + See detail for more info... Více informací v podrobnostech... - + Overview Prehled - + Files Soubory - + Correspondence overview file '%1' could not be written. Soubor s přehledem korespondence '%1' nemohl být zapsán. @@ -974,172 +1145,259 @@ DlgCreateAccount - + Password Heslo - + Certificate Certifikát - + Certificate + Password Certifikát + heslo - + Password + Secure code Heslo + Bezpečnostní kód - + Password + Secure SMS Heslo + SMS kód - + Update account %1 Aktualizovat účet %1 - + Enter password for account %1 Zadejte heslo pro účet %1 - + Set certificate for account %1 Nastavit certifikát pro účet %1 - + Enter password/certificate for account %1 Zadejte heslo/certifikát pro účet %1 - - mojeID - mojeID - - - + Open Certificate Otevřít certifikát - + Certificate Files (*.p12 *.pem) Soubory certifikátů (*.p12 *.pem) + DlgCreateAccountFromDb + + + Create account from database file + Vytvořit účet z existující databáze + + + + What do you want to create the account(s) from? + Jakým způsobem chce účet(účty) vytvořit? + + + + Database files from directory + Databázové soubory z adresáře + + + + Selected database files + Vybrané databázové soubory + + + + A new account will be created according to the name and the content of the database file. This account will operate over the selected database. Should such an account or database file already exist in Datovka then the association will fail. During the association no database file copy is created nor is the content of the database file modified. Nevertheless, we strongly advice you to back-up all important files before associating a database file. In order for the association to succeed you will need an active connection to the ISDS server. + Z názvu a obsahu vybraného databázového souboru se v Datovce vytvoří nový účet, který bude pracovat s vybranou databází. Pokud již tento účet či databáze v Datovce existují, nebude se účet znova vytvářet. Při vytváření účtu a jeho přiřazení k databázi se nevytváří žádná kopie databázového souboru ani se nemodifikuje jeho obsah, přesto silně doporučujeme databázový soubor projistotu pře importem zálohovat. Pro úspěšné přiřazení databáze k novému účtu je také zapotřebí aktivní připojení k serveru ISDS. + + + + Select directory + Vybrat adresář pro import + + + + No database file found + Nenalezen žádný databázový soubor + + + + No database file found in selected directory '%1'. + Nenalezeny žádné databázové soubory ve vybraném adresáři '%1'. + + + + Select database files + Vybrat databázové soubory + + + + Database file (*.db) + Databázový soubor (*.db) + + + + + + Create account: %1 + Nový účet: %1 + + + + + + File + Soubor + + + + Account with user name '%1' and its message database already exist. New account was not created and selected database file was not associated with this account. + Účet s uživatelským jménem '%1' a jeho databáze již existují. Nový účet nebyl vytvořen a vybraná databáze nebyla k účtu přiřazena. + + + + Account with name '%1' has been created (user name '%1'). + Účet s názvem '%1' byl vytvořen (uživatelské jméno '%1'). + + + + This database file has been set as the actual message database for this account. You'll probably have to modify the account properties in order to log in to the ISDS server correctly. + Tento databázový soubor byl nastaven jako aktuální databáze pro ukládání zpráv pro tento účet. Možná bude zapotřebí upravit vlastnosti tohoto účtu aby bylo možné se připojit k serveru ISDS. + + + DlgDsSearch - - + + All Vše - + All types Všechny - + OVM OVM - + Orgán veřejné moci Orgán veřejné moci - + PO PO - + Právnická osoba Právnická osoba - + PFO PFO - + Podnikající fyzická osoba Podnikající fyzická osoba - + FO FO - + Fyzická osoba Fyzická osoba - + Search in all fields Hledat ve všech položkách - + Address Adresa - + Search in address data Hledat podle adresy - + IC - + Identification number Identifikační číslo - + ID ID - + Box identifier ID datové schránky - + + Enter sought expression + Zadete hledaný výraz + + + + This is a special ID for a ISDS system data box. You can't use this ID for message delivery. Try again. + Toto je speciální ID "systémové schránky" ISDS. Momentálně není možné zasílat zprávy do této schránky. Hledejte dál. + + + Full-text data box search. Enter phrase for finding and set optional restrictions: Fulltextové vyhledávání datových schránek. Zadejte vyhledávaný výraz a zvolte případná omezení: - + Enter the ID, IČ or at least three letters from the name of the data box you look for: Zadejte ID, IČ nebo alespoň tři písmena z názvu hledané datové schránky: - - + + Your account is of type Váš účet je typu - + You have also Post Data Messages activated. This means you can only search for accounts of type OVM and accounts that have Post Data Messages delivery activated. Because of this limitation the results of your current search might not contain all otherwise matching databoxes. @@ -1150,187 +1408,216 @@ všechny datové schránky, které by jinak vyhovovaly parametrům. - + commercial messages are enabled poštovní datové zprávy jsou povoleny - + This means you can only search for accounts of type OVM. The current search settings will thus probably yield no result. To znamená, že můžete vyhledávat pouze schránky typu OVM. Vyhledávání s aktuálními parametry tak pravděpodobně nevrátí žádné výsledky. - + commercial messages are disabled poštovní datové zprávy jsou vypnuty - - + + Enter last name of the PFO or company name. Zadejte příjmení PFO nebo název firmy. - - + + Enter last name or last name at birth of the FO. Zadejte příjmení nebo rodné příjmení FO. - - + Total found Celkem nalezeno - - + + It was not possible find any data box because Nebylo možné najít žádnou datovou schránku protože - - + + It was not possible find any data box because an error occurred during the search process! Nebylo možné najít žádnou datovou schránku, protože během procesu vyhledávání došlo k chybě! - + Displayed Zobrazeno - - + + Subject Name: Název subjektu: - - - - + + + + Enter name of subject Zadejte název instituce - - Name: - Jméno: + + Search recipient + Vyhledat příjemce - - Last Name: - Příjmení: + + Current account: + Aktuální účet: - - - - - - Search result - Výsledek hledání + + + + n/a + n/a - - This is a special ID for system databox of Datové schránky. You can't use this ID for message delivery. Try again. - Toto je speciální ID "systémové schránky" systému Datových schránek. Momentálně není možné zasílat zprávy do této schránky. Hledejte dál. + + Use full-text search similar to the ISDS client portal. + Použít fulltextové vyhledávání podobné vyhledávání na portálu ISDS. - - - Search error - Chyba při vyhledávání + + Your account is not of type OVM (i.e. non-OVM). Sending of post data messages +from your account is activated. This means that you can only search for accounts +of the type OVM and accounts that have the the receiving of post data messages +activated. Because of this limitation the results of your current search may not +contain all otherwise matching databoxes. + Váš účet není typu OVM (tedy ne-OVM). Zasílání poštovních datových zpráv z Vašeho +účtu je aktivní. To znamená, že můžete vyhledávat pouze datové schránky typu OVM +nebo schránky, které mají aktivován příjem poštovních datových zpráv. Díky tomuto +omezení nemusí výsledek tohoto vyhledávání obsahovat všechny jinak odpovídající +datové zprávy. - - - DlgDsSearchMojeId - - Search - Vyhledat + + Note: Your search results will be limited. See tooltip for more information. + Poznámka: Výsledky vyhledávání budou omezeny. Více najdete v tooltipu. - - Search next - Vyhledat další + + Databox type: + Typ datové schránky: - - - DlgLoginToMojeId - - Password - Heslo + + Search in fileds: + Vyhledávat v položkách: - - Certificate - Certifikát + + Text: + Text: - - Password + Secure code - Heslo + Bezpečnostní kód + + ID: + ID schránky: - - Login to account: %1 - Přihlásit se do účtu: %1 + + IČ: + IČ: - - Open Certificate - Otevřít certifikát + + + Name: + Jméno: - - Certificate Files (*.p12 *.pem) - Soubory certifikátů (*.p12 *.pem) + + Postal code: + Směrovací číslo: + + + + Search + Vyhledat + + + + Filter: + Filtr: + + + + Last Name: + Příjmení: + + + + + + + + Search result + Výsledek hledání + + + + + Search error + Chyba při vyhledávání DlgMsgSearch - + Here it is possible to search for messages according to supplied criteria. You can search for messages in selected account or in all accounts. Double clicking on a found message will change focus to the selected message in the application window. Note: You can view additional information when hovering your mouse cursor over the message ID. Zde je možné vyhledávat zprávy podle zvolených kritérií. Je možné vyhledávat zprávy v aktivním účtu nebo ve všech účtech. Dvojklik na nalezenou zprávu změní fokus na zvolenou zprávu v hlavním okně. Poznámka: Dodatečné informace je možné zobrazit najetím kurzoru myši nad identifikátor zprávy. - + Account Účet - + Message ID ID zprávy - + Subject Předmět - + Sender Odesílatel - + Recipient Příjemce - + Delivery Year Rok dodání - + Message Type Typ zprávy @@ -1370,251 +1657,382 @@ + DlgRecordsManagement + + + Records Management Settings + Nastavení spisové služby + + + + Service location URL. + URL určující umístění služby. + + + + URL: + URL: + + + + Access token into the records management service. + Přístupový token do spisové služby. + + + + Token: + Token: + + + + Service Info + Info o službě + + + + Erase + Vymazat + + + + Service name: + Jméno služby: + + + + Token name: + Jméno tokenu: + + + + + + Communication Error + Chyba komunikace + + + + Received invalid response. + Obdržena neplatná odezva. + + + + Received empty response. + Obdržena prázdná odezva. + + + + DlgRecordsManagementStored + + + Records Management Stored Messages + Zprávy uložené ve spisové službě + + + + Updating stored information about messages. + Aktualizuji uložené informace o zprávách. + + + + Downloading information about messages from account: +%1 (%2). + Stahuji informace o zprávách z účtu: +%1 (%2). + + + + DlgRecordsManagementUpload + + + Upload Message into Records Management Service + Nahrát zprávu do spisové služby + + + + Appeal + Výzva + + + + Reload + Obnovit + + + + Filter: + Filtr: + + + + Select the location where you want +to upload the message '%1' into. + Vyberte umístění, kam chcete nahrát +zprávu '%1'. + + + + + + + + Communication Error + Chyba komunikace + + + + + Received invalid response. + Obdržena neplatná odezva. + + + + + Received empty response. + Obdržena prázdná odezva. + + + DlgSendMessage - + sending of PDZ: enabled posílání PDZ: povoleno - + remaining credit: zbývající kredit: - + sending of PDZ: disabled posílání PDZ: zakázáno - + Our reference number: Naše číslo jednací: - + Enter reference number: Zadejte Vaše referenční číslo: - + Warning: The permitted amount (%1) of attachments has been exceeded. Upozornění: Povolený počet (%1) příloh byl překročen. - + Total size of attachments is ~%1 KB Celková velikost příloh je ~%1 KB - + Warning: Total size of attachments is larger than %1 MB! Upozornění: Celková velikost příloh přesahuje %1 MB! - + Total size of attachments is ~%1 B Celková velikost příloh je ~%1 B - + Message contains non-OVM recipients. Zpráva obsahuje více ne-OVM příjemců. - + Wrong data box ID Špatné ID datové schránky - + Wrong data box ID '%1'! Špatné ID datové schránky '%1'! - + Message was successfully sent to <i>%1 (%2)</i> as PDZ with number <i>%3</i>. Zpráva byla úspěšně odeslána do <i>%1 (%2)</i> jako PDZ s číslem <i>%3</i>. - + Message was successfully sent to <i>%1 (%2)</i> as message number <i>%3</i>. Zpráva byla úspěšně odeslána do <i>%1 (%2)</i> jako zpráva s číslem <i>%3</i>. - + Message was NOT sent to <i>%1 (%2)</i>. Server says: %3 Zpráva nebyla odeslána do <i>%1 (%2)</i>. Server vrací: %3 - - + Message was successfully sent to all recipients. Zpráva byla úspěšně odeslána všem příjemcům. - - + Message was NOT sent to all recipients. Zpráva nebyla odeslána všem příjemcům. - + Your message contains %1 non-OVM recipients therefore this message will be sent as a commercial messages (PDZ) for these recipients. Vaše zpráva obsahuje %1 ne-OVM příjemců, proto bude zpráva těmto příjemcům odeslaná v režimu placená poštovní datová zpráva (PDZ). - + Message contains non-OVM recipient. Zpráva obsahuje ne-OVM příjemce. - + Your message contains non-OVM recipient therefore this message will be sent as a commercial message (PDZ) for this recipient. Vaše zpráva obsahuje jednoho ne-OVM příjemce, proto bude zpráva tomuto příjemci odeslaná v režimu placená poštovní datová zpráva (PDZ). - + Your remaining credit is Váš zbývající kredit je - + Wrong Recipient Chybný příjemce - + Recipient Search Failed Chyba vyhledávání příjemce - + Information about recipient data box could not be obtained. Nebylo možné získat informace o datové schránce příjemce. - + Do you still want to add the box '%1' into the recipient list? Chcete stále přidat schránku '%1' do seznamu příjemců? - + Enable commercial messages (PDZ). Zapnout poštovní datové zprávy (PDZ). - + Obtained ISDS error Obdržená chyba ISDS - + It has not been possible to send a message to the ISDS server. Nebylo možné odeslat zprávu na server ISDS. - - + Message sent Zpráva odeslána - - + Message sending error Chyba odesílání zprávy - - + Do you want to close the Send message form? Chcete zavřít formulář pro odesílání zpráv a zahodit vyplněné údaje? - + Send message error Chyba při odesílání zprávy - - + + Total size of attachments is %1 B Celková velikost příloh je %1 B - - + + Unknown Neznámý - + Data box is not active Datová schránka není aktivní - + Recipient with data box ID '%1' does not have active data box. Příjemce s datovou schránkou '%1' nemá tuto schránku aktivní. - + The message cannot be delivered. Zprávu nelze dodat. - + Cannot send to data box Nelze odeslat do datové schránky - + Cannot send message to recipient with data box ID '%1'. Nelze odeslat zprávu příjemci s datovou schránkou '%1'. - + You won't be able as user '%1' to send messages into data box '%2'. Jako uživatel '%1' nebudete moct odeslat zprávu do schránky '%2'. - + Recipient with data box ID '%1' does not exist. Příjemce s datovou schránkou '%1' neexistuje. - + An error occurred while loading attachments into message. Nastala chyba v průběhu vkládání příloh do zprávy. - + An error occurred during message envelope creation. Nastala chyba v průběhu vytváření obálky zprávy. - + The message will be discarded. Zpráva bude zahozena. - + Databox ID ID datové schránky - + Enter Databox ID (7 characters): Vložte ID datové schránky (7 znaků): - + Do you want to send all messages? Chcete opravdu odeslat tuto zprávu všem příjemcům? - + Do you want to send message? Chcete opravdu odeslat zprávu tomuto příjemci? @@ -1622,58 +2040,99 @@ DlgTag - + Choose tag colour Vyberte barvu tagu - - - + + Tag error Chyba tagu - + Tag name is empty. Jméno tagu je prázdné. - + + Tag wasn't created. Tag nebyl vytvořen. - - Tag update error - Chyba aktualizace tagu + + Tag with name '%1'' already exists in database. + Tag se jménem '%1' již v databázi existuje. + + + + Tag properties + Vlastnosti tagu - - Tag with name '%1'' wasn't updated in the WebDatovka database. - Tag pojmenovaný '%1' nebyl aktualizován v databázi WebDatovky. + + Tag name: + Jméno tagu: - - Tag insert error - Chyba vložení tagu + + Tag color: + Barva tagu: - - Tag with name '%1'' wasn't' created in WebDatovka database. - Tag pojmenovaný '%1' nebyl vytvořen v databázi WebDatovky. + + Change + Změnit + + + DlgTags - - - Tag with name '%1'' already exists in database. - Tag se jménem '%1' již v databázi existuje. + + Tag manager + Správce tagů + + + + Available Tags + Dostupné tagy + + + + Add + Přidat + + + + Delete + Smazat - - - Tag wasn't created again. - Tag nebyl znovu vytvořen. + + Update + Upravit + + + + Assign + Přiřadit + + + + Remove + Odstranit + + + + Assigned Tags + Přiřazené tagy + + + + Remove all + Odstranit vše @@ -1722,257 +2181,179 @@ DlgViewZfo - - + + Error parsing content Chyba načítání obsahu - + Cannot parse the content of file '%1'. Nelze načíst obsah souboru '%1'. - + Cannot parse the content of message. Nelze načíst obsah zprávy. - + Open attachment Otevřít přílohu - + Save attachment Uložit přílohu - + Save attachments Uložit všechny přílohy - + Identification Identifikace - + ID ID - + Subject Předmět - + Message type Typ zprávy - + Sender Odesílatel - + Sender Databox ID ID datové schránky odesílatele - + Sender Address Adresa odesílatele - + Recipient Příjemce - + Recipient Databox ID ID datové schránky příjemce - + Events Události - + Recipient Address Adresa - - + + Status Stav - + Delivery time Čas dodání - + Acceptance time Čas doručení - + Attachments Přílohy - + Signature Podpis - + Message signature Podpis zprávy - + Signing certificate Podepisující certifikát - + Time stamp Časové razítko - DsSearch - - - Search recipient - Vyhledat příjemce - - - - Current account: - Aktuální účet: - - - - - - n/a - n/a - - - - Use full-text search similar to the ISDS client portal. - Použít fulltextové vyhledávání podobné vyhledávání na portálu ISDS. - - - - Your account is not of type OVM (i.e. non-OVM). Sending of post data messages -from your account is activated. This means that you can only search for accounts -of the type OVM and accounts that have the the receiving of post data messages -activated. Because of this limitation the results of your current search may not -contain all otherwise matching databoxes. - Váš účet není typu OVM (tedy ne-OVM). Zasílání poštovních datových zpráv z Vašeho -účtu je aktivní. To znamená, že můžete vyhledávat pouze datové schránky typu OVM -nebo schránky, které mají aktivován příjem poštovních datových zpráv. Díky tomuto -omezení nemusí výsledek tohoto vyhledávání obsahovat všechny jinak odpovídající -datové zprávy. - - - - Note: Your search results will be limited. See tooltip for more information. - Poznámka: Výsledky vyhledávání budou omezeny. Více najdete v tooltipu. - - - - Databox type: - Typ datové schránky: - - - - Search in fileds: - Vyhledávat v položkách: - - - - Text: - Text: - + ErrorEntry - - ID: - ID schránky: + + No error occurred + Nevyskytla se žádná chyba - - IČ: - IČ: + + Request was malformed + Požadavek byl vadný - - Name: - Jméno: - - - - Postal code: - Směrovací číslo: - - - - Search - Vyhledat - - - - DsSearchMojeId - - - Search recipient - Vyhledat příjemce - - - - Current account: - Aktuální účet: + + Identifier is missing + Chybí identifikátor - - n/a - n/a + + Supplied identifier is wrong + Dodaný identifikátor je špatný - - Keyword: - Klíčové slovo: + + File format is not supported + Formát souboru není podporován - - Search - Vyhledat + + Data are already present + Data jsou již k dispozici - - ID - ID + + Service limit was exceeded + Limit služby byl dosažen - - Name - Jméno + + Unspecified error + Nespecifikovaná chyba - - Address - Adresa + + Unknown error + Neznámá chyba @@ -2039,57 +2420,290 @@ Ověřit importované ZFO soubory na serveru - - Import selected ZFO file(s) - Importovat vybrané ZFO soubory + + Import selected ZFO file(s) + Importovat vybrané ZFO soubory + + + + ImportZFODialog + + + Here you can import whole messages and message acceptance information from ZFO files into local database. The message or acceptance information import will succeed only for those files whose validity can be approved by the Datové schránky server (working connection to server is required). Acceptance information ZFO will be inserted into local database only if a corresponding complete message already exists in the database. + Zde můžete importovat celé zprávy a doručenky ze ZFO souborů do místní databáze. Import zprávy nebo doručenky proběhne úspěšně jen pro ty soubory, jejichž správnost se podaří ověřit na serveru Datové schránky (je vyžadováno funkční spojení se serverem). ZFO doručenky jde vložit do databáze pouze tehdy, pokud již v databázi existuje odpovídající zpráva. + + + + ImportZFOResult + + + Import ZFO result + Výsledek importu ZFO + + + + Number of ZFO files for import to database(s): + Počet ZFO souborů k importování do databází: + + + + Number of new imported files: + Počet nově importovaných souborů: + + + + + + Details: + Detaily: + + + + Number of existing files: + Počet již existujícíh v databázi: + + + + 0 + 0 + + + + Number of unsuccessfully imported files: + Počet neúspěšně importovaných souborů: + + + + IsdsConversion + + + The data box is accessible. It is possible to send messages into it. It can be looked up on the Portal. + Datová schránka je přístupná, lze do ní dodávat zprávy, na Portále lze vyhledat. + + + + The data box is temporarily inaccessible (at own request). It may be made accessible again at some point in the future. + Datová schránka je dočasně znepřístupněna (na vlastní žádost), může být později opět zpřístupněna. + + + + The data box is so far inactive. The owner of the box has to log into the web interface at first in order to activate the box. + Datová schránka je dosud neaktivní. Vlastník schránky se musí poprvé přihlásit do webového rozhraní, aby došlo k aktivaci schránky. + + + + The data box is permanently inaccessible. It is waiting to be deleted (but it may be made accessible again). + Datová schránka je trvale znepřístupněna, čeká na smazání (může být opět zpřístupněna). + + + + The data box has been deleted (none the less it exists in ISDS). + Datová schránka byla smazána (přesto existuje v ISDS). + + + + The data box is temporarily inaccessible (because of reasons listed in law). It may be made accessible again at some point in the future. + Datová schránka je dočasně znepřístupněna (z důvodů vyjmenovaných v zákoně), může být později opět zpřístupněna. + + + + An error occurred while checking the status. + Došlo k chybě při zjišťování stavu. + + + + System ISDS + Systém ISDS + + + + Public authority + Orgán veřejné moci (OVM) + + + + Legal person + Právnická osoba (PO) + + + + Self-employed person + Podnikající fyzická osoba (OSVČ) + + + + Natural person + Fyzická osoba (FO) + + + + Postal data message + Poštovní datová zpráva + + + + Initialising postal data message + Inicializační poštovní datová zpráva + + + + Reply postal data message + Odpovědní poštovní datová zpráva + + + + Initialising postal data message - expired + Inicializační poštovní datová zpráva - propadlá + + + + Initialising postal data message - used + Inicializační poštovní datová zpráva - použitá + + + + Message has been submitted (has been created in ISDS) + Zpráva byla podána (vznikla v ISDS) + + + + Data message including its attachments signed with time-stamp. + Datová zpráva včetně písemností podepsána časovým razítkem. + + + + Message did not pass through AV check; infected paper deleted; final status before deletion. + Zpráva neprošla AV kontrolou; nakažená písemnost je smazána; konečný stav zprávy před smazáním. + + + + Message handed into ISDS (delivery time recorded). + Zpráva dodána do ISDS (zapsán čas dodání). + + + + 10 days have passed since the delivery of the public message which has not been accepted by logging-in (assumption of acceptance through fiction in non-OVM DS); this state cannot occur for commercial messages. + Uplynulo 10 dnů od dodání veřejné zprávy, která dosud nebyla doručena přihlášením (předpoklad doručení fikcí u ne-OVM DS); tento stav nemůže nastat v případě poštovních datových zpráv. + + + + A person authorised to read this message has logged in -- delivered message has been accepted. + Osoba oprávněná číst tuto zprávu se přihlásila -- dodaná zpráva byla doručena. + + + + Message has been read (on the portal or by ESS action). + Zpráva byla přečtena (na portále nebo akcí ESS). + + + + Message marked as undeliverable because the target DS has been made inaccessible. + Zpráva byla označena jako nedoručitelná, protože DS adresáta byla zpětně znepřístupněna. + + + + Message content deleted, envelope including hashes has been moved into archive. + Zpráva byla označena jako nedoručitelná, protože DS adresáta byla zpětně znepřístupněna. + + + + Message resides in data vault. + Zpráva je v Datovém trezoru. + + + + Primary user + Oprávněná osoba + + + + Entrusted user + Pověřená osoba + + + + Administrator + Administrátor + + + + Official + Oficiální + + + + Virtual + Virtuální + + + + ??? + ??? + + + + Liquidator + Likvidátor + + + + Receiver + Nucený správce + + + + Guardian + Opatrovník + + + + Full control + Plný přístup + + + + Restricted control + Omezený přístup - - - ImportZFODialog - - Here you can import whole messages and message acceptance information from ZFO files into local database. The message or acceptance information import will succeed only for those files whose validity can be approved by the Datové schránky server (working connection to server is required). Acceptance information ZFO will be inserted into local database only if a corresponding complete message already exists in the database. - Zde můžete importovat celé zprávy a doručenky ze ZFO souborů do místní databáze. Import zprávy nebo doručenky proběhne úspěšně jen pro ty soubory, jejichž správnost se podaří ověřit na serveru Datové schránky (je vyžadováno funkční spojení se serverem). ZFO doručenky jde vložit do databáze pouze tehdy, pokud již v databázi existuje odpovídající zpráva. + + download and read incoming DM + stahovat a číst došlé DZ - - - ImportZFOResult - - Import ZFO result - Výsledek importu ZFO + + download and read DM sent into own hands + stahovat a číst DZ určené do vlastních rukou - - Number of ZFO files for import to database(s): - Počet ZFO souborů k importování do databází: + + create and send DM, download sent DM + vytvářet a odesílat DZ, stahovat odeslané DZ - - Number of new imported files: - Počet nově importovaných souborů: + + retrieve DM lists, delivery and acceptance reports + načítat seznamy DZ, dodejky a doručenky - - - - Details: - Detaily: + + search for data boxes + vyhledávat DS - - Number of existing files: - Počet již existujícíh v databázi: + + manage the data box + spravovat DS - - 0 - 0 + + read message in data vault + číst zprávy v datovém trezoru - - Number of unsuccessfully imported files: - Počet neúspěšně importovaných souborů: + + erase messages from data vault + mazat zprávy v datovém trezoru @@ -2291,1274 +2905,1063 @@ - JsonLayer - - - Login to mojeID failed. You must choose correct login method and enter correct login data. Try again. - Přihlášení do mojeID selhalo. Musíte vybrat správný způsob přihlašování a zadat správné přihlašovací údaje. Zkuste to znovu. - - - - Cannot open client certificate from path '%1' - Nelze otevřít certifikát z cesty '%1' - - - - Certificate password - Heslo certifikátu - - - - Enter certificate password: - Zadejte heslo k certifikátu: - - - - Cannot parse client certificate from path '%1' - Nemohu načíst certifikát z cesty '%1' - - - - - - - - - - - - - - - - - - - - - - User is not logged to mojeID - Uživatel není přihlášen do mojeID - - - - - - - - - - - - - - - - - - Reply content missing - Chybí obsah odpovědi - - - - LoginToMojeId - - - Add a new mojeID account(s) - Přidejte účet mojeID - - - - Please select login method and enter credentials for mojeID. - Vyberte způsob přihlašování a zadejte přihlašovací údaje do mojeID. - - - - Login method: - Způsob přihlášení: - - - - Select authorization method for login into your databox - Vyberte metodu přihlašování do datové schránky - - - - Username: - Uživatelské jméno: - - - - Enter your username - Zadejte své přihlašovací jméno - - - - Password: - Heslo: - - - - Enter your password - Zadejte své heslo - - - - Certificate file: - Soubor certifikátu: - - - - Select a certificate - Vyberte certifikát - - - - Add - Přidat - - - - Security code (OTP): - Bezpečnostní kód (OTP): - - - - Account will be included into synchronisation -process of all accounts on the background - Účet bude zahrnut do hromadné synchronizace -všech účtů na pozadí aplikace - - - - Synchronise account(s) when "Synchronise all" is activated - Synchronizovat účet při aktivaci hromadné synchronizace - - - MainWindow - + Search: Vyhledat: - - Clear search field - Vymazat pole - - - + Mode: offline Režim: nepřipojeno (offline) - + All messages Všechny zprávy - + Add new account Vytvořit nový účet - + Test account Testovací účet - + Standard account Standardní účet - + Account name Název účtu - + User name Uživatelské jméno - + Yes Ano - + No Ne - + Password expiration date Datum a čas expirace hesla - - + + Received messages Přijaté zprávy - - - + + + none žádné - - + + Sent messages Odeslané zprávy - + Version Verze - + Powered by Vytvořil - + Datovka: Database file present Datovka: Databázový soubor přítomen - + Database file for account '%1' already exists. Databázový soubor pro účet '%1' již existuje. - + If you want to use a new blank file then delete, rename or move the existing file so that the application can create a new empty file. Pokud chcete použít nový prázdný soubor, pak odstraňte, přejmenujte nebo přesuňte stávající soubor, aby aplikace mohla vytvořit nový prázdný soubor. - - - - - + + + + + Datovka: Problem loading database Datovka: Problém otevírání databáze - - - - - - + + + + + + Could not load data from the database for account '%1' Nemohu načíst data z databázového souboru pro účet '%1' - + I'll try to create an empty one. Pokusím se vytvořit prázdný. - - + + Datovka - Free client for Datové schránky Datovka - Svobodný klient pro Datové schránky - + No account synchronised. Nebyl synchronizován žádný účet. - + Account and user information could not be acquired. Nepodařilo se získat informace o účtu a uživateli. - + User information Informace o uživateli - + Databox information Informace o datové schránce - + The existing database files %1 in '%2' are going to be used. Existující databázové soubory %1 v '%2' budou použity. - + Database files are missing in '%1'. Databázové soubory chybí v '%1'. - + Some databases of %1 in '%2' are not a file. Některé databáze %1 v '%2' asi nejsou soubory. - + Some databases of '%1' in '%2' cannot be accessed. Některé databáze %1 v '%2' nelze zpřístupnit. - + You don't have enough access rights to use the file. Nemáte dostatečná oprávnění k použití souboru. - + The file either does not contain an sqlite database or the file is corrupted. - Soubor buď neobsahuje slite databázi nebo je poškozen. + Soubor buď neobsahuje sqlite databázi nebo je poškozen. - + Datovka: Database opening error Datovka: Chyba otevírání databáze - + Remove account Odstranit účet - + Do you want to remove account Chcete opravdu odstranit účet - + Delete also message database from storage Odstranit také databázi zpráv z disku - + Warning: If you delete the message database then all locally accessible messages that are not stored on the ISDS server will be lost. Upozornění: Jestli-že smažete databázi zpráv potom všechny zprávy, které nejsou uloženy na serveru ISDS budou ztraceny. - + Account '%1' was deleted together with message database file. Účet '%1' byl smazán společně s jeho databází zpráv. - + Account '%1' was deleted. Účet '%1' byl smazán. - - - - - - - Change data directory for current account - Změnit adresář pro ukládání dat pro aktuální účet - - - + Connection to ISDS or user authentication failed! Připojení k serveru datové schránky se nezdařilo nebo selhala autorizace uživatele! - + Please check your internet connection and try again or it is possible that your password (certificate) has expired - in this case, you need to use the official web interface of Datové schránky to change it. Zkontrolujte prosím připojení k internetu a zkuste to znovu. Také je možné, že vaše heslo (certifikát) již vypršelo - v tomto případě musíte použít oficiální webové rozhraní Datové schránky a heslo si změnit. - - + + Add ZFO file Vybrat ZFO soubor - - - + + + ZFO file (*.zfo) Soubor ZFO (*.zfo) - + Message is authentic Zpráva je autentická - + Message is not authentic Zpráva není autentická - - + + disk disk - - + + Uploaded to records management service + Nahráno do spisové služby + + + + memory paměť - + Storage: Úložiště: - + New version of Datovka is available: Nová verze Datovky je k dispozici: - - + + New version of Datovka Nová verze Datovky - - + + New version of Datovka is available. Nová verze Datovky je k dispozici. - + Current version is %1 Vaše současná verze je %1 - + New version is %1 Nová verze je %1 - + Do you want to download new version? Chcete nyní stáhnout novou verzi? - + Current version is "%1" Vaše verze je "%1" - + New version is "%1" Nová verze je "%1" - + Update your application... Aktualizujte aplikaci... - + Database files for account '%1' cannot be accessed in location '%2'. Databázové soubory pro účet '%1' nelze zpřístupnit ve složce '%2'. - + All received messages Všechny přijaté zprávy - + All sent messages Všechny odeslané zprávy - - - - + + + + As Unsettled Nevyřízeno - - - - + + + + As in Progress Vyřizuje se - - - - + + + + As Settled Vyřízeno - - + + Select target folder to save Vyberte cílovou složku pro uložení - + Error saving of attachments Chyba při ukládání příloh - + Some attachments of message '%1' were not saved to target folder! Některé přílohy zprávy '%1' nebyly uloženy do cílové složky! - + + ISDS + ISDS + + + + It was not possible to download a complete message "%1" from ISDS server. + Nebylo možné stáhnout celou zprávu "%1" ze serveru ISDS. + + + + Server + Server + + + First you must download the complete message to continue with the action. Před pokračováním akce musíte nejdříve stáhnout úplnou zprávu. - + + + Cannot export the message '%1'. + Nelze exportovat zprávu '%1'. + + + + + First you must download the message before its export... + Musíte nejprve stáhnout kompletní zprávu před exportem... + + + Invalid certificate data Neplatná data certifikátu - + The certificate or the supplied pass-phrase are invalid. Certifikát nebo zadané heslo jsou neplatné. - + Please enter a path to a valid certificate and/or provide a correct key to unlock the certificate. Prosím zadejte cestu k platnému certifikátu a/nebo zadejte správný klíč pro odemknutí certifikátu. - + Bad certificate data for account "%1". Špatná data certifikátu pro účet "%1". - + The log-in method used in account "%1" is not implemented. Přihlašovací metoda použitá v účtu "%1" není implementována. - + Account "%1" requires authentication via OTP<br/>security code for connection to data box. Pro připojení ke schránce pro účet "%1" je<br/>vyžadována OTP autentizace bezpečnostním kódem. - + Account "%1" requires authentication via security code for connection to data box. Účet "%1" vyžaduje pro přihlášení k datové schránce autorizaci bezpečnostním kódem OTP. - + Security code will be sent to you via a Premium SMS. Bezpečnostní kód Vám bude zaslán Prémiovou SMS zprávou. - + Do you want to send a Premium SMS with a security code into your mobile phone? Chcete zaslat Prémiovou SMS s bezpečnostním kódem do Vašeho mobilu? - + + You can change your password now or later using the '%1' command. Your new password will be valid for 90 days. + +Change password now? + Heslo můžete změnit nyní nebo později pomocí příkazu '%1'. Nové heslo bude platné po dobu 90 dnů. + +Změnit heslo nyní? + + + Select target folder for export Vyberte cílový adresář pro export - - Database file error - Chyba databazového souboru + + This action allow to import messages from selected database files into current account. Keep in mind that this action may take a while based on number of messages in the imported database. Import progress will be displayed in the status bar. + Tato akce umožňuje importovat zprávy z vybraných databázových souborů do aktuálního účtu. Mějte na paměti, že tato akce může chvíli trvat v závislosti na počtu zpráv v importované databázi. Průběh importu zpráv se bude zobrazovat ve stavovém panelu aplikace. - - Split of message database for account '%1' was not successfully. Please, restart the application for loading original database. - Rozdělení databáze zpráv pro účet '%1' nebylo úspěšné. Prosím, restartujte aplikaci pro načtení původní databáze. + + This action splits current account message database into several separate databases which will contain messages relevant to one year only. It is recommended for large databases in order to improve the performance. + Tato akce umožňuje rozdělit stávající databázi zpráv do několika menších databází podle roku dodání zpráv. Akce je doporučena spíše pro účty s velkou databází ke zlepšení výkonu. + + + + The original database file will be copied to selected directory and new database files will be created in the original location. If action finishes with success then new databases will be used instead of the original. Application restart is required. + Aktuální databáze zpráv bude zkopírována do vybrané složky. Nové databázové soubory budou vytvořeny do původní složky. Jestli-že bude proces rozdělení úspěšný, původní databáze bude nehrazena novými databázemi. Poté je třeba provést restart aplikace. + + + + Note: Keep in mind that this action may take a while based on the number of messages in the database. + Poznámka: Mějte na paměti, že tato akce může chvíli trvat v závislosti na počtu zpráv v databázi. + + + + Database file error + Chyba databazového souboru - + + Database split result Výsledek rozdělení databáze - + Enter sought expression Zadete hledaný výraz - + Import of messages to account %1 finished Import zpráv na účet %1 skončil - + In Progress Vyřizuje se - + Database access error Chyba přístupu k databázi - + The file cannot be accessed or is corrupted. Please fix the access privileges or remove or rename the file so that the application can create a new empty file. Nelze přistoupik k souboru nebo je soubor poškozen. Opravte prosím přístupová oprávnění nebo odstraňte nebo přejmenujte soubor, aby aplikace mohla vytvořit nový prázdný soubor. - + Create a backup copy of the affected file. This will help when trying to perform data recovery. Vytvořte si kopii postiženého souboru. Může to pomoct při případném obnovování dat. - + In general, it is recommended to create backup copies of the database files to prevent data loss. Všeobecně je doporučováno vyrábět záložní kopie databázových souborů aby se zamezilo ztrátě dat. - - + + Mark Označit - - - - + + + + As Read Přečtené - - - - + + + + As Unread Nepřečtené - - + + Cannot write file '%1'. Nemohu uložit soubor '%1'. - + Download message list error Chyba stahování seznamu zpráv - - ISDS: - ISDS: - - - - It was not possible to download a complete message "%1" from server Datové schránky. - Nebylo možné stáhnout kompletní zprávu "%1" ze serveru Datové schránky. - - - - + Delete message %1 Mazání zprávy %1 - - + Do you want to delete message '%1'? Chcete smazat zprávu '%1'? - + Delete this message also from server ISDS Smazat tuto zprávu také z ISDS - + Warning: If you delete the message from ISDS then this message will be lost forever. Upozornění: Jestli-že smažete zprávu ze serveru ISDS, bude tato zpráva navždy ztracena. - - + Delete messages Mazaní zpráv - - + Do you want to delete selected messages? Chcete smazat vybrané zprávy? - + Delete these messages also from server ISDS Smazat tyto zprávy také z ISDS - + No ZFO files to import. Žádné ZFO soubory k importování. - + There is no account to import of ZFO files into. Není účet, do kterého lze importovat ZFO soubory. - + Complete message '%1' is missing. Chybí úplná zpráva '%1'. - + Do you want to download the complete message now? Chcete nyní stáhnout úplnou zprávu? - + Complete message '%1' has been downloaded. Úplná zpráva '%1' byla stažena. - + Complete message '%1' has not been downloaded. Úplná zpráva '%1' nebyla stažena. - + Data message Datová zpráva - + Data messages Datové zprávy - + Attachments of message Přílohy zprávy - + Attachments of messages Přílohy zpráv - + Attachment of message %1 Příloha zprávy %1 - + Attachments of message %1 Přílohy zprávy %1 - + Datovka is currently processing some tasks. Datovka právě zpracovává úlohy. - + Do you want to abort pending actions and close Datovka? Přejete si zrušit nedokončené akce a zavřít Datovku? - - + + Adding new account failed Přidávání nového účtu selhalo - + Account could not be added because an error occurred. Účet nemohl být přidán, protože nastala chyba. - + Account could not be added because account already exists. Účet nemohl být přidán, protože účet již existuje. - - Import of mesages from database - Import zpráv z databáze - - - - This action allow to import messages from selected database files into current account. Keep in mind that this action may takes a few minutes based on number of messages in the imported database. Import progress will be displayed in the status bar. - Tato akce umožňuje importovat zprávy z vybraných databázových souborů do aktuálního účtu. Mějte na paměti, že tato akce může trvat i několik minut v závislosti na počtu zpráv v importované databázi. Průběh importu zpráv se bude zobrazovat ve stavovém panelu aplikace. - - - - - + + + Do you want to continue? Chcete pokračovat? - + Select database file(s) Vyberte databázové soubory - + DB file (*.db) DB soubor (*.db) - + Messages import result Výsledek importu zpráv - + Import of messages into account '%1' finished with result: Import zpráv do účtu '%1' skončil s tímto výsledkem: - + Imported messages: %1 Importováno zpráv: '%1' - + Non-imported messages: %1 Ignorováno zpráv: '%1' - + Database split Rozdělení databáze - - This action split current account message database into several new databases which will contain messages relevant by year only. It is recommended for large database because the performance of application will be better. - Tato akce umožňuje rozdělit stávající databázi zpráv do několika menších databází podle roku dodání zpráv. Akce je doporučena spíše pro účty s velkou databází, která obsahuje mnoho zpráv. Rozdělení databáze může vést ke zrychlení aplikace i rychlejšímu přístupu k datům jednotlivých zpráv. + + Split of message database finished with error + Rozdělení databáze skončilo s chybou - - Original database file will copy to selected directory and new database files will created in the same location. If action finished with success, new databases will be used instead of original. Restart of application is required. - Aktuální databáze zpráv bude zkopírována do vybrané složky. Nové databázové soubory budou vytvořeny do stejné složky. Jestli-že bude proces rozdělení úspěšný, původní databáze bude nehrazena novými databázemi. Poté je třeba provést restart aplikace. + + Database file cannot be split into original directory. + Databázový soubor nelze rozdělit do původní složky. - - Note: Keep in mind that this action may takes a few minutes based on number of messages in the database. - Poznámka: Mějte na paměti, že tato akce může trvat i několik minut v závislosti na počtu zpráv v databázi. + + Please choose another directory. + Prosím, vyberte jiný adresář. - - Split of message database finished with error - Rozdělení databáze skončilo s chybou + + Note: Original database file was backed up to: + Původní databáze byla přesunuta do: + + + + Splitting of message database for account '%1' was not successful. Please, restart the application in order to reload the original database. + Rozdělení databáze zpráv pro účet '%1' nebylo úspěšné. Prosím, restartujte aplikaci pro načtení původní databáze. - + Vacuum cannot be performed on databases in memory. Vakuum nelze aplikovat na databáze v paměti. - + Database operation error Chyba funkce databáze - + Database clean-up cannot be performed on database in memory. Pročištění databáze nelze provést s databází v paměti. - + Cannot call VACUUM on database in memory. Nelze volat VACUUM na databázi v paměti. - + Clean message database Pročisti databázi zpráv - + Performs a message database clean-up for the selected account. This action will block the entire application. The action may take several minutes to be completed. Furthermore, it requires more than %1 of free disk space to successfully proceed. Provede pročištění databáze zpráv ve zvoleném účtu. Tato akce zablokuje celou aplikaci. Dokončení akce může trvat několik minut. Akce navíc k úspěšnému dokončení vyžaduje více jak %1 volného místa na disku. - + Performing database clean-up. Provádím pročišťování databáze. - + Database clean-up finished. Počištění databáze dokončeno. - + Database clean-up successful Pročištění úspěšně dokončeno - + The database clean-up has finished successfully. Pročištění databáze bylo úspěšně dokončeno. - + Database clean-up failure Pročištění selhalo - + The database clean-up failed with error message: %1 Pročišťování databáze selhalo s chybovým hlášením: %1 - - You have to be logged into the WebDatovka if you want to modify tags. - Musíte být přihlášeni do WebDatovky, aby bylo možné upravovat tagy. - - - - Add account(s) error - Chyba přidávání účtu - - - - There aren't any Webdatovka accounts for this mojeID identity. - Pro tuto mojeID identitu nejsou žádné účty ve WebDatovce. - - - - - You are login into wrong mojeID identity. - Jste přihlášeni do špatné mojeID identity. - - - - Please enter correct mojeID login for account '%1'. - Zadejte prosím správné mojeID přihlašovací jméno '%1'. - - - - New mojeID identity has some account(s). - Nová modeID identita má nějaké účty. - - - - Do you want to add account(s) for this mojeID identity to Datovka? - Chcete přidat účet pro tuto mojeID identitu do Datovky? - - - - Some account(s) were removed from Webdatovka for this mojeID identity. - Některé účty byly odebrány z WebDatovky pro tuto mojeID identitu. - - - - Do you want to also remove these accounts from Datovka? - Chcete také odebrat tyto účty z Datovky? - - - - This action is not supported for MojeID account '%1' - Tato akce není podporována pro mojeID účet '%1' - - - - Login problem - Problém přihlášení - - - + Select directory for new databases Vyberte složku pro nové databáze - - Database file cannot split into same directory. - Databázový soubor nelze rozdělit do stejné složky. - - - - Please, you must choose another directory. - Prosím, vyberte jinou složku. - - - + Split of message database finished Rozdělení databáze zpráv skončilo - + Congratulation: message database for account '%1' was split successfully. Please, restart the application for loading of new databases. Gratulujeme: databáze zpráv pro účet '%1' byla úspěšně rozdělena. Prosím, restartujte aplikaci pro načtení nových databází zpráv. - - Note: Original database file was backup to: - Původní databáze byla přesunuta do: - - - + It was not possible download complete message "%1" from ISDS server. Nebylo možné stáhnout celou zprávu "%1" ze serveru ISDS. - - + Download message error Chyba stahování zprávy - + Message "%1" was deleted from local database. Zpráva "%1" byla smazána z místní databáze. - + Message "%1" was deleted from ISDS and local database. Zpráva "%1" byla smazána z ISDS i z místní databáze. - + Message "%1" was deleted only from ISDS. Zpráva "%1" byla smazána pouze z ISDS. - + Message "%1" was deleted only from local database. Zpráva "%1" byla smazána pouze z místní databáze. - + Message "%1" was not deleted. Zpráva "%1" nebyla smazána. - + Synchronise all accounts with ISDS server. Synchronizují se všechny účty ze serveru ISDS. - + Messages on the server Zprávy na serveru - + received přijato - - + + new nových - + sent odesláno - + Create a new account. Vytvořit nový účet. - - - + + Select directory Vybrat adresář pro import - - Database file(s) not found in selected directory. - Databázové soubory nenalezeny ve vybraném adresáři. - - - - Select db file(s) - Vybrat databázové soubory - - - - Database file (*.db) - Databázový soubor (*.db) - - - - + Database file(s) not selected. Databázové soubory nebyly vybrány. - + Verifying the ZFO file "%1" Ověřování ZFO souboru "%1" - + Server Datové schránky confirms that the message is authentic. Server Datové schránky potvrdil, že zpráva je autentická. - - + + Message was <b>successfully verified</b> against data on the server Datové schránky. Zpráva byla <b>úspěšně ověřena</b> proti datům na serveru Datové schránky. - - + + This message has passed through the system of Datové schránky and has not been tampered with since. Tato zpráva prošla systémem Datových schránek a nebyla od té doby upravena. - + Server Datové schránky confirms that the message is not authentic. Server Datové schránky potvrdil, že zpráva není autentická. - - + + Message was <b>not</b> authenticated as processed by the system Datové schránky. Zpráva <b>nebyla</b> ověřena jako zpracovaná systémem Datové schránky. - - + + It is either not a valid ZFO file or it was modified since it was downloaded from Datové schránky. Soubor buď neobsahuje platný ZFO obsah, nebo byl od chvíle stažení ze systému Datových schránek modifikován. - - - + + + Message authentication failed Autentizace zprávy selhala - - + + Authentication of message has been stopped because the connection to server Datové schránky failed! Check your internet connection. Autentizace zprávy byla zastavena, protože se nezdařilo připojení k serveru Datové schránky! Zkontrolujte připojení k internetu. - + Server Datové schránky confirms that the message is valid. Server Datové schránky potvrdil, že zpráva je validní. - + Server Datové schránky confirms that the message is not valid. Server Datové schránky potvrdil, že zpráva není validní. - + Message is not valid Zpráva není validní - - - - - + + + + + Message verification failed. Verifikace zprávy selhala. - + Verification failed Verifikace zprávy selhala - - - - + + + + Verification error Chyba verifikace - + The message hash is not in local database. Please download complete message from ISDS and try again. Otisk zprávy nebyl nalezen v lokální databázi. Prosím, stáhněte kompletní zprávu ze serveru Datové schránky a zkuste to znova. - - - - + + + + ZFO file(s) not found in selected directory. V adresáři nebyly nalezeny ZFO soubory. - - + + No ZFO file(s) Žádné ZFO soubory - + Select ZFO file(s) Vyberte ZFO soubory - + ZFO file(s) not selected. Nebyly vybrány ZFO soubory. - + Message '%1' stored to temporary file '%2'. Zpráva '%1' uložena do dočasného souboru '%2'. - + Message '%1' couldn't be stored to temporary file. Zpráva '%1' nemohla být uložena do dočasného souboru. - - + + Error opening message '%1'. Chyba při otevírání zprávy '%1'. - + Message acceptance information '%1' stored to temporary file '%2'. Doručenka zprávy '%1' uložena do dočasného souboru '%2'. - + Message acceptance information '%1' couldn't be stored to temporary file. Doručenka zprávy '%1' nemohla být uložena do dočasného souboru. - + Password required Vyžadováno heslo - + Account: %1 User name: %2 Certificate file: %3 @@ -3569,593 +3972,446 @@ Zadejte heslo pro odemčení souboru certifikátu: - - - - - - - + + + + + + + It was not possible to connect to your data box from account "%1". Nepodařilo se přihlásit k datové schránce z účtu "%1". - + + Password expiration Expirace hesla - + According to the last available information, your password for account '%1' (login '%2') expired %3 days ago (%4). Podle nejnovějších dostupných informací Vaše heslo pro účet '%1' (přihlašovací jméno '%2') vypršelo před %3 dnem/dny (%4). - + According to the last available information, your password for account '%1' (login '%2') will expire in %3 days (%4). Podle nejnovějších dostupných informací Vaše heslo pro účet '%1' (přihlašovací jméno '%2') vyprší za %3 dny/dnů (%4). - - You can change your password now, or later using the 'Change password' command. Your new password will be valid for 90 days. - -Change password now? - Heslo můžete změnit nyní nebo později pomocí příkazu 'Změnit heslo'. Nové heslo bude platné po dobu 90 dnů. - -Změnit heslo nyní? - - - + Enter OTP security code Zadejte OTP bezpečnostní kód - + Database is stored in memory. Data will be lost on application exit. Databáze je uložena v paměti. Data budou ztracena při vypnutí aplikace. - - + + Local database file location Umístění souboru místní databáze - + Create and send a message. Vytvoř a odešli zprávu. - + Account '%1' was deleted but its message database was not deleted. Účet '%1' byl smazán, ale jeho databázi zpráv se smazat nepodařilo. - - This database file has been set as actual message database for this account. Maybe you have to change account properties for correct login to the server Datové schránky. - Tento databázový soubor byl nastaven jako aktuální databáze pro ukládání zpráv pro nový účet. Možná bude zapotřebí upravit vlastnosti tohoto účtu aby bylo možné se připojit k serveru Datové schránky. - - - - - - Create account: %1 - Nový účet: %1 - - - + Tags Tagy - + + User-assigned tags + Uživatelem přiřazené tagy + + + Saving attachment of message '%1' to files was not successful! Nepodařilo se uložit přílohu zprávy '%1'! - + Saving attachment of message '%1' to file was successful. Nepodařilo se uložit přílohu zprávy '%1'. - + Saving attachment of message '%1' to file was not successful! Nepodařilo se uložit přílohu zprávy '%1'! - + Attachment '%1' stored into temporary file '%2'. Příloha '%1' uložena do dočasného souboru '%2'. - + Attachment '%1' couldn't be stored into temporary file. Příloha '%1' nemohla být uložena do dočasného souboru. - - + A connection error occurred or the message has already been deleted from the server. Nastala chyba spojení, nebo zpráva již byla smazána ze serveru. - - + Couldn't download message '%1'. - Nešlo stáhnout zprávu '%1'. - - - - It was not possible download complete message "%1" from webdatovka server. - Nebylo možné stáhnout celou zprávu '%1' ze serveru WebDatovky. - - - - It was not possible to download a complete message "%1" from webdatovka server. - Nebylo možné stáhnout celou zprávu '%1' ze serveru WebDatovky. - - - - Webdatovka: - WebDatovka: + Nešlo stáhnout zprávu '%1'. - + It was not possible download received message list from server. Nebylo možné stáhnout seznam přijatých zpráv ze serveru. - + It was not possible download sent message list from server. Nebylo možné stáhnout seznam odeslaných zpráv ze serveru. - - Server: - Server: - - - + A connection error occurred. Nastala chyba spojení. - + Message from '%1' (%2) has been successfully sent to '%3' (%4). Zpráva od '%1' (%2) byla úspěšně odeslána příjemci '%3' (%4). - + Error while sending message from '%1' (%2) to '%3' (%4). Chyba během odesílání zprávy od '%1' (%2) příjemci '%3' (%4). - + Message "%1" was downloaded from server. Zpráva "%1" byla úspěšně stažena ze serveru. - + Warning: If you delete selected messages from ISDS then these messages will be lost forever. Upozornění: Jestli-že smažete vybrané zprávy ze serveru ISDS, budou tyto zprávy navždy ztraceny. - - You have to be logged into the Webdatovka if you want to delete message(s). - Musíte být přihlášeni do WebDatovky, aby bylo možné mazat zprávy. - - - - Warning: If you delete the message from Webdatovka then this message will be lost forever. - Upozornění: Jestliže smažete vybrané zprávy z WebDatovky, budou tyto zprávy navždy ztraceny. - - - - Warning: If you delete selected messages from Webdatovka then these messages will be lost forever. - Upozornění: Jestli-že smažete vybrané zprávy z WebDatovky, budou tyto zprávy navždy ztraceny. - - - - - You have to be logged into the WebDatovka if you want to download complete message. - Musíte být přihlášeni do WebDatovky, aby bylo možné stahovat kompletní zprávy. - - - - MojeID account - MojeID účet - - - + Some databases of %1 in '%2' cannot be used. Některé databáze %1 v '%2' nelze použít. - + Conflicting databases %1 in '%2' cannot be used. Konfliktní databáze %1 v '%2' nelze použít. - + Please remove the conflicting files. Prosím, odstraňte konfliktní databázové soubory. - + Database files in '%1' cannot be created or are corrupted. Databázové soubory v '%1' nelze vytvořit nebo jsou poškozené. - + Full message not present! Úplná zpráva není k dispozici! - - Database files for '%1' have been successfully moved to - -'%2'. - Databázové soubory pro '%1' byl úspěšně přesunuty do - -'%2'. - - - - Database files for '%1' could not be moved to - -'%2'. - Databázové soubory pro '%1' nemohly být přesunuty do - -'%2'. - - - - Database files for '%1' have been successfully copied to - -'%2'. - Databázové soubory pro '%1' byl úspěšně překopírovány do - -'%2'. - - - - Database files for '%1' could not be copied to - -'%2'. - Databázové soubory pro '%1' nemohli být překopírovány do - -'%2'. - - - - New database files for '%1' have been successfully created in - -'%2'. - Databázové soubory pro '%1' byl úspěšně vytvořeny v - -'%2'. - - - - New database files for '%1' could not be created in - -'%2'. - Databázové soubory pro '%1' nemohli být vytvořeny v - -'%2'. - - - - You have to be logged into the WebDatovka if you want to find databox. - Musíte být přihlášeni do WebDatovky, aby bylo možné vyhledávat datové schránky. - - - + Enter OTP security code for account Zadejte OTP bezpečnostní kód pro účet - - + + Portable version Přenosná verze - - + + Change password of account "%1". Změnit heslo pro účet "%1". - + Change properties of account "%1". Změnit vlastnosti účtu "%1". - + Account "%1" was updated. Účet "%1" byl aktualizován. - + Account was moved up. Účet byl posunut nahoru. - + Account was moved down. Účet byl posunut dolů. - + Change data dierctory of account "%1". Změnit adresář pro data u účtu "%1". - + Find databoxes from account "%1". Vyhledat datovou schránku z účtu "%1". - - - + + + Message authentication failed. Zpráva je validní. - + Authentication of message has been stopped because the message file has wrong format! Ověřování zprávy bylo zastaveno, protože zpráva má chybný formát! - - - + + + An undefined error occurred! Try again. Došlo k neznámé chybě! Zkuste to znovu. - + Message is valid Zpráva je platná - + The message hash cannot be verified because an internal error occurred! Try again. Nebylo možné ověřit otisk zprávy, protože se v aplikaci vyskytla chyba! Zkuste to znova. - - - + + + + Message export error! Chyba exportu zprávy! - + You have to change your password from the ISDS web interface. Your new password will be valid for 90 days. Heslo si změňte ve webovém rozhraní ISDS. Vaše nové heslo bude platné 90 dnů. - - + + Checking time stamps in account '%1'... Kontrola časových razítek v účtu '%1'... - + Time stamp expiration check results Výsledky kontroly expirace časových razítek - + Time stamp expiration check in account '%1' finished with result: Kontrola časových razítek v účtu '%1' skončila s výsledkem: - + Loading of ZFO file(s) failed! Načítání ZFO souborů selhalo! - + Time stamp expiration check of ZFO files finished with result: Kontrola časových razítek ZFO souborů skončila s výsledkem: - + Total of ZFO files: %1 Celkem ZFO souborů: %1 - + ZFO files with time stamp expiring within %1 days: %2 ZFO souborů s časovým razítkem expirujícím do %1 dnů: %2 - + Unchecked ZFO files: %1 Nezkontrolovaných ZFO souborů: %1 - - + + Total of messages in database: %1 Celkem zpráv v databázi: %1 - + Messages with time stamp expiring within %1 days: %2 Zpráv s časovým razítkem expirujícím do %1 dnů: %2 - + Unchecked messages: %1 Nezkontrolovaných zpráv: %1 - + See details for more info... Více informací naleznete v podrobnostech... - + Do you want to export the expiring messages to ZFO? Chcete exportovat expirující zprávy do ZFO? - - + + Time stamp of message %1 expires within specified interval. Časové razítko zprávy %1 expiruje do určeného limitu. - - + + Time stamp of message %1 is not present. Časové razítko zprávy %1 není k dispozici. - - + + Datovka - Export error! Datovka - chyba exportu! - - - Cannot export the message - Nelze exportovat zprávu - - - - - First you must download message before its export... - Musíte nejprve stáhnout kompletní zprávu před exportem... - - - + SMS code for account SMS kód pro účet - + Datovka Datovka - + New account error Chyba nového účtu - + It was not possible to get user info and databox info from ISDS server for account Nebylo možné získat informace o uživateli a jeho datové schránce ze serveru ISDS pro účet - + Account Účet - + was not created! nebyl vytvořen! - + Welcome... Vítejte... - + Storage: disk | disk Úložiště: disk | disk - + unknown or without expiration Neznámý nebo bez expirace - - Account with user name '%1' and its message database already exist. New account was not created and selected database file was not associated with this account. - Účet s uživatelským jménem '%1' a jeho databáze již existují. Nový účet nebyl vytvořen a vybraná databáze nebyla k účtu přiřazena. - - - - Account with name '%1' has been created (user name '%1'). - Účet s názvem '%1' byl vytvořen (uživatelské jméno '%1'). - - - - + Mode: online Režim: připojeno (online) - - - File Soubor - + Message Zpráva - + Tools Nástroje - + Help Nápověda - + toolBar Panel nástrojů - + Sync all accounts Synchronizovat účty - + Download complete message, including attachments and verify its signature Stáhnout kompletní zprávu, včetně příloh a ověřit její podpis - + Open attachment in an associated application Otevřít přílohu v přiřazené aplikaci - + Signature details Detail podpisu - + Data box Schránka - - + + Remove account Odstranit účet @@ -4176,487 +4432,493 @@ nebo vyřízeno (bylo na zprávu odpovězeno) - + Unsettled Nevyřízeno - + Settled Vyřízeno - + Shift+F5 Shift+F5 - - + + Proxy settings Nastavení proxy - + Preferences Nastavení - + Preferences of Datovka Nastavení Datovky - + Quit Ukončit - + Ctrl+Q Ctrl+Q - - + + Create account from database Vytvořit účet z databáze - + F5 F5 - + Create message Vytvořit zprávu - + Ctrl+N Ctrl+N - + Mark all as read Označit vše jako přečtené - + Change password Změnit heslo - + Account properties Vlastnosti účtu - + Move account up Posunout účet nahoru - + Move account down Posunout účet dolů - + Change data directory Změnit adresář pro uložení dat - + About Datovka O Datovce - + About Datovka application O Datovce - + Find Data Box Vyhledat datovou schránku - + Authenticate message file Ověřit zprávu ze souboru ZFO - + View message from ZFO file Zobrazit zprávu ze souboru ZFO - + Export correspondence overview Exportovat přehled korespondence - + Synchronize all accounts at once Synchronizovat všechny účty najednou - + Add new data box account Přidat nový účet k datovým schránkám - + Quit the application Ukončit aplikaci - + Sync account Synchronizovat účet - + Synchronize selected account Synchronizovat vybraný účet - + Mark all messages as read Označit všechny zprávy jako přečtené - + Sets a new password to the selected account on the ISDS server Nastaví nové heslo pro zvolený účet na serveru ISDS - + Manage account properties Spravovat vlastnosti účtu - + Move selectet account one position up Posunout vybraný účet jednu pozici nahoru - + Move selectet account one position down Posunout vybraný účet jednu pozici dolů - + Change the directory where data are being stored for the selected account Změnit adresář, kam se ukládají data pro vybraný účet - + Find data box Najít datovou schránku - + Verify message authenticity Ověřit pravost zprávy - + View content of a ZFO file Zobrazit obsah ZFO souboru - + Create a correspondence overview Vytvořit přehled korespondence - + Download signed message Stáhnout podepsanou zprávu - + Reply to the selected message Odpovědět na vybranou zprávu - + Display details about the signature Zobrazit podrobnosti o podpisu - + Deletes message from local database and/or from ISDS server Vymazat zprávu z lokální databáze a/nebo ze serveru ISDS - + Export the selected message as ZFO file Exportovat vybranou zprávu jako ZFO soubor - + Pass the selected message to an external application Předat vybranou zprávu externí aplikaci - + Pass the acceptance information of the selected message to an external application Předat doručenku vybrané zprávy externí aplikaci - + Export the acceptance information of the selected message as ZFO file Exportovat doručenku vybrané zprávy jako ZFO soubor - + Export the acceptance information of the selected message as PDF file Exportovat doručenku vybrané zprávy jako PDF soubor - + Export the envelope of the selected message as PDF file Exportovat obálku vybrané zprávy jako PDF soubor - + Export envelope PDF with attachments Exportovat obálku jako PDF s přílohami - + Export the envelope to a PDF file together with message attachments Exportovat obálku to souboru PDF společně s přílohami zprávy - + Save selected attachments to files Uložit vybrané přílohy do souborů - + Saves all message attachments Uloží všechny přílohy zprávy - + Import messages from ZFO files Importovat zprávy ze souborů ZFO - + Import a message from ZFO file into the database Importovat zprávu se souboru ZFO do databáze - + Use the selected message as a template Použít vybranou zprávu jako šablonu - + Search message Vyhledat zprávu - + Check whether the message time stamp is not expired or expiring Oveřit, zda časové razítko zprávy neexpirovalo nebo neexpiruje - + Homepage Domovská stránka - + Open the home page of the application Otevřít domovskou stránku aplikace - + + Import messages from database Importovat zprávy z databáze - + Import messages into database from an external database file Importovat zprávy do databáze z externího databázového souboru - + Split database by years Rozdělit databázi podle roků - + Messages are going to be stored into separate database files according to years Zprávy budou ukládány do databázových souborů rozdělených podle let - + E-mail with ZFOs E-mail se ZFO - + Creates an e-mail containing ZFOs of selected messages Vytvoří e-mail obsahující ZFO vybraných zpráv - + E-mail with all attachments E-mail se všemi přílohami - + Creates an e-mail containing all attachments of selected messages Vytvoří e-mail obsahující všechny přílohy vybraných zpráv - + E-mail with selected attachments E-mail s vybranými přílohami - + Creates an e-mail containing selected attachments Vytvoří e-mail obsahující vybrané přílohy - - + + Edit tags Editovat tagy - + Vacuum message database Vakuum databáze zpráv - + This may reduce the database file size and optimise the access speed To může zmenšit velikost databáze a optimalizovat přístupovou rychlost - - + + Forward message Přeposlat zprávu - - Add mojeID account - Přidat účet mojeID + + Records management settings + Nastavení spisové služby + + + + Send to records management + Odeslat do spisové služby - - Add new mojeID account - Přidat nový mojeID účet + + Update records management information + Aktualizovat informace ze spisové služby - + Use message as template Použít zprávu jako šablonu - + Advanced searching in message envelopes Rozšířené vyhledávání v obálkách zpráv - + Time stamp expiration check Zkontrolovat expirace časových razítek - + Ctrl+Shift+F Ctrl+Shift+F - - + + User manual Uživatelská příručka - + Create and send a new message Vytvořit a poslat novou zprávu - + Verify the selected message Ověřit vybranou zprávu - + Reply to message Odpovědět na zprávu - + Ctrl+R Ctrl+R - + Authenticate message Ověřit zprávu - + Delete message Vymazat zprávu - + Export message as ZFO Exportovat zprávu jako soubor ZFO - + Open message externally Otevřít zprávu externí aplikací - + Open acceptance info externally Otevřít doručenku pomocí externí aplikace - + Export acceptance info as ZFO Exportovat doručenku do ZFO - + Export acceptance info as PDF Exportovat doručenku do PDF - + Export message envelope as PDF Exportovat obálku zprávy do PDF - + Open attachment Otevřít přílohu - + Save attachment Uložit soubor jako - + Save all attachments Uložit vše @@ -5302,7 +5564,7 @@ - The HTTPS protocol is used when accessing the Databox server while HTTP is used to download the certificate revocation list and information about new Datovka versions. + The HTTPS protocol is used when accessing the Databox server while HTTP is used to download the certificate revocation list and information about new Datovka versions. Protokol HTTPS je využíván k přístupu na server Datových schránek. Protokol HTTP je použit ke stažení seznamu zneplatněných certifikátů a informací o nových verzích Datovky. @@ -5366,690 +5628,368 @@ Show HTTPS proxy authentication. - Zobrazit HTTPS proxy přihlašovací údaje. - - - - - Username: - Uživatelské jméno: - - - - - Enter your username - Zadejte své uživatelské jméno - - - - - Password: - Heslo: - - - - - Enter your password - Zadejte heslo - - - - HTTP proxy - HTTP proxy - - - - - Show HTTP proxy authentication. - Zobrazit HTTP proxy přihlašovací údaje. - - - - QObject - - - Postal data message - Poštovní datová zpráva - - - - Initializing postal data message - Inicializační poštovní datová zpráva - - - - Reply postal data message - Odpovědní poštovní datová zpráva - - - - Initializing postal data message - expired - Inicializační poštovní datová zpráva - propadlá - - - - Initializing postal data message - used - Inicializační poštovní datová zpráva - použitá - - - - Primary user - Oprávněná osoba - - - - Entrusted user - Pověřená osoba - - - - Administrator - Administrátor - - - - Official - Oficiální - - - - Virtual - Virtuální - - - - File '%1' does not contain a valid database filename. - Databázový soubor '%1' neobsahuje správny název. - - - - File '%1' does not contain a valid username in the database filename. - Databáze '%1' neobsahuje správné uživatelské jméno v názvu souboru. - - - - File '%1' does not contain valid year in the database filename. - Databáze '%1' neobsahuje správný rok v názvu souboru. - - - - - File '%1' does not contain valid database filename. - Databáze '%1' neobsahuje správný název souboru. - - - - File '%1' does not contain a valid account type flag or filename has wrong format. - Databáze '%1' neobsahuje správný typ účtu nebo názvu souboru má špatný formát. - - - - File '%1' does not contain a valid message database or filename has wrong format. - Soubor '%1' neobsahuje validní databázi zpráv nebo název souboru má špatný formát. - - - - Message did not pass through AV check; infected paper deleted; final status before deletion. - Zpráva neprošla AV kontrolou; nakažená písemnost je smazána; konečný stav zprávy před smazáním. - - - - Message handed into ISDS (delivery time recorded). - Zpráva dodána do ISDS (zapsán čas dodání). - - - - 10 days have passed since the delivery of the public message which has not been accepted by logging-in (assumption of acceptance through fiction in non-OVM DS); this state cannot occur for commercial messages. - Uplynulo 10 dnů od dodání veřejné zprávy, která dosud nebyla doručena přihlášením (předpoklad doručení fikcí u ne-OVM DS); tento stav nemůže nastat v případě poštovních datových zpráv. - - - - Message has been read (on the portal or by ESS action). - Zpráva byla přečtena (na portále nebo akcí ESS). - - - - Message has been submitted (has been created in ISDS) - Zpráva byla podána (vznikla v ISDS) - - - - Data message including its attachments signed with time-stamp. - Datová zpráva včetně písemností podepsána časovým razítkem. - - - - A person authorised to read this message has logged in -- delivered message has been accepted. - Osoba oprávněná číst tuto zprávu se přihlásila -- dodaná zpráva byla doručena. - - - - Message marked as undeliverable because the target DS has been made inaccessible. - Zpráva byla označena jako nedoručitelná, protože DS adresáta byla zpětně znepřístupněna. - - - - Message content deleted, envelope including hashes has been moved into archive. - Zpráva byla označena jako nedoručitelná, protože DS adresáta byla zpětně znepřístupněna. - - - - Message resides in data vault. - Zpráva je v Datovém trezoru. - - - - Full control - Plný přístup - - - - Restricted control - Omezený přístup - - - - download and read incoming DM - stahovat a číst došlé DZ - - - - download and read DM sent into own hands - stahovat a číst DZ určené do vlastních rukou - - - - create and send DM, download sent DM - vytvářet a odesílat DZ, stahovat odeslané DZ - - - - retrieve DM lists, delivery and acceptance reports - načítat seznamy DZ, dodejky a doručenky - - - - search for data boxes - vyhledávat DS - - - - manage the data box - spravovat DS - - - - read message in data vault - číst zprávy v datovém trezoru + Zobrazit HTTPS proxy přihlašovací údaje. - - erase messages from data vault - mazat zprávy v datovém trezoru + + + Username: + Uživatelské jméno: - - System ISDS - Systém ISDS + + + Enter your username + Zadejte své uživatelské jméno - - Public authority - Orgán veřejné moci (OVM) + + + Password: + Heslo: - - Legal person - Právnická osoba (PO) + + + Enter your password + Zadejte heslo - - Self-employed person - Podnikající fyzická osoba (OSVČ) + + HTTP proxy + HTTP proxy - - Natural person - Fyzická osoba (FO) + + + Show HTTP proxy authentication. + Zobrazit HTTP proxy přihlašovací údaje. + + + QObject - - The data box is accessible. It is possible to send messages into it. It can be looked up on the Portal. - Datová schránka je přístupná, lze do ní dodávat zprávy, na Portále lze vyhledat. + + File '%1' does not contain a valid database filename. + Databázový soubor '%1' neobsahuje správny název. - - The data box is temporarily inaccessible (at own request). It may be made accessible again at some point in the future. - Datová schránka je dočasně znepřístupněna (na vlastní žádost), může být později opět zpřístupněna. + + File '%1' does not contain a valid username in the database filename. + Databáze '%1' neobsahuje správné uživatelské jméno v názvu souboru. - - The data box is so far inactive. The owner of the box has to log into the web interface at first in order to activate the box. - Datová schránka je dosud neaktivní. Vlastník schránky se musí poprvé přihlásit do webového rozhraní, aby došlo k aktivaci schránky. + + File '%1' does not contain valid year in the database filename. + Databáze '%1' neobsahuje správný rok v názvu souboru. - - The data box is permanently inaccessible. It is waiting to be deleted (but it may be made accessible again). - Datová schránka je trvale znepřístupněna, čeká na smazání (může být opět zpřístupněna). + + + File '%1' does not contain valid database filename. + Databáze '%1' neobsahuje správný název souboru. - - The data box has been deleted (none the less it exists in ISDS). - Datová schránka byla smazána (přesto existuje v ISDS). + + File '%1' does not contain a valid account type flag or filename has wrong format. + Databáze '%1' neobsahuje správný typ účtu nebo názvu souboru má špatný formát. - - An error occurred while checking the status. - Došlo k chybě při zjišťování stavu. + + File '%1' does not contain a valid message database or filename has wrong format. + Soubor '%1' neobsahuje validní databázi zpráv nebo název souboru má špatný formát. - + File name Název souboru - + Data box ID ID datové schránky - + Data box type Typ datové schránky - - + + - - + + Given name Jméno - - + + Middle name Prostření jméno - - + + Surname Příjmení - - + + Surname at birth Rodné příjmení - - + + Company name Název firmy - - + + Date of birth Datum narození - + City of birth Místo narození - + County of birth Okres narození - + State of birth Stát narození - - + + City of residence Sídlo - město - - + + Street of residence Sídlo - ulice - - + + Number in street Číslo orientační - - + + Number in municipality Číslo popisné - - - + + + Zip code PSČ - - + + State of residence Sídlo - stát - + Nationality Státní občanství - + Databox state Stav schránky - + Effective OVM Efektivní OVM - + Open addressing Otevřené adresování - + User type Typ uživatele - + Permissions Oprávnění - + City Město - + Street Ulice - + State Stát - + ID ID - - - - + + + + Sender Odesílatel - + Sender address Adresa odesílatele - - - - + + + + Recipient Příjemce - + Recipient address Adresa příjemce - - - + + + To hands K rukám - + Section Sekce - + Acceptance through fiction enabled Doručení fikcí povoleno - + Delivery time Čas dodání - + Acceptance time Čas doručení - + Your reference number Vaše číslo jednací - + Our reference number Naše číslo jednací - + Your file mark Vaše spisová značka - + Our file mark Naše spisová značka - + Law Zákon - + Year Rok - + Paragraph Odstavec - + Letter Písmeno - + Personal delivery Doručení do vlastních rukou - - + + Status Stav - + Attachment size Velikost příloh - + Mime type Typ MIME - + Read locally Přečteno lokálně - - Data box application - Aplikace pro datové schránky - - - - Use <conf-subdir> subdirectory for configuration. - Použít <conf-subdir> podadresář pro konfiguraci. - - - - conf-subdir - conf-subdir - - - - On start load <conf> file. - Po spuštění načíst <conf> soubor. - - - - - conf - conf - - - - On stop save <conf> file. - Po ukončení uložit <conf> soubor. - - - - Log messages to <file>. - Zaznamenávat výpisy do <souboru>. - - - - file - soubor - - - - Set verbosity of logged messages to <level>. Default is - Nastavit podrobnost ladicích zpráv na <level>. Výchozí je - - - - - level - úroveň - - - - Set debugging verbosity to <level>. Default is - Nastavit podrobnost ladicích informací na <level>. Výchozí je - - - - Service: connect to isds and login into databox. - Služba: připojit se k datové schránce. - - - - Service: download acceptance info of message with signature and time stamp of MV. - Služba: stáhnout informace o doručení zprávy s podpisem a časovým razítkem MV. - - - + Application is loading... Aplikace se načítá... - - - - - - - string-of-parameters - řetězec-parametrů - - - - Service: download list of received/sent messages from ISDS. - Služba: stáhnout seznam přijatých a odeslaných zpráv z ISDS. - - - - Service: create and send a new message to ISDS. - Služba: vytvořit a odeslat novou zprávu do ISDS. - - - - Service: download complete message with signature and time stamp of MV. - Služba: stáhnout kompletní zprávu s podpisem a časovým razítkem MV. - - - - Service: get information about user (role, privileges, ...). - Služba: stáhnout informace o uživateli (role, oprávnění, ...). - - - - Service: get information about owner and its databox. - Služba: stáhnout informace o vlastníkovi a jeho datové schránce. - - - - Service: get list of messages where attachment missing (local database only). - Služba: získat seznam zpráv bez přílohy (pouze lokální databaze). - - - - Service: find a databox via several parameters. - Služba: vyhledat datovou schránku na ISDS. - - - - ZFO file to be viewed. - Zobrazovaný ZFO soubor. - - - + Advice of Acceptance Doručenka - - + + Message ID: ID zprávy: @@ -6057,280 +5997,280 @@ - - - - + + + + Name Jméno - - + + General Information Obecné informace - - - - + + + + Subject Předmět - - + + paragraph odstavec - - + + letter písmeno - - + + Delegation Zmocnění - - - - - - - - - - + + + + + + + + + + Not specified Nebylo zadáno - - + + Our ref.number Naše číslo jednací - - + + Our doc.id Naše spisová značka - - + + Your ref.number Vaše číslo jednací - - + + Your doc.id Vaše spisová značka - - - - + + + + yes ano - - - - + + + + no ne - - + + Personal Delivery Osobní doručení - + List of attachments Seznam příloh - + Delivery/Acceptance Information Informace o dodání/doručení - - + + Delivery Dodání - + Databox type Typ datové schránky - + Download the complete message in order to verify its time stamp. Stáhněte kompletní zprávu pro ověření jejího časového razítka. - - + + Prohibit Acceptance through Fiction Zakázat doručení fikcí - + Acceptance Doručení - - + + Events Události - + Sender Databox ID ID datové schránky odesílatele - + Recipient Databox ID ID datové schránky příjemce - + Time Čas - + Envelope Obálka - - + + Databox ID ID schránky - + Databox Type Typ datové schránky - - - - + + + + Attachments Přílohy - + Identification Identifikace - + Message ID ID zprávy - + Message type Typ zprávy - + Sender Address Adresa odesílatele - + Message author Odesílající osoba - + Recipient Address Adresa příjemce - + (downloaded and ready) (staženo a připraveno) - + not downloaded yet, ~ ještě nestaženo, ~ - + KB; use 'Download' to get them. KB; použijte 'Stáhnout' k jejich získání. - + (not available) (nestažené) - + Signature Podpis - - - + + + Message signature Podpis zprávy - - + + Not present Není k dispozici - + Download the complete message in order to verify its signature. Stáhněte kompletní zprávu pro ověření jejího podpisu. - + Time stamp Časové razítko - - - - - - + + + + + + Invalid Neplatný - - + + Message signature and content do not correspond! Podpis zprávy a její obsah si neodpovídají! @@ -6339,30 +6279,30 @@ - - - - - - + + + + + + Valid Platný - - + + Certificate revocation check is turned off! Kontrola zneplatnění certifikátu je vypnutá! - + Signing certificate Podepisující certifikát - + Depends on libraries: Závisí na knihovnách: @@ -6374,13 +6314,13 @@ - + No Ne - + Yes Ano @@ -6489,7 +6429,7 @@ Časové razítko není přítomno. - + Created using Datovka Vytvořeno Datovkou @@ -6499,67 +6439,67 @@ Tento soubor (zpráva) nebyl vložen do databáze, protože odpovídající databázový soubor nemohl být otevřen, nebo vytvořen. - + Message '%1' already exists in the local database, account '%2'. Zpráva '%1' již v lokální databázi existuje, účet '%2'. - - + + Couldn't read data from file for authentication on the ISDS server. Data ze souboru nemohla být přečtena za účelem ověření serverem ISDS. - - + + Error contacting ISDS server. Chyba při navazování spojení se serverem ISDS. - + Message '%1' could not be authenticated by ISDS server. Zpráva '%1' nemohla být ověřena serverem ISDS. - - + + File has not been imported because an error was detected during insertion process. Soubor nebyl importován, protože byla zjištěna chyba v průběhu ukládání. - + Imported message '%1', account '%2'. Importována zpráva '%1', účet '%2'. - - - + + + Wrong ZFO format. This file does not contain correct data for import. Špatný formát ZFO. Soubor neobsahuje platná data pro import. - + The selection does not contain any valid ZFO file. Vybraný soubor neobsahuje platný ZFO formát. - + This file (acceptance info) has not been inserted into database because there isn't any related message with id '%1' in the databases. Tento soubor (doručenka) nebyl vložen do databáze, protože v databázi nebyla nalezena žádná odpovídající zpráva s id '%1'. - + Acceptance info for message '%1' already exists in the local database, account '%2'. Doručenka '%1' již v lokální databázi existuje, účet '%2'. - + Acceptance info for message '%1' could not be authenticated by ISDS server. Doručenka zprávy '%1' nemohla být ověřena serverem ISDS. - + Imported acceptance info for message '%1', account '%2'. Importována doručenka zprávy '%1', účet '%2'. @@ -6829,30 +6769,60 @@ Prosím, restartujte aplikaci. - + Tags Tagy - + Message '%1' does not contain data necessary for ZFO export. Zpráva '%1' neobsahuje potřebná data pro export do ZFO souboru. - + Message '%1' does not contain acceptance info data necessary for ZFO export. Zpráva '%1' neobsahuje data potřebná pro export doručenky do ZFO souboru. - + Message '%1' does not contain message envelope data necessary for PDF export. Zpráva '%1' neobsahuje data potřebná pro export obálky do PDF souboru. - + Message '%1' does not contain acceptance info data necessary for PDF export. Ke zprávě '%1' chybí data doručenky, která jsou potřeba pro export do PDF. + + + Message '%1' could not be uploaded. + Zpráva '%1' nemohla být nahrána. + + + + Received error + Obdržená chyba + + + + File Upload Error + Chyba při nahrávání souboru + + + + Successful File Upload + Úspěšné nahrání souboru + + + + Message '%1' was successfully uploaded into the records management service. + Zpráva '%1' byla úspěšně nahrána do spisové služby. + + + + It can be now found in the records management service in these locations: + Ve spisové službě ji můžete nyní nalézt v těchto místech: + SendMessage @@ -6867,6 +6837,11 @@ Prosím, vyplňte ve formuláři <b>předmět</b>, <b>alespoň jednoho příjemce</b> a <b>alespoň jednu přílohu</b>: + + Sender: + Odesílatel: + + Subject: Předmět: @@ -7044,11 +7019,6 @@ Účet: - - Sender: - Odesílatel: - - Find and add a recipient from Datové schránky server Najít a přidat příjemce ze serveru Datové schránky @@ -7178,77 +7148,6 @@ - TagDialog - - - Tag properties - Vlastnosti tagu - - - - Tag name: - Jméno tagu: - - - - Tag color: - Barva tagu: - - - - Change - Změnit - - - - TagsDialog - - - Tag manager - Správce tagů - - - - Tag operations - Operace s tagy - - - - Add - Přidat - - - - Update - Upravit - - - - Delete - Smazat - - - - Tag assignment - Přiřazení tagů - - - - Assign - Přiřadit - - - - Remove - Odstranit - - - - Remove all - Odstranit vše - - - TagsModel @@ -7257,6 +7156,14 @@ + UploadHierarchyModel + + + Records Management Hierarchy + Hierarchie spisové služby + + + ViewZfo diff -Nru datovka-4.8.3/locale/datovka_en.ts datovka-4.9.3/locale/datovka_en.ts --- datovka-4.8.3/locale/datovka_en.ts 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/locale/datovka_en.ts 2017-09-06 11:49:23.000000000 +0000 @@ -2,62 +2,34 @@ - AboutDialog - - - Version: - - - - - About Datovka - - - - - Copyright © - - - - - Licence - - - - - Credits - - - - AccountModel - + Recent Received - + Recent Sent - + All - + Received - + Sent - + Accounts @@ -161,60 +133,141 @@ - ChangeDirectory + CLIParser - - Change data directory for current account + + Data box application - - Data for this account is currenly stored in: + + Use <%1> subdirectory for configuration. - - n/a + + + conf-subdir - - Select a new directory where data should be stored: + + On start load <%1> file. - - New data directory + + + conf - - Choose + + On stop save <%1> file. - - Cannot used the original directory as destination! + + Log messages to <%1>. - - Action + + file - - Move data to the new directory + + Set verbosity of logged messages to <%1>. Default is %2. - - Copy data to the new directory + + + + + level - - Start afresh in the new directory + + Enable debugging information. + + + + + Set debugging verbosity to <%1>. Default is %2. + + + + + Service: connect to ISDS and login into data box. + + + + + + + + + + + string-of-parameters + + + + + Service: download list of received/sent messages from ISDS (synchronization). + + + + + Service: create and send a new message to ISDS. + + + + + Service: download complete message with signature and time stamp of MV. + + + + + Service: download acceptance info of message with signature and time stamp of MV. + + + + + Service: get information about user (role, privileges, ...). + + + + + Service: get information about owner and its data box. + + + + + Service: get list of messages where attachment missing (local database only). + + + + + Service: find a data box via several parameters. + + + + + Service: get list of message IDs (received/sent) from local database. + + + + + [zfo-file] + + + + + ZFO file to be viewed. @@ -323,11 +376,6 @@ Filter: - - - Clear - - CorrespondenceOverview @@ -522,37 +570,6 @@ - CreateAccountFromDb - - - Create account form database file - - - - - What do you want to create the account(s) from? - - - - - Database file(s) from directory - - - - - Selected database file(s) - - - - - CreateAccountFromDbDialog - - - A new account will be created according to the name and the content of the database file. This account will operate over the selected database. Should such an account or database file already exist in Datovka then the association will fail. During the association no database file copy is created nor is the content of the database file modified. Nevertheless, we strongly advice you to back-up all important files before associating a database file. In order for the association to succeed you will need an active connection to the ISDS server. - - - - DbFlsTblModel @@ -570,7 +587,7 @@ - + unknown @@ -578,13 +595,13 @@ DbMsgsTblModel - - + + Attachments downloaded - + Processing state @@ -592,372 +609,514 @@ DlgAbout - + Portable version - + Version - + Free client for Czech eGov data boxes. - + Additional informations - + home page - + handbook - + FAQ - + Support - - - DlgChangeDirectory - - Open Directory + + + File '%1' either doesn't exist or is empty. - - - DlgChangePwd - - Enter security code: + + About Datovka - - - Enter SMS code: + + Version: - - Hide + + Copyright © - - Show + + Licence - - SMS code for account + + Credits + + + DlgChangeDirectory - - Account "%1" requires authentication via security code for connection to databox. + + Open Directory - - Security code will be sent you via Premium SMS. + + + + + + + + Change data directory for current account - - Do you want to send Premium SMS with security code into your mobile phone? + + Database files for '%1' have been successfully moved to + +'%2'. - - Enter SMS security code + + Database files for '%1' could not be moved to + +'%2'. - - SMS security code for account "%1"<br/>has been sent on your mobile phone... + + Database files for '%1' have been successfully copied to + +'%2'. - - Enter SMS security code for account + + Database files for '%1' could not be copied to + +'%2'. - - Login error + + New database files for '%1' have been successfully created in + +'%2'. - - An error occurred while preparing request for SMS with OTP security code. + + New database files for '%1' could not be created in + +'%2'. - - Please try again later or you have to use the official web interface of Datové schránky for access to your data box. + + Data for this account is currenly stored in: - - Password has been changed + + n/a - - Password has been changed successfully on the server ISDS. + + Select a new directory where data should be stored: - - Restart the application. Also don't forget to remember the new password so you will still be able to log into your data box via the web interface. + + New data directory - - Error: + + Choose - - ISDS returns: + + You cannot use the original directory as destination! - - An error occurred while password was changed. + + Action - - You have to fix the problem and try to again. + + Move data to the new directory - - Password error + + Copy data to the new directory + + + + + Start afresh in the new directory - DlgCorrespondenceOverview + DlgChangePwd - - - messages: + + Enter security code: - - Sent + + + Enter SMS code: - - Received + + Hide - - - Correspondence overview + + Show - - From date: + + SMS code for account - - To date: + + Account "%1" requires authentication via security code for connection to databox. - - Generated: + + Security code will be sent you via Premium SMS. - - Status + + Do you want to send Premium SMS with security code into your mobile phone? - - Message type + + Enter SMS security code - - Delivery time + + SMS security code for account "%1"<br/>has been sent on your mobile phone... - - Acceptance time + + Enter SMS security code for account - - - Subject + + Login error - - - Sender + + An error occurred while preparing request for SMS with OTP security code. - - Sender Address + + Please try again later or you have to use the official web interface of Datové schránky for access to your data box. + + + + + Password has been changed + + + + + Password has been changed successfully on the server ISDS. + + + + + Restart the application. Also don't forget to remember the new password so you will still be able to log into your data box via the web interface. + + + + + Error: + + + + + ISDS returns + + + + + An error occurred while password was changed. + + + + + You have to fix the problem and try to again. + + + + + Password error + + + + + DlgContacts + + + Enter sought expression + + + + + DlgCorrespondenceOverview + + + + messages: + + + + + Sent + + + + + Received + + + + + + Correspondence overview + + + + + From date: + + + + + To date: + + + + + Generated: + + + + + Status + + + + + Message type + + + + + Delivery time + + + + + Acceptance time + + + + + + Subject + + + + + + Sender - + Sender Address + + + + + Recipient - + Delivery - + Acceptance - + Recipient Address - + Our file mark - + Our reference number - + Your file mark - + Your reference number - + Overview - + Select file to save correspondence overview - + Correspondence Overview Export Error - + correspondence overview file was exported to HTML. - + correspondence overview file was exported to CSV. - + correspondence overview file was exported. - + Select directory for export of ZFO/PDF file(s) - + messages were successfully exported to ZFO/PDF. - + messages were successfully exported to ZFO. - + acceptance infos were successfully exported to ZFO. - + acceptance infos were successfully exported to PDF. - + message envelopes were successfully exported to PDF. - + Export results - + Export of correspondence overview finished with these results: - + Some errors occurred during export. - + See detail for more info... - + Files - + Correspondence overview file '%1' could not be written. @@ -965,358 +1124,470 @@ DlgCreateAccount - + Password - + Certificate - + Certificate + Password - + Password + Secure code - + Password + Secure SMS - + Update account %1 - + Enter password for account %1 - + Set certificate for account %1 - + Enter password/certificate for account %1 - - mojeID + + Open Certificate - - Open Certificate + + Certificate Files (*.p12 *.pem) + + + DlgCreateAccountFromDb - - Certificate Files (*.p12 *.pem) + + Create account from database file + + + + + What do you want to create the account(s) from? + + + + + Database files from directory + + + + + Selected database files + + + + + A new account will be created according to the name and the content of the database file. This account will operate over the selected database. Should such an account or database file already exist in Datovka then the association will fail. During the association no database file copy is created nor is the content of the database file modified. Nevertheless, we strongly advice you to back-up all important files before associating a database file. In order for the association to succeed you will need an active connection to the ISDS server. + + + + + Select directory + + + + + No database file found + + + + + No database file found in selected directory '%1'. + + + + + Select database files + + + + + Database file (*.db) + + + + + + + Create account: %1 + + + + + + + File + + + + + Account with user name '%1' and its message database already exist. New account was not created and selected database file was not associated with this account. + + + + + Account with name '%1' has been created (user name '%1'). + + + + + This database file has been set as the actual message database for this account. You'll probably have to modify the account properties in order to log in to the ISDS server correctly. DlgDsSearch - - + + All - + All types - + OVM - + Orgán veřejné moci - + PO - + Právnická osoba - + PFO - + Podnikající fyzická osoba - + FO - + Fyzická osoba - + Search in all fields - + Address - + Search in address data - + IC - + Identification number - + ID - + Box identifier - + + Enter sought expression + + + + + This is a special ID for a ISDS system data box. You can't use this ID for message delivery. Try again. + + + + Full-text data box search. Enter phrase for finding and set optional restrictions: - + Enter the ID, IČ or at least three letters from the name of the data box you look for: - - + + Your account is of type - + You have also Post Data Messages activated. This means you can only search for accounts of type OVM and accounts that have Post Data Messages delivery activated. Because of this limitation the results of your current search might not contain all otherwise matching databoxes. - + commercial messages are enabled - + This means you can only search for accounts of type OVM. The current search settings will thus probably yield no result. - + commercial messages are disabled - - + + Enter last name or last name at birth of the FO. - - + Total found - - + + It was not possible find any data box because - - + + It was not possible find any data box because an error occurred during the search process! - + Displayed - - + + Subject Name: - - - - + + + + Enter name of subject - - Name: + + Search recipient - - - Enter last name of the PFO or company name. + + Current account: - - Last Name: + + + + n/a - - - - - - Search result + + Use full-text search similar to the ISDS client portal. - - This is a special ID for system databox of Datové schránky. You can't use this ID for message delivery. Try again. + + Your account is not of type OVM (i.e. non-OVM). Sending of post data messages +from your account is activated. This means that you can only search for accounts +of the type OVM and accounts that have the the receiving of post data messages +activated. Because of this limitation the results of your current search may not +contain all otherwise matching databoxes. - - - Search error + + Note: Your search results will be limited. See tooltip for more information. - - - DlgDsSearchMojeId - - Search + + Databox type: - - Search next + + Search in fileds: - - - DlgLoginToMojeId - - Password + + Text: - - Certificate + + ID: - - Password + Secure code + + IČ: - - Login to account: %1 + + + Name: - - Open Certificate + + Postal code: - - Certificate Files (*.p12 *.pem) + + Search - - - DlgMsgSearch - - Here it is possible to search for messages according to supplied criteria. You can search for messages in selected account or in all accounts. Double clicking on a found message will change focus to the selected message in the application window. Note: You can view additional information when hovering your mouse cursor over the message ID. + + Filter: - + + + Enter last name of the PFO or company name. + + + + + Last Name: + + + + + + + + + Search result + + + + + + Search error + + + + + DlgMsgSearch + + + Here it is possible to search for messages according to supplied criteria. You can search for messages in selected account or in all accounts. Double clicking on a found message will change focus to the selected message in the application window. Note: You can view additional information when hovering your mouse cursor over the message ID. + + + + Account - + Message ID - + Subject - + Sender - + Recipient - + Delivery Year - + Message Type @@ -1356,251 +1627,380 @@ + DlgRecordsManagement + + + Records Management Settings + + + + + Service location URL. + + + + + URL: + + + + + Access token into the records management service. + + + + + Token: + + + + + Service Info + + + + + Erase + + + + + Service name: + + + + + Token name: + + + + + + + Communication Error + + + + + Received invalid response. + + + + + Received empty response. + + + + + DlgRecordsManagementStored + + + Records Management Stored Messages + + + + + Updating stored information about messages. + + + + + Downloading information about messages from account: +%1 (%2). + + + + + DlgRecordsManagementUpload + + + Upload Message into Records Management Service + + + + + Appeal + + + + + Reload + + + + + Filter: + + + + + Select the location where you want +to upload the message '%1' into. + + + + + + + + + Communication Error + + + + + + Received invalid response. + + + + + + Received empty response. + + + + DlgSendMessage - + Enter reference number: - + Warning: The permitted amount (%1) of attachments has been exceeded. - + Total size of attachments is ~%1 KB - + Warning: Total size of attachments is larger than %1 MB! - + Total size of attachments is ~%1 B - + Message contains non-OVM recipients. - + Wrong data box ID - + Wrong data box ID '%1'! - + Message was successfully sent to <i>%1 (%2)</i> as PDZ with number <i>%3</i>. - + Message was successfully sent to <i>%1 (%2)</i> as message number <i>%3</i>. - + Message was NOT sent to <i>%1 (%2)</i>. Server says: %3 - - + Message was successfully sent to all recipients. - - + Message was NOT sent to all recipients. - + Your message contains %1 non-OVM recipients therefore this message will be sent as a commercial messages (PDZ) for these recipients. - + Message contains non-OVM recipient. - + Your message contains non-OVM recipient therefore this message will be sent as a commercial message (PDZ) for this recipient. - + Your remaining credit is - + Wrong Recipient - + Recipient Search Failed - + Information about recipient data box could not be obtained. - + Do you still want to add the box '%1' into the recipient list? - + Enable commercial messages (PDZ). - + Obtained ISDS error - + It has not been possible to send a message to the ISDS server. - - + Do you want to close the Send message form? - - + + Unknown - + Data box is not active - + Recipient with data box ID '%1' does not have active data box. - + The message cannot be delivered. - + Cannot send to data box - + Cannot send message to recipient with data box ID '%1'. - + You won't be able as user '%1' to send messages into data box '%2'. - + Recipient with data box ID '%1' does not exist. - + Send message error - + An error occurred while loading attachments into message. - + An error occurred during message envelope creation. - + The message will be discarded. - - + Message sent - - + Message sending error - + Databox ID - + Enter Databox ID (7 characters): - + Do you want to send all messages? - - + + Total size of attachments is %1 B - + sending of PDZ: enabled - + remaining credit: - + sending of PDZ: disabled - + Our reference number: - + Do you want to send message? @@ -1608,57 +2008,98 @@ DlgTag - + Choose tag colour - - - + + Tag error - + Tag name is empty. - + + Tag wasn't created. - - Tag update error + + Tag with name '%1'' already exists in database. - - Tag with name '%1'' wasn't updated in the WebDatovka database. + + Tag properties - - Tag insert error + + Tag name: - - Tag with name '%1'' wasn't' created in WebDatovka database. + + Tag color: - - - Tag with name '%1'' already exists in database. + + Change + + + + + DlgTags + + + Tag manager + + + + + Available Tags + + + + + Add + + + + + Delete + + + + + Update + + + + + Assign + + + + + Remove + + + + + Assigned Tags - - - Tag wasn't created again. + + Remove all @@ -1708,252 +2149,178 @@ DlgViewZfo - + Open attachment - + Save attachment - + Save attachments - + Identification - + ID - + Subject - + Message type - + Sender - + Sender Databox ID - + Sender Address - + Recipient - + Recipient Databox ID - + Events - + Recipient Address - - + + Error parsing content - + Cannot parse the content of file '%1'. - + Cannot parse the content of message. - - + + Status - + Delivery time - + Acceptance time - + Attachments - + Signature - + Message signature - + Signing certificate - + Time stamp - DsSearch - - - Search recipient - - - - - Current account: - - - - - - - n/a - - - - - Use full-text search similar to the ISDS client portal. - - - - - Your account is not of type OVM (i.e. non-OVM). Sending of post data messages -from your account is activated. This means that you can only search for accounts -of the type OVM and accounts that have the the receiving of post data messages -activated. Because of this limitation the results of your current search may not -contain all otherwise matching databoxes. - - - - - Note: Your search results will be limited. See tooltip for more information. - - - - - Databox type: - - - - - Search in fileds: - - - - - Text: - - - - - ID: - - + ErrorEntry - - IČ: + + No error occurred - - Name: - - - - - Postal code: - - - - - Search - - - - - DsSearchMojeId - - - Search recipient + + Request was malformed - - Current account: + + Identifier is missing - - n/a + + Supplied identifier is wrong - - Keyword: + + File format is not supported - - Search + + Data are already present - - ID + + Service limit was exceeded - - Name + + Unspecified error - - Address + + Unknown error @@ -2072,998 +2439,1120 @@ - IsdsLogin + IsdsConversion - - Error when connecting to ISDS server! + + The data box is accessible. It is possible to send messages into it. It can be looked up on the Portal. - - Error during authentication! + + The data box is temporarily inaccessible (at own request). It may be made accessible again at some point in the future. - - - It was not possible to connect to your data box from account "%1". + + The data box is so far inactive. The owner of the box has to log into the web interface at first in order to activate the box. - - Authentication failed! + + The data box is permanently inaccessible. It is waiting to be deleted (but it may be made accessible again). - - - - - - - - - - - Error: + + The data box has been deleted (none the less it exists in ISDS). - - Please check your credentials and login method together with your password. + + The data box is temporarily inaccessible (because of reasons listed in law). It may be made accessible again at some point in the future. - - - It is also possible that your password has expired - in this case, you need to use the official ISDS web interface to change it. + + An error occurred while checking the status. - - Error during OTP authentication! + + System ISDS - - OTP authentication failed! + + Public authority - - Please check your credentials together with entered security/SMS code and try again. + + Legal person - - It was not possible to establish a connection within a set time. + + Self-employed person - - Time-out for connection to server expired! + + Natural person - - This is either caused by an extremely slow and/or unstable connection or by an improper set-up. + + Postal data message - - - Please check your internet connection and try again. + + Initialising postal data message - - It might be necessary to use a proxy to connect to the server. It is also possible that the ISDS server is inoperative or busy. Try again later. + + Reply postal data message - - - - - - - It was not possible to establish a connection between your computer and the ISDS server. + + Initialising postal data message - expired - - HTTPS problem occurred or redirection to server failed! + + Initialising postal data message - used - - - This is usually caused by either lack of internet connectivity or by some problem with the ISDS server. + + Message has been submitted (has been created in ISDS) - - - It is possible that the ISDS server is inoperative or busy. Try again later. + + Data message including its attachments signed with time-stamp. - - An ISDS server problem occurred or service was not found! + + Message did not pass through AV check; infected paper deleted; final status before deletion. - - The connection to server failed or a problem with the network occurred! + + Message handed into ISDS (delivery time recorded). - - This is usually caused by either lack of internet connectivity or by a firewall on the way. + + 10 days have passed since the delivery of the public message which has not been accepted by logging-in (assumption of acceptance through fiction in non-OVM DS); this state cannot occur for commercial messages. - - It might be necessary to use a proxy to connect to the server. If yes, please set it up in the proxy settings menu. + + A person authorised to read this message has logged in -- delivered message has been accepted. - - Problem with HTTPS connection! + + Message has been read (on the portal or by ESS action). - - This may be caused by a missing certificate for the SSL communication or the application cannot open an SSL socket. + + Message marked as undeliverable because the target DS has been made inaccessible. - - This may be caused by a missing SSL certificate needed for communication with the server or it was not possible to establish a secure connection with the ISDS server. + + Message content deleted, envelope including hashes has been moved into archive. - - This may be caused by an error in SOAP or the XML content for this web service is invalid. + + Message resides in data vault. - - It is also possible that some libraries (e.g. CURL, SSL) may be missing or may be incorrectly configured. + + Primary user - - HTTPS problem or security problem! + + Entrusted user - - It is also possible that the certificate has expired. + + Administrator - - SOAP problem or XML problem! + + Official - - It is also possible that the ISDS server is inoperative or busy. Try again later. + + Virtual - - - Datovka internal error! + + ??? - - It was not possible to establish a connection to the ISDS server. + + Liquidator + + + + + Receiver + + + + + Guardian + + + + + Full control + + + + + Restricted control + + + + + download and read incoming DM + + + + + download and read DM sent into own hands + + + + + create and send DM, download sent DM + + + + + retrieve DM lists, delivery and acceptance reports + + + + + search for data boxes + + + + + manage the data box + + + + + read message in data vault + + + + + erase messages from data vault + + + + + IsdsLogin + + + Error when connecting to ISDS server! + + + + + Error during authentication! + + + + + + It was not possible to connect to your data box from account "%1". + + + + + Authentication failed! + + + + + + + + + + + + + + Error: + + + + + Please check your credentials and login method together with your password. + + + + + + It is also possible that your password has expired - in this case, you need to use the official ISDS web interface to change it. + + + + + Error during OTP authentication! + + + + + OTP authentication failed! + + + + + Please check your credentials together with entered security/SMS code and try again. + + + + + It was not possible to establish a connection within a set time. + + + + + Time-out for connection to server expired! + + + + + This is either caused by an extremely slow and/or unstable connection or by an improper set-up. - - An unexpected error occurred. Please restart the application and try again. It this doesn't help then you should contact the support for this application. + + + Please check your internet connection and try again. - - - JsonLayer - - Login to mojeID failed. You must choose correct login method and enter correct login data. Try again. + + It might be necessary to use a proxy to connect to the server. It is also possible that the ISDS server is inoperative or busy. Try again later. - - Cannot open client certificate from path '%1' + + + + + + + It was not possible to establish a connection between your computer and the ISDS server. - - Certificate password + + HTTPS problem occurred or redirection to server failed! - - Enter certificate password: + + + This is usually caused by either lack of internet connectivity or by some problem with the ISDS server. - - Cannot parse client certificate from path '%1' + + + It is possible that the ISDS server is inoperative or busy. Try again later. - - - - - - - - - - - - - - - - - - - - User is not logged to mojeID + + An ISDS server problem occurred or service was not found! - - - - - - - - - - - - - - - - Reply content missing + + The connection to server failed or a problem with the network occurred! - - - LoginToMojeId - - Add a new mojeID account(s) + + This is usually caused by either lack of internet connectivity or by a firewall on the way. - - Please select login method and enter credentials for mojeID. + + It might be necessary to use a proxy to connect to the server. If yes, please set it up in the proxy settings menu. - - Login method: + + Problem with HTTPS connection! - - Select authorization method for login into your databox + + This may be caused by a missing certificate for the SSL communication or the application cannot open an SSL socket. - - Username: + + This may be caused by a missing SSL certificate needed for communication with the server or it was not possible to establish a secure connection with the ISDS server. - - Enter your username + + This may be caused by an error in SOAP or the XML content for this web service is invalid. - - Password: + + It is also possible that some libraries (e.g. CURL, SSL) may be missing or may be incorrectly configured. - - Enter your password + + HTTPS problem or security problem! - - Certificate file: + + It is also possible that the certificate has expired. - - Select a certificate + + SOAP problem or XML problem! - - Add + + It is also possible that the ISDS server is inoperative or busy. Try again later. - - Security code (OTP): + + + Datovka internal error! - - Account will be included into synchronisation -process of all accounts on the background + + It was not possible to establish a connection to the ISDS server. - - Synchronise account(s) when "Synchronise all" is activated + + An unexpected error occurred. Please restart the application and try again. It this doesn't help then you should contact the support for this application. MainWindow - + Search: - - Clear search field - - - - + Mode: offline - - + + disk - - + + memory - + Storage: - + New version of Datovka is available: - - + + New version of Datovka - - + + New version of Datovka is available. - + Current version is %1 - + New version is %1 - + Do you want to download new version? - + Current version is "%1" - + New version is "%1" - + Update your application... - + All messages - + Add new account - - + + Cannot write file '%1'. - + Synchronise all accounts with ISDS server. - + Messages on the server - + Database files for account '%1' cannot be accessed in location '%2'. - + + Uploaded to records management service + + + + All received messages - + All sent messages - - + + Select target folder to save - + Error saving of attachments - + Some attachments of message '%1' were not saved to target folder! - - + + ISDS + + + + + It was not possible to download a complete message "%1" from ISDS server. + + + + + Server + + + + Delete message %1 - - + Do you want to delete message '%1'? - + Delete this message also from server ISDS - + Warning: If you delete the message from ISDS then this message will be lost forever. - - + Delete messages - - + Do you want to delete selected messages? - + Delete these messages also from server ISDS - + received - - + + new - + sent - + Test account - + Standard account - + Account name - + User name - + Yes - + No - + unknown or without expiration - + Password expiration date - - + + Received messages - - - + + + none - - + + Sent messages - + Version - + Powered by - + Datovka: Database file present - + Database file for account '%1' already exists. - + If you want to use a new blank file then delete, rename or move the existing file so that the application can create a new empty file. - - - - - + + + + + Datovka: Problem loading database - - - - - - + + + + + + Could not load data from the database for account '%1' - + I'll try to create an empty one. - - Import of messages to account %1 finished + + + Cannot export the message '%1'. - - - Datovka - Free client for Datové schránky + + + First you must download the message before its export... - - Select target folder for export + + You can change your password now or later using the '%1' command. Your new password will be valid for 90 days. + +Change password now? - - Database file error + + This action allow to import messages from selected database files into current account. Keep in mind that this action may take a while based on number of messages in the imported database. Import progress will be displayed in the status bar. - - Split of message database for account '%1' was not successfully. Please, restart the application for loading original database. + + This action splits current account message database into several separate databases which will contain messages relevant to one year only. It is recommended for large databases in order to improve the performance. - - Database split result + + The original database file will be copied to selected directory and new database files will be created in the original location. If action finishes with success then new databases will be used instead of the original. Application restart is required. - - Enter sought expression + + Note: Keep in mind that this action may take a while based on the number of messages in the database. - - In Progress + + Database file cannot be split into original directory. - - - Mark + + Please choose another directory. - - - - - As Read + + Note: Original database file was backed up to: - - - - - As Unread + + Splitting of message database for account '%1' was not successful. Please, restart the application in order to reload the original database. - - It was not possible to download a complete message "%1" from server Datové schránky. + + Import of messages to account %1 finished - - No account synchronised. + + + Datovka - Free client for Datové schránky - - You don't have enough access rights to use the file. + + Select target folder for export - - The file either does not contain an sqlite database or the file is corrupted. + + Database file error - - Datovka: Database opening error + + + Database split result - - Create a new account. + + Enter sought expression - - Remove account + + In Progress - - Do you want to remove account + + + Mark - - Account '%1' was deleted but its message database was not deleted. + + + + + As Read - - - - Select directory + + + + + As Unread - - Database file(s) not found in selected directory. + + No account synchronised. + + + + + You don't have enough access rights to use the file. - - Select db file(s) + + The file either does not contain an sqlite database or the file is corrupted. - - Database file (*.db) + + Datovka: Database opening error - - - Database file(s) not selected. + + Create a new account. - - Account with user name '%1' and its message database already exist. New account was not created and selected database file was not associated with this account. + + Remove account - - Account with name '%1' has been created (user name '%1'). + + Do you want to remove account + + + + + Account '%1' was deleted but its message database was not deleted. + + + + + + Select directory + + + + + Database file(s) not selected. - + Verifying the ZFO file "%1" - + Server Datové schránky confirms that the message is authentic. - - + + Message was <b>successfully verified</b> against data on the server Datové schránky. - - + + This message has passed through the system of Datové schránky and has not been tampered with since. - + Server Datové schránky confirms that the message is not authentic. - - + + Message was <b>not</b> authenticated as processed by the system Datové schránky. - - + + It is either not a valid ZFO file or it was modified since it was downloaded from Datové schránky. - - - + + + Message authentication failed - - + + Authentication of message has been stopped because the connection to server Datové schránky failed! Check your internet connection. - + Server Datové schránky confirms that the message is valid. - + Server Datové schránky confirms that the message is not valid. - + Message is not valid - - - - - + + + + + Message verification failed. - + Verification failed - - - - + + + + Verification error - + Tags - - + Couldn't download message '%1'. - + The message hash is not in local database. Please download complete message from ISDS and try again. - - - - + + + + ZFO file(s) not found in selected directory. - - + + No ZFO file(s) - + Select ZFO file(s) - + ZFO file(s) not selected. - + Complete message '%1' is missing. - + Do you want to download the complete message now? - + Complete message '%1' has been downloaded. - + Complete message '%1' has not been downloaded. - + Data message - + Data messages - + Attachments of message - + Attachments of messages - + Attachment of message %1 - + Attachments of message %1 - + Message '%1' stored to temporary file '%2'. - + Message '%1' couldn't be stored to temporary file. - - + + Error opening message '%1'. - + Password required - + Account: %1 User name: %2 Certificate file: %3 @@ -3071,1073 +3560,839 @@ - + SMS code for account - - - - - - - + + + + + + + It was not possible to connect to your data box from account "%1". - + + User-assigned tags + + + + Saving attachment of message '%1' to files was not successful! - + Saving attachment of message '%1' to file was successful. - + Saving attachment of message '%1' to file was not successful! - + Attachment '%1' stored into temporary file '%2'. - + Attachment '%1' couldn't be stored into temporary file. - - It was not possible download complete message "%1" from webdatovka server. - - - - - It was not possible to download a complete message "%1" from webdatovka server. - - - - - Webdatovka: - - - - + It was not possible download received message list from server. - + It was not possible download sent message list from server. - - Server: - - - - + Message "%1" was downloaded from server. - + Warning: If you delete selected messages from ISDS then these messages will be lost forever. - - You have to be logged into the Webdatovka if you want to delete message(s). - - - - - Warning: If you delete the message from Webdatovka then this message will be lost forever. - - - - - Warning: If you delete selected messages from Webdatovka then these messages will be lost forever. - - - - - - You have to be logged into the WebDatovka if you want to download complete message. - - - - - MojeID account - - - - + Full message not present! - - You have to be logged into the WebDatovka if you want to find databox. - - - - + First you must download the complete message to continue with the action. - + Message acceptance information '%1' stored to temporary file '%2'. - + Message acceptance information '%1' couldn't be stored to temporary file. - + Invalid certificate data - + The certificate or the supplied pass-phrase are invalid. - + Please enter a path to a valid certificate and/or provide a correct key to unlock the certificate. - + Bad certificate data for account "%1". - + Datovka is currently processing some tasks. - + Do you want to abort pending actions and close Datovka? - - + + Adding new account failed - + Account could not be added because an error occurred. - + Account could not be added because account already exists. - - + + Checking time stamps in account '%1'... - + Time stamp expiration check results - - Import of mesages from database - - - - - This action allow to import messages from selected database files into current account. Keep in mind that this action may takes a few minutes based on number of messages in the imported database. Import progress will be displayed in the status bar. - - - - - - + + + Do you want to continue? - + Select database file(s) - + DB file (*.db) - + Messages import result - + Import of messages into account '%1' finished with result: - + Imported messages: %1 - + Non-imported messages: %1 - + Database split - - This action split current account message database into several new databases which will contain messages relevant by year only. It is recommended for large database because the performance of application will be better. - - - - - Original database file will copy to selected directory and new database files will created in the same location. If action finished with success, new databases will be used instead of original. Restart of application is required. - - - - - Note: Keep in mind that this action may takes a few minutes based on number of messages in the database. - - - - + Split of message database finished with error - + Vacuum cannot be performed on databases in memory. - + Database operation error - + Database clean-up cannot be performed on database in memory. - + Cannot call VACUUM on database in memory. - + Clean message database - + Performs a message database clean-up for the selected account. This action will block the entire application. The action may take several minutes to be completed. Furthermore, it requires more than %1 of free disk space to successfully proceed. - + Performing database clean-up. - + Database clean-up finished. - + Database clean-up successful - + The database clean-up has finished successfully. - + Database clean-up failure - + The database clean-up failed with error message: %1 - - You have to be logged into the WebDatovka if you want to modify tags. - - - - - Add account(s) error - - - - - There aren't any Webdatovka accounts for this mojeID identity. - - - - - - You are login into wrong mojeID identity. - - - - - Please enter correct mojeID login for account '%1'. - - - - - New mojeID identity has some account(s). - - - - - Do you want to add account(s) for this mojeID identity to Datovka? - - - - - Some account(s) were removed from Webdatovka for this mojeID identity. - - - - - Do you want to also remove these accounts from Datovka? - - - - - This action is not supported for MojeID account '%1' - - - - - Login problem - - - - - + A connection error occurred or the message has already been deleted from the server. - + A connection error occurred. - + Message from '%1' (%2) has been successfully sent to '%3' (%4). - + Error while sending message from '%1' (%2) to '%3' (%4). - + No ZFO files to import. - + There is no account to import of ZFO files into. - + The log-in method used in account "%1" is not implemented. - + Account "%1" requires authentication via OTP<br/>security code for connection to data box. - + Account "%1" requires authentication via security code for connection to data box. - + Security code will be sent to you via a Premium SMS. - + Do you want to send a Premium SMS with a security code into your mobile phone? - - Select directory for new databases - - - - - Database file cannot split into same directory. - - - - - Please, you must choose another directory. + + Select directory for new databases - + Split of message database finished - + Congratulation: message database for account '%1' was split successfully. Please, restart the application for loading of new databases. - - Note: Original database file was backup to: - - - - + Time stamp expiration check in account '%1' finished with result: - + Loading of ZFO file(s) failed! - + Time stamp expiration check of ZFO files finished with result: - + Total of ZFO files: %1 - + ZFO files with time stamp expiring within %1 days: %2 - + Unchecked ZFO files: %1 - - + + Total of messages in database: %1 - + Messages with time stamp expiring within %1 days: %2 - + Unchecked messages: %1 - + See details for more info... - + Do you want to export the expiring messages to ZFO? - - + + Time stamp of message %1 expires within specified interval. - - + + Time stamp of message %1 is not present. - + New account error - + Account - + was not created! - + + Password expiration - + According to the last available information, your password for account '%1' (login '%2') expired %3 days ago (%4). - + You have to change your password from the ISDS web interface. Your new password will be valid for 90 days. - + According to the last available information, your password for account '%1' (login '%2') will expire in %3 days (%4). - - You can change your password now, or later using the 'Change password' command. Your new password will be valid for 90 days. - -Change password now? - - - - - + + Change password of account "%1". - - + + Portable version - + Database access error - + The file cannot be accessed or is corrupted. Please fix the access privileges or remove or rename the file so that the application can create a new empty file. - + Create a backup copy of the affected file. This will help when trying to perform data recovery. - + In general, it is recommended to create backup copies of the database files to prevent data loss. - - - - + + + + As Unsettled - - - - + + + + As in Progress - - - - + + + + As Settled - + Download message list error - - ISDS: - - - - + Account and user information could not be acquired. - + User information - + Databox information - + Database is stored in memory. Data will be lost on application exit. - - + + Local database file location - + Change properties of account "%1". - + Account "%1" was updated. - + Account was moved up. - + Account was moved down. - + Change data dierctory of account "%1". - - - - - - - Change data directory for current account - - - - + Find databoxes from account "%1". - + Enter OTP security code - + Enter OTP security code for account - + It was not possible to get user info and databox info from ISDS server for account - + Connection to ISDS or user authentication failed! - + Please check your internet connection and try again or it is possible that your password (certificate) has expired - in this case, you need to use the official web interface of Datové schránky to change it. - - + + Add ZFO file - - - + + + ZFO file (*.zfo) - + Message is authentic - + Datovka - + Message is not authentic - + It was not possible download complete message "%1" from ISDS server. - - + Download message error - + Message "%1" was deleted from local database. - + Message "%1" was deleted from ISDS and local database. - + Message "%1" was deleted only from ISDS. - + Message "%1" was deleted only from local database. - + Message "%1" was not deleted. - + Create and send a message. - + Delete also message database from storage - + Warning: If you delete the message database then all locally accessible messages that are not stored on the ISDS server will be lost. - + Account '%1' was deleted together with message database file. - + Account '%1' was deleted. - - This database file has been set as actual message database for this account. Maybe you have to change account properties for correct login to the server Datové schránky. - - - - - - - Create account: %1 - - - - + The existing database files %1 in '%2' are going to be used. - + Database files are missing in '%1'. - + Some databases of %1 in '%2' are not a file. - + Some databases of '%1' in '%2' cannot be accessed. - + Some databases of %1 in '%2' cannot be used. - + Conflicting databases %1 in '%2' cannot be used. - + Please remove the conflicting files. - + Database files in '%1' cannot be created or are corrupted. - - Database files for '%1' have been successfully moved to - -'%2'. - - - - - Database files for '%1' could not be moved to - -'%2'. - - - - - Database files for '%1' have been successfully copied to - -'%2'. - - - - - Database files for '%1' could not be copied to - -'%2'. - - - - - New database files for '%1' have been successfully created in - -'%2'. - - - - - New database files for '%1' could not be created in - -'%2'. - - - - - - + + + Message authentication failed. - + Authentication of message has been stopped because the message file has wrong format! - - - + + + An undefined error occurred! Try again. - + Message is valid - + The message hash cannot be verified because an internal error occurred! Try again. - - - + + + + Message export error! - - + + Datovka - Export error! - + Welcome... - + Storage: disk | disk - - - Cannot export the message - - - - - - First you must download message before its export... - - - - - + Mode: online - - - File - + Message - + Tools - + Help - + toolBar - + Sync all accounts - + Download complete message, including attachments and verify its signature - + Open acceptance info externally - + Pass the acceptance information of the selected message to an external application - + Export acceptance info as ZFO - + Export the acceptance information of the selected message as ZFO file - + Export acceptance info as PDF - + Export the acceptance information of the selected message as PDF file - + Open attachment in an associated application - + Signature details - - + + Remove account @@ -4155,462 +4410,468 @@ - + Unsettled - + Settled - + Shift+F5 - + Add new data box account - - + + Proxy settings - + Preferences - + Preferences of Datovka - + Quit - + Quit the application - + Ctrl+Q - + F5 - + Create message - + Ctrl+N - + Mark all as read - + Mark all messages as read - + Change password - + Sets a new password to the selected account on the ISDS server - + Account properties - + Manage account properties - + Move account up - + Move selectet account one position up - + Move account down - + Move selectet account one position down - + Change data directory - + Change the directory where data are being stored for the selected account - + About Datovka - + About Datovka application - + Find Data Box - + Find data box - + Authenticate message file - + Verify message authenticity - + View message from ZFO file - + View content of a ZFO file - + Export correspondence overview - + Create a correspondence overview - + Download signed message - + Reply to the selected message - + Display details about the signature - + Deletes message from local database and/or from ISDS server - + Export the selected message as ZFO file - + Pass the selected message to an external application - + Export the envelope of the selected message as PDF file - + Export envelope PDF with attachments - + Export the envelope to a PDF file together with message attachments - + Save selected attachments to files - + Saves all message attachments - + Import messages from ZFO files - + Import a message from ZFO file into the database - + Use the selected message as a template - + Search message - + Check whether the message time stamp is not expired or expiring - + Homepage - + Open the home page of the application - + + Import messages from database - + Import messages into database from an external database file - + Split database by years - + Messages are going to be stored into separate database files according to years - + E-mail with ZFOs - + Creates an e-mail containing ZFOs of selected messages - + E-mail with all attachments - + Creates an e-mail containing all attachments of selected messages - + E-mail with selected attachments - + Creates an e-mail containing selected attachments - - + + Edit tags - + Vacuum message database - + This may reduce the database file size and optimise the access speed - - + + Forward message - - Add mojeID account + + Records management settings + + + + + Send to records management - - Add new mojeID account + + Update records management information - + Create and send a new message - + Reply to message - + Ctrl+R - + Authenticate message - + Use message as template - + Advanced searching in message envelopes - + Ctrl+Shift+F - + Time stamp expiration check - + Delete message - + Data box - - + + Create account from database - - + + User manual - + Synchronize all accounts at once - + Sync account - + Synchronize selected account - + Verify the selected message - + Export message as ZFO - + Open message externally - + Export message envelope as PDF - + Open attachment - + Save attachment - + Save all attachments @@ -5211,7 +5472,7 @@ - The HTTPS protocol is used when accessing the Databox server while HTTP is used to download the certificate revocation list and information about new Datovka versions. + The HTTPS protocol is used when accessing the Databox server while HTTP is used to download the certificate revocation list and information about new Datovka versions. @@ -5252,708 +5513,386 @@ - Enter your proxy hostname - - - - - - Port: - - - - - - Enter port - - - - - Show HTTPS proxy authentication - - - - - Show HTTPS proxy authentication. - - - - - - Username: - - - - - - Enter your username - - - - - - Password: - - - - - - Enter your password - - - - - HTTP proxy - - - - - - Show HTTP proxy authentication. - - - - - QObject - - - Postal data message - - - - - Initializing postal data message - - - - - Reply postal data message - - - - - Initializing postal data message - expired - - - - - Initializing postal data message - used - - - - - Primary user - - - - - Entrusted user - - - - - Administrator - - - - - Official - - - - - Virtual - - - - - File '%1' does not contain a valid database filename. - - - - - File '%1' does not contain a valid username in the database filename. - - - - - File '%1' does not contain valid year in the database filename. - - - - - - File '%1' does not contain valid database filename. - - - - - File '%1' does not contain a valid account type flag or filename has wrong format. - - - - - File '%1' does not contain a valid message database or filename has wrong format. - - - - - Data message including its attachments signed with time-stamp. - - - - - Message did not pass through AV check; infected paper deleted; final status before deletion. - - - - - Message handed into ISDS (delivery time recorded). - - - - - 10 days have passed since the delivery of the public message which has not been accepted by logging-in (assumption of acceptance through fiction in non-OVM DS); this state cannot occur for commercial messages. - - - - - Message has been read (on the portal or by ESS action). - - - - - Message has been submitted (has been created in ISDS) - - - - - A person authorised to read this message has logged in -- delivered message has been accepted. - - - - - Message marked as undeliverable because the target DS has been made inaccessible. - - - - - Message content deleted, envelope including hashes has been moved into archive. - - - - - Message resides in data vault. - - - - - Full control - - - - - Restricted control - - - - - download and read incoming DM - - - - - download and read DM sent into own hands - - - - - create and send DM, download sent DM + Enter your proxy hostname - - retrieve DM lists, delivery and acceptance reports + + + Port: - - search for data boxes + + + Enter port - - manage the data box + + Show HTTPS proxy authentication - - read message in data vault + + Show HTTPS proxy authentication. - - erase messages from data vault + + + Username: - - System ISDS + + + Enter your username - - Public authority + + + Password: - - Legal person + + + Enter your password - - Self-employed person + + HTTP proxy - - Natural person + + + Show HTTP proxy authentication. + + + QObject - - The data box is accessible. It is possible to send messages into it. It can be looked up on the Portal. + + File '%1' does not contain a valid database filename. - - The data box is temporarily inaccessible (at own request). It may be made accessible again at some point in the future. + + File '%1' does not contain a valid username in the database filename. - - The data box is so far inactive. The owner of the box has to log into the web interface at first in order to activate the box. + + File '%1' does not contain valid year in the database filename. - - The data box is permanently inaccessible. It is waiting to be deleted (but it may be made accessible again). + + + File '%1' does not contain valid database filename. - - The data box has been deleted (none the less it exists in ISDS). + + File '%1' does not contain a valid account type flag or filename has wrong format. - - An error occurred while checking the status. + + File '%1' does not contain a valid message database or filename has wrong format. - + File name - + Data box ID - + Data box type - - + + - - + + Given name - - + + Middle name - - + + Surname - - + + Surname at birth - - + + Company name - - + + Date of birth - + City of birth - + County of birth - + State of birth - - + + City of residence - - + + Street of residence - - + + Number in street - - + + Number in municipality - - - + + + Zip code - - + + State of residence - + Nationality - + Databox state - + Effective OVM - + Open addressing - + User type - + Permissions - + City - + Street - + State - + ID - - - - + + + + Sender - + Sender address - - - - + + + + Recipient - + Recipient address - - - + + + To hands - + Section - + Delivery time - + Acceptance time - + Your reference number - + Our reference number - + Your file mark - + Our file mark - + Law - + Year - + Paragraph - + Letter - + Personal delivery - + Acceptance through fiction enabled - - + + Status - + Attachment size - + Mime type - + Read locally - - Data box application - - - - - Use <conf-subdir> subdirectory for configuration. - - - - - conf-subdir - - - - - On start load <conf> file. - - - - - - conf - - - - - On stop save <conf> file. - - - - - Log messages to <file>. - - - - - file - - - - - Set verbosity of logged messages to <level>. Default is - - - - - - level - - - - - Set debugging verbosity to <level>. Default is - - - - - Service: connect to isds and login into databox. - - - - - - - - - string-of-parameters - - - - - Service: download list of received/sent messages from ISDS. - - - - - Service: create and send a new message to ISDS. - - - - - Service: download complete message with signature and time stamp of MV. - - - - - Service: download acceptance info of message with signature and time stamp of MV. - - - - - Service: get information about user (role, privileges, ...). - - - - - Service: get information about owner and its databox. - - - - - Service: get list of messages where attachment missing (local database only). - - - - - Service: find a databox via several parameters. - - - - - ZFO file to be viewed. - - - - Application is loading... - - + + Message ID: @@ -5961,285 +5900,285 @@ - - - - + + + + Name - - + + General Information - - - - + + + + Subject - - + + paragraph - - + + letter - - + + Delegation - - - - - - - - - - + + + + + + + + + + Not specified - - + + Our ref.number - - + + Our doc.id - - + + Your ref.number - - + + Your doc.id - - - - + + + + yes - - - - + + + + no - - + + Personal Delivery - + List of attachments - + Advice of Acceptance - + Delivery/Acceptance Information - - + + Delivery - + Download the complete message in order to verify its time stamp. - - + + Prohibit Acceptance through Fiction - + Acceptance - - + + Events - + Sender Databox ID - + Recipient Databox ID - + Time - + Envelope - - + + Databox ID - + Databox Type - - - - + + + + Attachments - + Identification - + Message ID - + Message type - + Databox type - + Sender Address - + Message author - + Recipient Address - + (downloaded and ready) - + not downloaded yet, ~ - + KB; use 'Download' to get them. - + (not available) - + Signature - - - + + + Message signature - - + + Not present - + Download the complete message in order to verify its signature. - + Time stamp - - - - - - + + + + + + Invalid - - + + Message signature and content do not correspond! @@ -6248,30 +6187,30 @@ - - - - - - + + + + + + Valid - - + + Certificate revocation check is turned off! - + Signing certificate - + Depends on libraries: @@ -6283,13 +6222,13 @@ - + No - + Yes @@ -6398,7 +6337,7 @@ - + Created using Datovka @@ -6408,67 +6347,67 @@ - + Message '%1' already exists in the local database, account '%2'. - - + + Couldn't read data from file for authentication on the ISDS server. - - + + Error contacting ISDS server. - + Message '%1' could not be authenticated by ISDS server. - - + + File has not been imported because an error was detected during insertion process. - + Imported message '%1', account '%2'. - + This file (acceptance info) has not been inserted into database because there isn't any related message with id '%1' in the databases. - + Acceptance info for message '%1' already exists in the local database, account '%2'. - + Acceptance info for message '%1' could not be authenticated by ISDS server. - + Imported acceptance info for message '%1', account '%2'. - - - + + + Wrong ZFO format. This file does not contain correct data for import. - + The selection does not contain any valid ZFO file. @@ -6733,30 +6672,60 @@ - + Tags - + Message '%1' does not contain data necessary for ZFO export. - + Message '%1' does not contain acceptance info data necessary for ZFO export. - + Message '%1' does not contain acceptance info data necessary for PDF export. - + Message '%1' does not contain message envelope data necessary for PDF export. + + + Message '%1' could not be uploaded. + + + + + Received error + + + + + File Upload Error + + + + + Successful File Upload + + + + + Message '%1' was successfully uploaded into the records management service. + + + + + It can be now found in the records management service in these locations: + + SendMessage @@ -6771,6 +6740,11 @@ + + Sender: + + + Subject: @@ -6961,11 +6935,6 @@ - - Sender: - - - Find and add a recipient from Datové schránky server @@ -7078,81 +7047,18 @@ - TagDialog - - - Tag properties - - - - - Tag name: - - - - - Tag color: - - - - - Change - - - - - TagsDialog - - - Tag manager - - - - - Tag operations - - - - - Add - - - - - Update - - - - - Delete - - - - - Tag assignment - - - - - Assign - - - - - Remove - - + TagsModel - - Remove all + + Tags - TagsModel + UploadHierarchyModel - - Tags + + Records Management Hierarchy diff -Nru datovka-4.8.3/notes/libdepends.win datovka-4.9.3/notes/libdepends.win --- datovka-4.8.3/notes/libdepends.win 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/notes/libdepends.win 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -Folder "dlls" must contains these files: -======================================== -locale\qtbase_cs.qm copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\translations\ -platforms\qwindows.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\plugins\platforms\ -sqldrivers\qsqlite.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\plugins\sqldrivers\ -icudt53.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -icuin53.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -icuuc53.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -libasprintf-0.dll -libcurl-4.dll -libeay32.dll -libexpat-1.dll -libgcc_s_dw2-1.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -libgcc_s_sjlj-1.dll -libgettextlib-0-19-4.dll -libgettextpo-0.dll -libgettextsrc-0-19-4.dll -libcharset-1.dll -libiconv-2.dll -libintl-8.dll -libisds-5.dll -libltdl-7.dll -libstdc++-6.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -libwinpthread-1.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -libxml2-2.dll -Qt5Core.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -Qt5Gui.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -Qt5Network.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -Qt5PrintSupport.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -Qt5Sql.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -Qt5Widgets.dll copy from: c:\Qt\{Qtversion}\mingw{Mingwversion}\bin\ -ssleay32.dll -zlib1.dll diff -Nru datovka-4.8.3/pri/check_qt_version.pri datovka-4.9.3/pri/check_qt_version.pri --- datovka-4.8.3/pri/check_qt_version.pri 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/pri/check_qt_version.pri 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,33 @@ + +defineTest(sufficientQtVersion) { + # Required Qt versions + required_major = $$1 + required_minor = $$2 + advised_ninor = $$3 + advised_patch = $$4 + + lessThan(QT_MAJOR_VERSION, $${required_major}) { + error(Qt version $${required_major}.$${required_minor} is required.) + return(false) + } + + isEqual(QT_MAJOR_VERSION, $${required_major}) { + lessThan(QT_MINOR_VERSION, $${required_minor}) { + error(Qt version $${required_major}.$${required_minor} is required.) + return(false) + } + + lessThan(QT_MINOR_VERSION, $${advised_ninor}) { + warning(Qt version at least $${required_major}.$${advised_ninor}.$${advised_patch} is suggested.) + } else { + isEqual(QT_MINOR_VERSION, $${advised_ninor}) { + lessThan(QT_PATCH_VERSION, $${advised_patch}) { + warning(Qt version at least $${required_major}.$${advised_ninor}.$${advised_patch} is suggested.) + } + } + } + } else { + warning(The current Qt version $${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION} may not work.) + } + return(true) +} diff -Nru datovka-4.8.3/pri/version.pri datovka-4.9.3/pri/version.pri --- datovka-4.8.3/pri/version.pri 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/pri/version.pri 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,3 @@ + +# VERSION must contain only three dot-separated numbers because of OS X deployment. +VERSION = 4.9.3 diff -Nru datovka-4.8.3/README datovka-4.9.3/README --- datovka-4.8.3/README 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/README 2017-09-06 11:49:23.000000000 +0000 @@ -1,15 +1,14 @@ Important --------- -The application is still in its development! We know about some bugs but most -likely there are even more. - -If you have been using the previous Python-based datovka application then -back-up your critical data before using this application! - The application is provided without any warranty. -For a list of known issues visit the following page: -https://gitlab.labs.nic.cz/labs/qdatovka/issues +List of known bugs and issues can be found here: +https://gitlab.labs.nic.cz/datovka/datovka/issues +If you encounter a problem then please send an email to +datove-schranky@labs.nic.cz or use the aforementioned site to let us know. -If you encounter a problem please use the aforementioned site to let us know. +If you have been using the Python-based Datovka application (i.e. version 3 and +earlier versions) then back up your critical data before using this application! +An attempt to execute Datovka 3 after you've run Datovka 4 will most likely +lead to data corruption and loss of stored data. Binary files /tmp/tmpe3CEIf/dc8GgEGq5K/datovka-4.8.3/res/icons/3party/briefcase_grey_16.png and /tmp/tmpe3CEIf/yNYspGPMCd/datovka-4.9.3/res/icons/3party/briefcase_grey_16.png differ Binary files /tmp/tmpe3CEIf/dc8GgEGq5K/datovka-4.8.3/res/icons/3party/briefcase_grey_32.png and /tmp/tmpe3CEIf/yNYspGPMCd/datovka-4.9.3/res/icons/3party/briefcase_grey_32.png differ Binary files /tmp/tmpe3CEIf/dc8GgEGq5K/datovka-4.8.3/res/mojeid2.png and /tmp/tmpe3CEIf/yNYspGPMCd/datovka-4.9.3/res/mojeid2.png differ Binary files /tmp/tmpe3CEIf/dc8GgEGq5K/datovka-4.8.3/res/mojeid.png and /tmp/tmpe3CEIf/yNYspGPMCd/datovka-4.9.3/res/mojeid.png differ diff -Nru datovka-4.8.3/res/resources.qrc datovka-4.9.3/res/resources.qrc --- datovka-4.8.3/res/resources.qrc 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/res/resources.qrc 2017-09-06 11:49:23.000000000 +0000 @@ -24,6 +24,7 @@ icons/3party/block_16.png icons/3party/bookmark_16.png icons/3party/briefcase_16.png + icons/3party/briefcase_grey_16.png icons/3party/bubble_16.png icons/3party/buy_16.png icons/3party/calendar_16.png @@ -155,13 +156,12 @@ icons/3party/buy_32.png icons/3party/bubble_32.png icons/3party/briefcase_32.png + icons/3party/briefcase_grey_32.png icons/3party/bookmark_32.png icons/3party/block_32.png icons/3party/address_32.png datovka.png splash/datovka-splash.png - mojeid.png - mojeid2.png dschranka.png diff -Nru datovka-4.8.3/scripts/build_osx_dmgs.sh datovka-4.9.3/scripts/build_osx_dmgs.sh --- datovka-4.8.3/scripts/build_osx_dmgs.sh 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/scripts/build_osx_dmgs.sh 2017-09-06 11:49:23.000000000 +0000 @@ -94,7 +94,7 @@ exit 1 fi -PKG_VER=$(cat datovka.pro | grep '^VERSION\ =\ ' | sed -e 's/VERSION\ =\ //g') +PKG_VER=$(cat pri/version.pri | grep '^VERSION\ =\ ' | sed -e 's/VERSION\ =\ //g') APP="datovka.app" diff -Nru datovka-4.8.3/scripts/build-win-all.bat datovka-4.9.3/scripts/build-win-all.bat --- datovka-4.8.3/scripts/build-win-all.bat 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/scripts/build-win-all.bat 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,28 @@ +@echo OFF + +:: =========================================================================== +:: Datovka build script +:: The script builds Datovka binary and creates installation package (*.exe) +:: and archive (*.zip) with all dependencies. +:: CZ.NIC, z.s.p.o. 2017 +:: =========================================================================== + +@echo ------------------------------------------------------------------------ +@echo This batch creates Datovka installation packages (*.exe) for Windows +@echo and Portable Datovka package (*.zip) for Windows. +@echo NOTE: For more info see build-win-install-package.bat script +@echo and build-win-portable-package.bat and set required paths and variables. +@echo ------------------------------------------------------------------------ +@echo. +pause +cd .. +if exist packages ( + rmdir /S /Q packages +) +cd scripts +:: Run Datovka installation build script with parameter "nopause" +call build-win-install-package.bat nopause +cd scripts +:: Run Portable Datovka build script with parameter "nopause" +call build-win-portable-package.bat nopause +cd scripts \ No newline at end of file diff -Nru datovka-4.8.3/scripts/build-win-install-package.bat datovka-4.9.3/scripts/build-win-install-package.bat --- datovka-4.8.3/scripts/build-win-install-package.bat 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/scripts/build-win-install-package.bat 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,140 @@ +@echo OFF + +:: =========================================================================== +:: Datovka build script +:: The script builds Datovka binary and creates installation package (*.exe) +:: and archive (*.zip) with all dependencies. +:: CZ.NIC, z.s.p.o. 2017 +:: =========================================================================== + +:: --------------------------------------------------------------------------- +:: How to use it? +:: --------------------------------------------------------------------------- +:: First, install Qt, NSIS and 7-ZIP tools on you computer. +:: NSIS must include plugins: ReplaceInFile.nsh, StrRep.nsh in \nsis\nsis-libs\ +:: Set path to Qt, Qt compiler executables to Windows Environment Variables (section PATH). +:: See https://www.computerhope.com/issues/ch000549.htm for exmaple. +:: Set to PATH following paths (5.9.1 replace for your version of Qt): +:: "C:\Qt\5.9.1\mingw53_32\bin\" and "C:\Qt\Tools\mingw530_32\bin\" +:: Set your path to NSIS and 7ZIP executables into variables below: +set NSISPATH="C:\Program Files (x86)\NSIS\makensis.exe" +set ZIPPATH="C:\Program Files (x86)\7-Zip\7z.exe" +:: You must have built libisds, openssl and other dependencies in the folder "mingw32built" +:: Then you can run this script. +:: --------------------------------------------------------------------------- + +:: Obtain current version from datovka.pro +cd .. +findstr /C:"VERSION =" pri\version.pri > version.txt +set "string=var1;var2;var3;" +for /f "tokens=1,2,3 delims= " %%i in (version.txt) do set "variable1=%%i" &set "variable2=%%j" &set "VERSION=%%k" +endlocal +del version.txt + +:: Define package name, User can change it if needed +set DATOVKAZIP="datovka-%VERSION%-windows.zip" + +@echo ------------------------------------------------------------------------- +@echo This batch creates Datovka installation package for Windows in several steps: +@echo 1) Build Datovka binary (datovka.exe) with QT tool (requires Qt) +@echo 2) Create application bundle with dependencies to "packages" folder +@echo 3) Create installation package (*.exe) to "packages" folder (requires NSIS tool) +@echo 4) Create ZIP package to "packages" folder (requires 7-ZIP tool) +@echo ------------------------------------------------------------------------- +@echo WARNING: +@echo You must set path to Qt, Qt compiler executables to Windows Environment +@echo Variables (section PATH) otherwise the script will not run correctly. +@echo Add to Windows PATH following paths (replace 5.9.1 for your Qt version): +@echo "C:\Qt\5.9.1\mingw53_32\bin\" +@echo "C:\Qt\Tools\mingw530_32\bin\" +@echo ------------------------------------------------------------------------- +@echo Current path to NSIS: %NSISPATH% +@echo Current path to 7-ZIP: %ZIPPATH% +@echo NOTE: If paths to NSIS and 7-ZIP are wrong, you must set correct paths +@echo in the script before running. +@echo ------------------------------------------------------------------------- +@echo Datovka version to build: %VERSION% +@echo ------------------------------------------------------------------------- +@echo. + +if NOT "%1" == "nopause" ( + pause + if exist packages ( + rmdir /S /Q packages + ) +) + +:: Datovka installation version +@echo. +@echo ---------------------------------------------------- +@echo Build Datovka binary and CLI binary (v%VERSION%) ... +@echo ---------------------------------------------------- +mingw32-make.exe clean +lupdate datovka.pro +lrelease datovka.pro +qmake.exe datovka.pro -r -spec win32-g++ +mingw32-make.exe -j 4 +mingw32-make.exe clean +qmake.exe datovka-cli.pro.noauto -r -spec win32-g++ +mingw32-make.exe -j 4 +mingw32-make.exe clean +@echo Build done. +@echo. +@echo -------------------------------------------------------------- +@echo Create application bundle and copy all files and libraries ... +@echo -------------------------------------------------------------- +:: Create app packege folder +set DATOVKAPATH=packages\datovka-%VERSION% +mkdir %DATOVKAPATH% +mkdir "%DATOVKAPATH%\locale" +:: Copy all required app files and libraries +copy "release\datovka.exe" %DATOVKAPATH% +copy "release\datovka-cli.exe" %DATOVKAPATH% +copy "AUTHORS" %DATOVKAPATH% +copy "copyING" %DATOVKAPATH% +copy "Changelog" %DATOVKAPATH% +copy "scripts\datovka-log.bat" %DATOVKAPATH% +copy "locale\datovka_cs.qm" "%DATOVKAPATH%\locale" +for /R "mingw32built\bin\" %%x in (*.dll) do copy "%%x" %DATOVKAPATH% /Y +windeployqt --release "%DATOVKAPATH%\datovka.exe" +copy "%DATOVKAPATH%\translations\qt_cs.qm" "%DATOVKAPATH%\locale\qtbase_cs.qm" +rmdir /S /Q "%DATOVKAPATH%\translations" +@echo Bundle done. +@echo. +@echo -------------------------------------------------- +@echo Create executable installation package (*.exe) ... +@echo -------------------------------------------------- +:: Replace version string in the NSIS script +set SEARCHTEXT="VERSIONXXX" +set file="nsis\datovka-install\datovka-install.nsi" +copy nsis\datovka-install\datovka-install.template %file% +set VERSIONNSIS="%VERSION%" +SETLOCAL ENABLEEXTENSIONS +SETLOCAL DISABLEDELAYEDEXPANSION +if "%SEARCHTEXT%"=="" findstr "^::" "%~f0"&GOTO:EOF +for /f "tokens=1,* delims=]" %%A in ('"type %file%|find /n /v """') do ( + set "line=%%B" + if defined line ( + call set "line=echo.%%line:%SEARCHTEXT%=%VERSIONNSIS%%%" + for /f "delims=" %%X in ('"echo."%%line%%""') do %%~X >> %file%_new + ) else echo. >> %file%_new +) +move /Y %file%_new %file% > nul +@echo Replace %SEARCHTEXT% to %VERSIONNSIS% in the NSIS script +@echo Run Datovka NSIS script and create Datovka install package (*.exe) ... +start /wait /Min "Build Datovka installer" %NSISPATH% %file% +del %file% +@echo Install package done. +@echo. +@echo ----------------------------------------------- +@echo Run 7-ZIP and create ZIP archive of Datovka ... +@echo ----------------------------------------------- +cd packages +start /wait /Min "Create Datovka ZIP archive" %ZIPPATH% a -tzip %DATOVKAZIP% datovka-%VERSION% +cd .. +@echo ZIP archive done. +rmdir /S /Q release +rmdir /S /Q debug +if NOT "%1" == "nopause" ( + cd packages +) \ No newline at end of file diff -Nru datovka-4.8.3/scripts/build-win-portable-package.bat datovka-4.9.3/scripts/build-win-portable-package.bat --- datovka-4.8.3/scripts/build-win-portable-package.bat 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/scripts/build-win-portable-package.bat 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,112 @@ +@echo OFF + +:: =========================================================================== +:: Datovka build script +:: The script builds Portable Datovka binary and creates and archive (*.zip) +:: with all dependencies. +:: CZ.NIC, z.s.p.o. 2017 +:: =========================================================================== + +:: --------------------------------------------------------------------------- +:: How to use it? +:: --------------------------------------------------------------------------- +:: First, install Qt and 7-ZIP tools on you computer. +:: Set path to Qt, Qt compiler executables to Windows Environment Variables (section PATH). +:: See https://www.computerhope.com/issues/ch000549.htm for exmaple. +:: Set to PATH following paths (5.9.1 replace for your version of Qt): +:: "C:\Qt\5.9.1\mingw53_32\bin\" and "C:\Qt\Tools\mingw530_32\bin\" +:: Set your path to 7ZIP executables into variables below: +set ZIPPATH="C:\Program Files (x86)\7-Zip\7z.exe" +:: You must have built libisds, openssl and other dependencies in the folder "mingw32built" +:: Then you can run this script. +:: --------------------------------------------------------------------------- + +:: Obtain current version from datovka.pro +cd .. +findstr /C:"VERSION =" pri\version.pri > version.txt +set "string=var1;var2;var3;" +for /f "tokens=1,2,3 delims= " %%i in (version.txt) do set "variable1=%%i" &set "variable2=%%j" &set "VERSION=%%k" +endlocal +del version.txt + +:: Define package name, User can change it if needed +set DATOVKAPZIP="datovka-portable-%VERSION%-windows.zip" + +@echo ------------------------------------------------------------------------- +@echo This batch creates portable Datovka package for Windows in several steps: +@echo 1) Build Portable Datovka binary (datovka.exe) with QT tool (requires Qt) +@echo 2) Create application bundle with dependencies to "packages" folder +@echo 3) Create ZIP package to "packages" folder (requires 7-ZIP tool) +@echo ------------------------------------------------------------------------- +@echo WARNING: +@echo You must set path to Qt, Qt compiler executables to Windows Environment +@echo Variables (section PATH) otherwise the script will not run correctly. +@echo Add to Windows PATH following paths (replace 5.9.1 for your Qt version): +@echo "C:\Qt\5.9.1\mingw53_32\bin\" +@echo "C:\Qt\Tools\mingw530_32\bin\" +@echo ------------------------------------------------------------------------- +@echo Current path to 7-ZIP: %ZIPPATH% +@echo NOTE: If path to 7-ZIP is wrong, you must set correct path in the script +@echo before running. +@echo ------------------------------------------------------------------------- +@echo Portable Datovka version to build: %VERSION% +@echo ------------------------------------------------------------------------- +@echo. + +if NOT "%1" == "nopause" ( + pause + if exist packages ( + rmdir /S /Q packages + ) +) + +:: Datovka portable version +@echo. +@echo ------------------------------------------------------------- +@echo Build Portable Datovka binary and CLI binary (v%VERSION%) ... +@echo ------------------------------------------------------------- +mingw32-make.exe clean +lupdate datovka.pro +lrelease datovka.pro +qmake.exe datovka.pro -r -spec win32-g++ PORTABLE_APPLICATION=1 +mingw32-make.exe -j 4 +mingw32-make.exe clean +qmake.exe datovka-cli.pro.noauto -r -spec win32-g++ PORTABLE_APPLICATION=1 +mingw32-make.exe -j 4 +mingw32-make.exe clean +@echo Build done. +@echo. +@echo -------------------------------------------------------------- +@echo Create application bundle and copy all files and libraries ... +@echo -------------------------------------------------------------- +:: Create app packege folder +set DATOVKAPORTPATH=packages\datovka-%VERSION%-portable +mkdir %DATOVKAPORTPATH% +mkdir "%DATOVKAPORTPATH%\locale" +:: copy all required app files and libraries +copy "release\datovka-portable.exe" %DATOVKAPORTPATH% +copy "release\datovka-cli-portable.exe" %DATOVKAPORTPATH% +copy "AUTHORS" %DATOVKAPORTPATH% +copy "copyING" %DATOVKAPORTPATH% +copy "Changelog" %DATOVKAPORTPATH% +copy "scripts\datovka-portable-log.bat" %DATOVKAPORTPATH% +copy "locale\datovka_cs.qm" "%DATOVKAPORTPATH%\locale" +for /R "mingw32built\bin\" %%x in (*.dll) do copy "%%x" %DATOVKAPORTPATH% /Y +windeployqt --release "%DATOVKAPORTPATH%\datovka-portable.exe" +copy "%DATOVKAPORTPATH%\translations\qt_cs.qm" "%DATOVKAPORTPATH%\locale\qtbase_cs.qm" +rmdir /S /Q "%DATOVKAPORTPATH%\translations" +@echo Bundle done. +@echo. +@echo -------------------------------------------------------- +@echo Run 7-ZIP and create ZIP archive of Portable Datovka ... +@echo -------------------------------------------------------- +cd packages +start /wait /Min "Create portable Datovka ZIP archive" %ZIPPATH% a -tzip %DATOVKAPZIP% datovka-%VERSION%-portable +cd .. +@echo ZIP archive done. +@echo. +rmdir /S /Q release +rmdir /S /Q debug +if NOT "%1" == "nopause" ( + cd packages +) \ No newline at end of file diff -Nru datovka-4.8.3/scripts/dependency_sources.sh datovka-4.9.3/scripts/dependency_sources.sh --- datovka-4.8.3/scripts/dependency_sources.sh 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/scripts/dependency_sources.sh 2017-09-06 11:49:23.000000000 +0000 @@ -2,17 +2,17 @@ # Latest libraries. _ZLIB_ARCHIVE="zlib-1.2.11.tar.xz" -_EXPAT_ARCHIVE="expat-2.2.0.tar.bz2" +_EXPAT_ARCHIVE="expat-2.2.4.tar.bz2" _LIBTOOL_ARCHIVE="libtool-2.4.6.tar.xz" _LIBICONV_ARCHIVE="libiconv-1.15.tar.gz" -_LIBXML2_ARCHIVE="libxml2-2.9.4.tar.gz" +_LIBXML2_ARCHIVE="libxml2-2.9.5.tar.gz" _GETTEXT_ARCHIVE="gettext-0.19.8.1.tar.xz" -_LIBCURL_ARCHIVE="curl-7.54.0.tar.bz2" +_LIBCURL_ARCHIVE="curl-7.55.1.tar.bz2" _OPENSSL_ARCHIVE="openssl-1.0.2l.tar.gz" -_LIBISDS_ARCHIVE="libisds-0.10.6.tar.xz" +_LIBISDS_ARCHIVE="libisds-0.10.7.tar.xz" _LIBISDS_ARCHIVE_PATCHES=" \ " _LIBISDS_GIT="https://gitlab.labs.nic.cz/kslany/libisds.git" diff -Nru datovka-4.8.3/scripts/make-win.bat datovka-4.9.3/scripts/make-win.bat --- datovka-4.8.3/scripts/make-win.bat 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/scripts/make-win.bat 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -@echo OFF - -:: There are define paths to QT, NSIS and 7-ZIP -:: Qt paths must be set into PATH on Windows envirom.varialbe -:: User have to change it -set QTPATH="C:\Qt\Qt5.5.1\5.5\mingw492_32\bin\" -set QTMAKEPATH="C:\Qt\Qt5.5.1\Tools\mingw492_32\bin\" -set NSISPATH="C:\Program Files (x86)\NSIS\makensis.exe" -set ZIPPATH="C:\Program Files (x86)\7-Zip\7z.exe" - -:: Get current version from datovka.pro -cd .. -findstr /C:"VERSION =" datovka.pro > version.txt -set "string=var1;var2;var3;" -for /f "tokens=1,2,3 delims= " %%i in (version.txt) do set "variable1=%%i" &set "variable2=%%j" &set "VERSION=%%k" -endlocal -del version.txt - -:: Define packages names -:: User can change it -set DATOVKAZIP="datovka-%VERSION%-windows.zip" -set DATOVKAPZIP="datovka-portable-%VERSION%-windows.zip" - -@echo -------------------------------------------------------------------- -@echo This batch creates Datovka packages for Windows in several steps: -@echo 1) build Datovka (datovka.exe) with QT build tools (requires Qt5.4) -@echo 2) create application packages to "packages" folder -@echo 3) create installation package to "packages" -@echo folder from NSIS script (requires NSIS) -@echo 4) create ZIP packages to "packages" folder (requires 7-ZIP) -@echo --------------------------------------------------------------------- -@echo Warning: Script requires dependency libraries in the folder "dlls"! -@echo This folder and its content must create user - see -@echo "notes/libdepends.win" for more details about "dlls" content. -@echo Qt paths must be set in Windows Environment Variables (PATH)! -@echo NSIS must include plugins: ReplaceInFile.nsh, StrRep.nsh -@echo {available in: \nsis\nsis-libs\} -@echo --------------------------------------------------------------------- -@echo Windows PATH to Qt: %QTPATH% -@echo Windows PATH to Mingw32: %QTMAKEPATH% -@echo Current path to NSIS: %NSISPATH% -@echo Current path to 7-ZIP: %ZIPPATH% -@echo --------------------------------------------------------------------- -@echo Current Datovka version: %VERSION% -@echo --------------------------------------------------------------------- -@echo. -pause - -IF EXIST packages ( - rmdir /S /Q packages -) - -@echo. -@echo ================================= -@echo Build Datovka normal (v%VERSION%) -@echo ================================= -mingw32-make.exe clean -lupdate datovka.pro -lrelease datovka.pro -qmake.exe datovka.pro -r -spec win32-g++ -mingw32-make.exe -j 2 -mingw32-make.exe clean -@echo Build done. -@echo. -@echo ------------------------------------------------- -@echo Creating normal package ... -set DATOVKAPATH=packages\datovka-%VERSION% -mkdir %DATOVKAPATH% -copy "release\datovka.exe" %DATOVKAPATH% -copy "AUTHORS" %DATOVKAPATH% -copy "COPYING" %DATOVKAPATH% -copy "Changelog" %DATOVKAPATH% -copy "scripts\datovka-log.bat" %DATOVKAPATH% -xcopy "dlls\*" %DATOVKAPATH% /E -copy "locale\datovka_cs.qm" "%DATOVKAPATH%\locale" -set SEARCHTEXT="VERSIONXXX" -set file="nsis\datovka-install\datovka-install.nsi" -copy nsis\datovka-install\datovka-install.template %file% -set VERSIONNSIS="%VERSION%" -SETLOCAL ENABLEEXTENSIONS -SETLOCAL DISABLEDELAYEDEXPANSION -if "%SEARCHTEXT%"=="" findstr "^::" "%~f0"&GOTO:EOF -for /f "tokens=1,* delims=]" %%A in ('"type %file%|find /n /v """') do ( - set "line=%%B" - if defined line ( - call set "line=echo.%%line:%SEARCHTEXT%=%VERSIONNSIS%%%" - for /f "delims=" %%X in ('"echo."%%line%%""') do %%~X >> %file%_new - ) ELSE echo. >> %file%_new -) -move /Y %file%_new %file% > nul -@echo Replace %SEARCHTEXT% to %VERSIONNSIS% in the NSIS script -@echo Run Datovka NSIS script ... -start /wait /Min "Build Datovka installer" %NSISPATH% %file% -@echo Done. -@echo Run 7-ZIP and create ZIP archive of Datovka ... -cd packages -start /wait /Min "Build Datovka ZIP archive" %ZIPPATH% a -tzip %DATOVKAZIP% datovka-%VERSION% -cd .. -del %file% -@echo Datovka packages ... Done. - -@echo. -@echo =================================== -@echo Build Datovka portable (v%VERSION%) -@echo =================================== -mingw32-make.exe clean -lupdate datovka.pro -lrelease datovka.pro -qmake.exe datovka.pro -r -spec win32-g++ PORTABLE_APPLICATION=1 -mingw32-make.exe -j 2 -mingw32-make.exe clean -@echo Build done. -@echo. -@echo ------------------------------------------------- -@echo Creating portable package ... -set DATOVKAPORTPATH=packages\datovka-%VERSION%-portable -mkdir %DATOVKAPORTPATH% -copy "release\datovka-portable.exe" %DATOVKAPORTPATH% -copy "AUTHORS" %DATOVKAPORTPATH% -copy "COPYING" %DATOVKAPORTPATH% -copy "Changelog" %DATOVKAPORTPATH% -copy "scripts\datovka-portable-log.bat" %DATOVKAPORTPATH% -xcopy "dlls\*" %DATOVKAPORTPATH% /E -copy "locale\datovka_cs.qm" "%DATOVKAPORTPATH%\locale" -@echo Run 7-ZIP and create ZIP archive of portable Datovka ... -cd packages -start /wait /Min "Build portable Datovka ZIP archive" %ZIPPATH% a -tzip %DATOVKAPZIP% datovka-%VERSION%-portable -cd .. -@echo Portable Datovka package ... Done. -@echo. - -rmdir /S /Q release -rmdir /S /Q debug -cd scripts \ No newline at end of file diff -Nru datovka-4.8.3/src/about.cpp datovka-4.9.3/src/about.cpp --- datovka-4.8.3/src/about.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/about.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#if defined(__APPLE__) || defined(__clang__) +# define __USE_C99_MATH +# define _Bool bool +#else /* !__APPLE__ */ +# include +#endif /* __APPLE__ */ + +#include +#include +#include /* SSLeay_version(3) */ + +#include "src/about.h" + +QStringList libraryDependencies(void) +{ + QStringList libs; + + libs.append(QStringLiteral("Qt ") + qVersion()); + + char *isdsVer = isds_version(); + libs.append(QStringLiteral("libisds ") + isdsVer); + free(isdsVer); isdsVer = NULL; + + libs.append(SSLeay_version(SSLEAY_VERSION)); + + return libs; +} diff -Nru datovka-4.8.3/src/about.h datovka-4.9.3/src/about.h --- datovka-4.8.3/src/about.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/about.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _ABOUT_H_ +#define _ABOUT_H_ + +#include + +/*! + * @brief Obtain list of strings containing libraries which the application + * depends on. + * + * @return List of strings containing library descriptions. + */ +QStringList libraryDependencies(void); + +#endif /* _ABOUT_H_ */ diff -Nru datovka-4.8.3/src/cli/cli.cpp datovka-4.9.3/src/cli/cli.cpp --- datovka-4.8.3/src/cli/cli.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/cli/cli.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -21,22 +21,29 @@ * the two. */ +#include +#include #include #include "src/cli/cli.h" #include "src/cli/cli_login.h" -#include "src/gui/datovka.h" #include "src/io/account_db.h" #include "src/io/dbs.h" #include "src/io/filesystem.h" #include "src/io/isds_helper.h" #include "src/io/isds_sessions.h" #include "src/log/log.h" +#include "src/model_interaction/account_interaction.h" #include "src/worker/pool.h" #include "src/worker/task_download_message.h" #include "src/worker/task_download_message_list.h" #include "src/worker/task_search_owner.h" +const QSet serviceSet = QSet() << SER_LOGIN << +SER_GET_MSG_LIST << SER_SEND_MSG << SER_GET_MSG << SER_GET_DEL_INFO << +SER_GET_USER_INFO << SER_GET_OWNER_INFO << SER_CHECK_ATTACHMENT << +SER_GET_MSG_IDS << SER_FIND_DATABOX; + // Known attributes definition const QStringList connectAttrs = QStringList() << "username" << "password" << "certificate" << "otpcode"; @@ -55,10 +62,10 @@ << "attachmentDir"; const QStringList getDelInfoAttrs = QStringList() << "dmID" << "zfoFile" << "download"; +const QStringList getMsgIdsAttrs = QStringList() << "dmType"; const QStringList findDataboxAttrs = QStringList() << "dbType" << "dbID" << "ic" << "firmName" << "pnFirstName" << "pnLastName" << "adZipCode"; - /* ========================================================================= */ static void printDataToStdOut(const QStringList &data) @@ -99,7 +106,6 @@ cout << CLI_PREFIX << " error(" << err << ") : " << errmsg << endl; } - /* ========================================================================= */ const QString createErrorMsg(const QString &msg) /* ========================================================================= */ @@ -107,7 +113,6 @@ return QString(CLI_PREFIX) + QString(PARSER_PREFIX) + msg; } - /* ========================================================================= */ static void isds_document_free_void(void **document) /* ========================================================================= */ @@ -115,7 +120,6 @@ isds_document_free((struct isds_document **) document); } - /* ========================================================================= */ bool checkAttributeIfExists(const QString &service, const QString &attribute) /* ========================================================================= */ @@ -130,13 +134,14 @@ return getMsgAttrs.contains(attribute); } else if (service == SER_GET_DEL_INFO) { return getDelInfoAttrs.contains(attribute); + } else if (service == SER_GET_MSG_IDS) { + return getMsgIdsAttrs.contains(attribute); } else if (service == SER_FIND_DATABOX) { return findDataboxAttrs.contains(attribute); } return false; } - /* ========================================================================= */ const QStringList parseAttachment(const QString &files) /* ========================================================================= */ @@ -147,7 +152,6 @@ return files.split(";"); } - /* ========================================================================= */ const QStringList parseDbIDRecipient(const QString &dbIDRecipient) /* ========================================================================= */ @@ -158,7 +162,6 @@ return dbIDRecipient.split(";"); } - /* ========================================================================= */ cli_error getMsgList(const QMap &map, MessageDbSet *msgDbSet, QString &errmsg) @@ -310,7 +313,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ cli_error getMsg(const QMap &map, MessageDbSet *msgDbSet, bool needsISDS, QString &errmsg) @@ -473,7 +475,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ cli_error getDeliveryInfo(const QMap &map, MessageDbSet *msgDbSet, bool needsISDS, QString &errmsg) @@ -552,7 +553,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ cli_error checkAttachment(const QMap &map, MessageDbSet *msgDbSet) @@ -568,6 +568,34 @@ return CLI_SUCCESS; } +/* ========================================================================= */ +cli_error getMsgIds(const QMap &map, + MessageDbSet *msgDbSet, QString &errmsg) +/* ========================================================================= */ +{ + const QString username = map["username"].toString(); + + qDebug() << CLI_PREFIX << "Get list of message IDs " + "from local database for username" << username; + + if ((map["dmType"].toString() != MT_RECEIVED) && + (map["dmType"].toString() != MT_SENT) && + (map["dmType"].toString() != MT_SENT_RECEIVED)) { + errmsg = "Wrong dmType value: " + map["dmType"].toString(); + qDebug() << CLI_PREFIX << errmsg; + return CLI_ATR_VAL_ERR; + } + + if (map["dmType"].toString() == MT_RECEIVED) { + printDataToStdOut(msgDbSet->getAllMessageIDs(MessageDb::TYPE_RECEIVED)); + } else if (map["dmType"].toString() == MT_SENT) { + printDataToStdOut(msgDbSet->getAllMessageIDs(MessageDb::TYPE_SENT)); + } else { + printDataToStdOut(msgDbSet->getAllMessageIDs(MessageDb::TYPE_RECEIVED)); + printDataToStdOut(msgDbSet->getAllMessageIDs(MessageDb::TYPE_SENT)); + } + return CLI_SUCCESS; +} /* ========================================================================= */ cli_error getUserInfo(const QMap &map, QString &errmsg) @@ -586,7 +614,6 @@ return CLI_ERROR; } - /* ========================================================================= */ cli_error getOwnerInfo(const QMap &map, QString &errmsg) /* ========================================================================= */ @@ -604,7 +631,6 @@ return CLI_ERROR; } - /* ========================================================================= */ cli_error findDatabox(const QMap &map, QString &errmsg) /* ========================================================================= */ @@ -659,7 +685,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ static struct isds_list *buildDocuments(const QStringList &filePaths) @@ -1069,7 +1094,6 @@ return ret; } - /* ========================================================================= */ cli_error checkLoginMandatoryAttributes(const QMap &map, QString &errmsg) @@ -1089,7 +1113,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ cli_error checkSendMsgMandatoryAttributes(const QMap &map, QString &errmsg) @@ -1134,7 +1157,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ cli_error checkGetMsgListMandatoryAttributes(const QMap &map, QString &errmsg) @@ -1163,7 +1185,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ cli_error checkGetMsgMandatoryAttributes(const QMap &map, QString &errmsg) @@ -1209,7 +1230,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ cli_error checkDownloadDeliveryMandatoryAttributes( const QMap &map, QString &errmsg) @@ -1241,7 +1261,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ cli_error checkFindDataboxMandatoryAttributes( const QMap &map, QString &errmsg) @@ -1342,7 +1361,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ cli_error checkMandatoryAttributes(const QString &service, QMap &map, QString &errmsg) @@ -1358,6 +1376,8 @@ return checkGetMsgMandatoryAttributes(map, errmsg); } else if (service == SER_GET_DEL_INFO) { return checkDownloadDeliveryMandatoryAttributes(map, errmsg); + } else if (service == SER_GET_MSG_IDS) { + return checkGetMsgListMandatoryAttributes(map, errmsg); } else if (service == SER_FIND_DATABOX) { return checkFindDataboxMandatoryAttributes(map, errmsg); } @@ -1365,7 +1385,6 @@ return CLI_UNKNOWN_SER; } - /* ========================================================================= */ cli_error parsePamamString(const QString &service, const QString ¶mString, QMap &map, QString &errmsg) @@ -1501,7 +1520,6 @@ return CLI_SUCCESS; } - /* ========================================================================= */ cli_error doService(const QString &service, const QMap &map, MessageDbSet *msgDbSet, bool needsISDS, QString &errmsg) @@ -1522,6 +1540,8 @@ return getOwnerInfo(map, errmsg); } else if (service == SER_CHECK_ATTACHMENT) { return checkAttachment(map, msgDbSet); + } else if (service == SER_GET_MSG_IDS) { + return getMsgIds(map, msgDbSet, errmsg); } else if (service == SER_FIND_DATABOX) { return findDatabox(map, errmsg); } @@ -1529,7 +1549,6 @@ return CLI_UNKNOWN_SER; } - /* ========================================================================= */ int runService(const QString &lParam, const QString &service, const QString &sParam) @@ -1540,7 +1559,7 @@ cli_error cret = CLI_ERROR; bool needsISDS = true; QString errmsg = "Unknown error"; - int ret = CLI_EXIT_ERROR; + int ret = EXIT_FAILURE; /* parse service parameter list */ if (!(service.isNull()) && !(sParam.isNull())) { @@ -1570,7 +1589,13 @@ const QString username = loginMap["username"].toString(); /* get message database set */ - MessageDbSet *msgDbSet = MainWindow::accountDbSet(username, 0); + MessageDbSet *msgDbSet = Q_NULLPTR; + { + enum AccountInteraction::AccessStatus status; + QString dbDir, namesStr; + msgDbSet = AccountInteraction::accessDbSet(username, status, + dbDir, namesStr); + } if (msgDbSet == NULL) { errmsg = "Database doesn't exists for user " + username; qDebug() << CLI_PREFIX << errmsg; @@ -1646,7 +1671,7 @@ } } - if (service == SER_CHECK_ATTACHMENT) { + if (service == SER_CHECK_ATTACHMENT || service == SER_GET_MSG_IDS) { needsISDS = false; } @@ -1665,7 +1690,7 @@ if (!globIsdsSessions.isConnectedToIsds(username) && !connectToIsdsCLI(globIsdsSessions, - AccountModel::globAccounts[username], pwd, otp)) { + globAccounts[username], pwd, otp)) { errmsg = "Missing session for " + username + " or connection fails"; qDebug() << errmsg; @@ -1685,7 +1710,7 @@ } if (CLI_SUCCESS == cret) { - ret = CLI_EXIT_OK; + ret = EXIT_SUCCESS; } else { printErrToStdErr(cret, errmsg); } diff -Nru datovka-4.8.3/src/cli/cli.h datovka-4.9.3/src/cli/cli.h --- datovka-4.8.3/src/cli/cli.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/cli/cli.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,16 +21,12 @@ * the two. */ +#ifndef _CLI_H_ +#define _CLI_H_ -#ifndef CLI_H -#define CLI_H +#include +#include -#include -#include - - -#define CLI_EXIT_ERROR 1 -#define CLI_EXIT_OK 0 #define CLI_PREFIX "D-CLI: " #define PARSER_PREFIX "Parser error: " @@ -60,6 +56,7 @@ #define SER_GET_USER_INFO "get-user-info" #define SER_GET_OWNER_INFO "get-owner-info" #define SER_CHECK_ATTACHMENT "check-attachment" +#define SER_GET_MSG_IDS "get-msg-ids" #define SER_FIND_DATABOX "find-databox" @@ -78,19 +75,16 @@ // IMORTANT: if any another service is/ will be defined, // it must be added into this service list -const QStringList serviceList = QStringList() << SER_LOGIN << -SER_GET_MSG_LIST << SER_SEND_MSG << SER_GET_MSG << SER_GET_DEL_INFO << -SER_GET_USER_INFO << SER_GET_OWNER_INFO << SER_CHECK_ATTACHMENT << -SER_FIND_DATABOX; +extern const QSet serviceSet; /* * Run login + service * [in] lParam = login parameter string * [in] service = name of service * [in] sParam = service parameter string - * @retrun status code of operation + * @return status code of operation (EXIT_SUCCESS or EXIT_FAILURE) */ int runService(const QString &lParam, const QString &service, const QString &sParam); -#endif // CLI_H +#endif /* _CLI_H_ */ diff -Nru datovka-4.8.3/src/cli/cli_parser.cpp datovka-4.9.3/src/cli/cli_parser.cpp --- datovka-4.8.3/src/cli/cli_parser.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/cli/cli_parser.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include + +#include "src/cli/cli.h" +#include "src/cli/cli_parser.h" +#include "src/log/log.h" + +int CLIParser::setupCmdLineParser(QCommandLineParser &parser) +{ + parser.setApplicationDescription(tr("Data box application")); + parser.addHelpOption(); + parser.addVersionOption(); + /* Options with values. */ + if (!parser.addOption(QCommandLineOption(CONF_SUBDIR_OPT, + tr("Use <%1> subdirectory for configuration.").arg(tr("conf-subdir")), + tr("conf-subdir")))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(LOAD_CONF_OPT, + tr("On start load <%1> file.").arg(tr("conf")), tr("conf")))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(SAVE_CONF_OPT, + tr("On stop save <%1> file.").arg(tr("conf")), tr("conf")))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(LOG_FILE, + tr("Log messages to <%1>.").arg(tr("file")), tr("file")))) { + return -1; + } + QCommandLineOption logVerb(QStringList() << "L" << LOG_VERBOSITY_OPT, + tr("Set verbosity of logged messages to <%1>. Default is %2.") + .arg(tr("level")).arg(QString::number(globLog.logVerbosity())), + tr("level")); + if (!parser.addOption(logVerb)) { + return -1; + } + /* Boolean options. */ +#ifdef DEBUG + QCommandLineOption debugOpt(QStringList() << "D" << DEBUG_OPT, + tr("Enable debugging information.")); + if (!parser.addOption(debugOpt)) { + return -1; + } + QCommandLineOption debugVerb(QStringList() << "V" << DEBUG_VERBOSITY_OPT, + tr("Set debugging verbosity to <%1>. Default is %2.") + .arg(tr("level")).arg(QString::number(globLog.debugVerbosity())), + tr("level")); + if (!parser.addOption(debugVerb)) { + return -1; + } +#endif /* DEBUG */ + + /* Options with values. */ + if (!parser.addOption(QCommandLineOption(SER_LOGIN, + tr("Service: connect to ISDS and login into data box."), + tr("string-of-parameters")))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(SER_GET_MSG_LIST, + tr("Service: download list of received/sent messages from ISDS (synchronization)."), + tr("string-of-parameters")))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(SER_SEND_MSG, + tr("Service: create and send a new message to ISDS."), + tr("string-of-parameters")))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(SER_GET_MSG, + tr("Service: download complete message with signature and time stamp of MV."), + tr("string-of-parameters")))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(SER_GET_DEL_INFO, + tr("Service: download acceptance info of message with signature and time stamp of MV."), + tr("string-of-parameters")))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(SER_GET_USER_INFO, + tr("Service: get information about user (role, privileges, ...)."), + QString()))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(SER_GET_OWNER_INFO, + tr("Service: get information about owner and its data box."), + QString()))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(SER_CHECK_ATTACHMENT, + tr("Service: get list of messages where attachment missing (local database only)."), + QString()))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(SER_FIND_DATABOX, + tr("Service: find a data box via several parameters."), + tr("string-of-parameters")))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(SER_GET_MSG_IDS, + tr("Service: get list of message IDs (received/sent) from local database."), + tr("string-of-parameters")))) { + return -1; + } + + parser.addPositionalArgument(tr("[zfo-file]"), + tr("ZFO file to be viewed.")); + + return 0; +} + +QStringList CLIParser::CLIServiceArgs(const QStringList &options) +{ + QStringList srvcArgs; + + foreach (const QString &option, options) { + if (serviceSet.contains(option)) { + srvcArgs.append(option); + } + } + + return srvcArgs; +} + +int CLIParser::runCLIService(const QStringList &srvcArgs, + const QCommandLineParser &parser) +{ + int ret = EXIT_FAILURE; + QString errmsg; + QString serName; + QTextStream errStream(stderr); + + /* + * Every valid CLI action must have only one login parameter + * or one login parameter and one service name. + */ + switch (srvcArgs.count()) { + case 0: + errmsg = "No service has been defined for CLI action!"; + break; + case 1: + if (srvcArgs.contains(SER_LOGIN)) { + ret = runService(parser.value(SER_LOGIN), + QString(), QString()); + return ret; + } else { + errmsg = "Only service name was set. " + "Login parameter is missing!"; + } + break; + case 2: + if (srvcArgs.contains(SER_LOGIN)) { + if (0 == srvcArgs.indexOf(SER_LOGIN)) { + serName = srvcArgs.at(1); + } else { + serName = srvcArgs.at(0); + } + ret = runService(parser.value(SER_LOGIN), + serName, parser.value(serName)); + return ret; + } else { + errmsg = "Login parameter is missing! " + "Maybe two service names were set."; + } + break; + default: + errmsg = "More than two service names or logins were set! " + "This situation is not allowed."; + break; + } + + /* Print error to error output. */ + errStream << CLI_PREFIX << " error(" << CLI_ERROR << ") : " + << errmsg << endl; + + return ret; +} diff -Nru datovka-4.8.3/src/cli/cli_parser.h datovka-4.9.3/src/cli/cli_parser.h --- datovka-4.8.3/src/cli/cli_parser.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/cli/cli_parser.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _CLI_PARSER_H_ +#define _CLI_PARSER_H_ + +#include +#include + +#define CONF_SUBDIR_OPT "conf-subdir" +#define LOAD_CONF_OPT "load-conf" +#define SAVE_CONF_OPT "save-conf" +#define LOG_FILE "log-file" + +#define LOG_VERBOSITY_OPT "log-verbosity" +#define DEBUG_OPT "debug" +#define DEBUG_VERBOSITY_OPT "debug-verbosity" + +/*! + * @brief Provides namespace for convenience methods dealing with command line + * parser. + */ +class CLIParser { + Q_DECLARE_TR_FUNCTIONS(CLIParser) + +private: + /*! + * @brief Private constructor. + */ + CLIParser(void); + +public: + /*! + * @brief Performs command-line parser setup. + * + * @param[in,out] parser Parser to add options to. + * @return 0 on success, -1 else. + */ + static + int setupCmdLineParser(QCommandLineParser &parser); + + /*! + * @brief Returns list of options related to CLI services. + * + * @param[in] options Command line options. + * @return List of options related to services. + */ + static + QStringList CLIServiceArgs(const QStringList &options); + + /*! + * @brief Calls command-line service. + * + * @param[in] srvcArgs Service arguments. + * @patam[in] parser Command line parser. + * @return EXIT_SUCCESS on success, EXIT_FAILURE on failure. + */ + static + int runCLIService(const QStringList &srvcArgs, + const QCommandLineParser &parser); +}; + +#endif /* _CLI_PARSER_H_ */ diff -Nru datovka-4.8.3/src/common.cpp datovka-4.9.3/src/common.cpp --- datovka-4.8.3/src/common.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/common.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -24,8 +24,7 @@ #include #include -#include "common.h" -#include "src/io/isds_sessions.h" +#include "src/common.h" #include "src/log/log.h" const QString dateTimeDisplayFormat("dd.MM.yyyy HH:mm:ss"); @@ -58,28 +57,6 @@ message += newLine; } -const QString authorTypeToText(const QString &authorType) -{ - if ("PRIMARY_USER" == authorType) { - /* Opravnena osoba nebo likvidator. */ - return QObject::tr("Primary user"); - } else if ("ENTRUSTED_USER" == authorType) { - /* Poverena osoba. */ - return QObject::tr("Entrusted user"); - } else if ("ADMINISTRATOR" == authorType) { - /* Systemove DZ. */ - return QObject::tr("Administrator"); - } else if ( "OFFICIAL" == authorType) { - /* Systemove DZ. */ - return QObject::tr("Official"); - } else if ("VIRTUAL" == authorType) { - /* Spisovka. */ - return QObject::tr("Virtual"); - } else { - return QString(); - } -} - int base64RealSize(const QByteArray &b64) { int b64size = b64.size(); @@ -94,206 +71,6 @@ return b64size * 3 / 4 - cnt; } -QString convertAttachmentType(int value) -{ - if (value == FILEMETATYPE_MAIN) return "main"; - else if (value == FILEMETATYPE_ENCLOSURE) return "encl"; - else if (value == FILEMETATYPE_SIGNATURE) return "sign"; - else if (value == FILEMETATYPE_META) return "meta"; - else return ""; -} - -QString convertDbTypeToString(int value) -{ - if (value == DBTYPE_SYSTEM) return "SYSTEM"; - else if (value == DBTYPE_OVM) return "OVM"; - else if (value == DBTYPE_OVM_NOTAR) return "OVM_NOTAR"; - else if (value == DBTYPE_OVM_EXEKUT) return "OVM_EXEKUT"; - else if (value == DBTYPE_OVM_REQ) return "OVM_REQ"; - else if (value == DBTYPE_PO) return "PO"; - else if (value == DBTYPE_PO_ZAK) return "PO_ZAK"; - else if (value == DBTYPE_PO_REQ) return "PO_REQ"; - else if (value == DBTYPE_PFO) return "PFO"; - else if (value == DBTYPE_PFO_ADVOK) return "PFO_ADVOK"; - else if (value == DBTYPE_PFO_DANPOR) return "PFO_DANPOR"; - else if (value == DBTYPE_PFO_INSSPR) return "PFO_INSSPR"; - else if (value == DBTYPE_FO) return "FO"; - else return ""; -} - -int convertDbTypeToInt(QString value) -{ - if (value == "OVM") return DBTYPE_OVM; - else if (value == "OVM_NOTAR") return DBTYPE_OVM_NOTAR; - else if (value == "OVM_EXEKUT") return DBTYPE_OVM_EXEKUT; - else if (value == "OVM_REQ") return DBTYPE_OVM_REQ; - else if (value == "PO") return DBTYPE_PO; - else if (value == "PO_ZAK") return DBTYPE_PO_ZAK; - else if (value == "PO_REQ") return DBTYPE_PO_REQ; - else if (value == "PFO") return DBTYPE_PFO; - else if (value == "PFO_ADVOK") return DBTYPE_PFO_ADVOK; - else if (value == "PFO_DANPOR") return DBTYPE_PFO_DANPOR; - else if (value == "PFO_INSSPR") return DBTYPE_PFO_INSSPR; - else if (value == "FO") return DBTYPE_FO; - else return DBTYPE_SYSTEM; -} - -QString convertEventTypeToString(int value) -{ - if (value == EVENT_ACCEPTED_BY_RECIPIENT) return "EV4: "; - else if (value == EVENT_ACCEPTED_BY_FICTION) return "EV2: "; - else if (value == EVENT_UNDELIVERABLE) return "EV3: "; - else if (value == EVENT_COMMERCIAL_ACCEPTED) return "EV1: "; - else if (value == EVENT_ENTERED_SYSTEM) return "EV0: "; - else if (value == EVENT_DELIVERED) return "EV5: "; - else if (value == EVENT_PRIMARY_LOGIN) return "EV11: "; - else if (value == EVENT_ENTRUSTED_LOGIN) return "EV12: "; - else if (value == EVENT_SYSCERT_LOGIN) return "EV13: "; - else if (value == EVENT_UKNOWN) return ""; - else return ""; -} - -QString convertHashAlg(int value) -{ - if (value == HASH_ALGORITHM_MD5) return "MD5"; - else if (value == HASH_ALGORITHM_SHA_1) return "SHA-1"; - else if (value == HASH_ALGORITHM_SHA_224) return "SHA-224"; - else if (value == HASH_ALGORITHM_SHA_256) return "SHA-256"; - else if (value == HASH_ALGORITHM_SHA_384) return "SHA-384"; - else if (value == HASH_ALGORITHM_SHA_512) return "SHA-512"; - else return ""; -} - -int convertHashAlg2(QString value) -{ - if (value == "MD5") return HASH_ALGORITHM_MD5; - else if (value == "SHA-1") return HASH_ALGORITHM_SHA_1; - else if (value == "SHA-224") return HASH_ALGORITHM_SHA_224; - else if (value == "SHA-256") return HASH_ALGORITHM_SHA_256; - else if (value == "SHA-384") return HASH_ALGORITHM_SHA_384; - else if (value == "SHA-512") return HASH_ALGORITHM_SHA_512; - else return 0; -} - -int convertHexToDecIndex(int value) -{ - if (value == MESSAGESTATE_SENT) return 1; - else if (value == MESSAGESTATE_STAMPED) return 2; - else if (value == MESSAGESTATE_INFECTED) return 3; - else if (value == MESSAGESTATE_DELIVERED) return 4; - else if (value == MESSAGESTATE_SUBSTITUTED) return 5; - else if (value == MESSAGESTATE_RECEIVED) return 6; - else if (value == MESSAGESTATE_READ) return 7; - else if (value == MESSAGESTATE_UNDELIVERABLE) return 8; - else if (value == MESSAGESTATE_REMOVED) return 9; - else if (value == MESSAGESTATE_IN_SAFE) return 10; - else return 0; -} - -QString convertSenderDbTypesToString(int value) -{ - /* System ISDS */ - if (value == DBTYPE_SYSTEM) return QObject::tr("System ISDS"); - /* OVM */ - else if (value == DBTYPE_OVM) return QObject::tr("Public authority"); - /* PO */ - else if (value == DBTYPE_PO) return QObject::tr("Legal person"); - /* PFO (OSVC) */ - else if (value == DBTYPE_PFO) return QObject::tr("Self-employed person"); - /* FO */ - else if (value == DBTYPE_FO) return QObject::tr("Natural person"); - /* unknown */ - else return ""; -} - -QString convertSenderTypeToString(int value) -{ - if (value == SENDERTYPE_PRIMARY) return "PRIMARY_USER"; - else if (value == SENDERTYPE_ENTRUSTED) return "ENTRUSTED_USER"; - else if (value == SENDERTYPE_ADMINISTRATOR) return "ADMINISTRATOR"; - else if (value == SENDERTYPE_OFFICIAL) return "OFFICIAL"; - else if (value == SENDERTYPE_VIRTUAL) return "VIRTUAL"; - else if (value == SENDERTYPE_OFFICIAL_CERT) return "OFFICIAL_CERT"; - else if (value == SENDERTYPE_LIQUIDATOR) return "LIQUIDATOR"; - else return ""; -} - -QString convertUserPrivilsToString(int userPrivils) -{ - QString privStr; - const QString sepPref("
  • - "), sepSuff("
  • "); - - if (userPrivils == 255) { - return QObject::tr("Full control"); - } else { - privStr = QObject::tr("Restricted control"); - } - - if (userPrivils & PRIVIL_READ_NON_PERSONAL) { - // "stahovat a číst došlé DZ" - privStr += sepPref + - QObject::tr("download and read incoming DM") + sepSuff; - } - if (userPrivils & PRIVIL_READ_ALL) { - // "stahovat a číst DZ určené do vlastních rukou" - privStr += sepPref + - QObject::tr("download and read DM sent into own hands") + - sepSuff; - } - if (userPrivils & PRIVIL_CREATE_DM) { - // "vytvářet a odesílat DZ, stahovat odeslané DZ" - privStr += sepPref + - QObject::tr("create and send DM, download sent DM") + - sepSuff; - } - if (userPrivils & PRIVIL_VIEW_INFO) { - // "načítat seznamy DZ, Dodejky a Doručenky" - privStr += sepPref + - QObject::tr( - "retrieve DM lists, delivery and acceptance reports") + - sepSuff; - } - if (userPrivils & PRIVIL_SEARCH_DB) { - // "vyhledávat DS" - privStr += sepPref + - QObject::tr("search for data boxes") + sepSuff; - } - if (userPrivils & PRIVIL_OWNER_ADM) { - // "spravovat DS" - privStr += sepPref + QObject::tr("manage the data box") + - sepSuff; - } - if (userPrivils & PRIVIL_READ_VAULT) { - // "číst zprávy v DT" - privStr += sepPref + - QObject::tr("read message in data vault") + sepSuff; - } - if (userPrivils & PRIVIL_ERASE_VAULT) { - // "mazat zprávy v DT" - privStr += sepPref + - QObject::tr("erase messages from data vault") + sepSuff; - } - return privStr; -} - -const QString & convertUserTypeToString(int value) -{ - static const QString pu("PRIMARY_USER"), eu("ENTRUSTED_USER"), - a("ADMINISTRATOR"), l("LIQUIDATOR"), ou("OFFICIAL_USER"), - ocu("OFFICIAL_CERT_USER"); - static const QString empty; - - switch (value) { - case USERTYPE_PRIMARY: return pu; - case USERTYPE_ENTRUSTED: return eu; - case USERTYPE_ADMINISTRATOR: return a; - case USERTYPE_LIQUIDATOR: return l; - case USERTYPE_OFFICIAL: return ou; - case USERTYPE_OFFICIAL_CERT: return ocu; - default: return empty; - } -} - void createEmailMessage(QString &message, const QString &subj, const QString &boundary) { @@ -319,35 +96,6 @@ message += " " + newLine; } -const QString dmTypeToText(const QString &dmType) -{ - if (dmType.size() != 1) { - return QString(); - } - - switch (dmType[0].toLatin1()) { - case 'K': - return QObject::tr("Postal data message"); - break; - case 'I': - return QObject::tr("Initializing postal data message"); - break; - case 'O': - return QObject::tr("Reply postal data message"); - break; - case 'X': - return QObject::tr( - "Initializing postal data message - expired"); - break; - case 'Y': - return QObject::tr("Initializing postal data message - used"); - break; - default: - return QString(); - break; - } -} - void finishEmailMessage(QString &message, const QString &boundary) { const QString newLine("\n"); /* "\r\n" ? */ @@ -359,78 +107,6 @@ return QString::fromUtf8(QByteArray::fromBase64(base64.toUtf8())); } -QString getdbStateText(int value) -{ - switch (value) { - case DBSTATE_ACCESSIBLE: - /* Datová schránka je přístupná, lze do ní dodávat zprávy, na Portále lze vyhledat. */ - return QObject::tr( - "The data box is accessible. It is possible to send messages into it. It can be looked up on the Portal."); - break; - case DBSTATE_TEMP_UNACCESSIBLE: - /* Datová schránka je dočasně znepřístupněna (na vlastní žádost), může být později opět zpřístupněna. */ - return QObject::tr( - "The data box is temporarily inaccessible (at own request). It may be made accessible again at some point in the future."); - break; - case DBSTATE_NOT_YET_ACCESSIBLE: - /* Datová schránka je dosud neaktivní. Vlastník schránky se musí poprvé přihlásit do webového rozhraní, aby došlo k aktivaci schránky. */ - return QObject::tr( - "The data box is so far inactive. The owner of the box has to log into the web interface at first in order to activate the box."); - break; - case DBSTATE_PERM_UNACCESSIBLE: - /* Datová schránka je trvale znepřístupněna, čeká na smazání (může být opět zpřístupněna). */ - return QObject::tr( - "The data box is permanently inaccessible. It is waiting to be deleted (but it may be made accessible again)."); - break; - case DBSTATE_REMOVED: - /* Datová schránka je smazána (přesto existuje v ISDS). */ - return QObject::tr( - "The data box has been deleted (none the less it exists in ISDS)."); - break; - default: - return QObject::tr("An error occurred while checking the status."); - break; - } -} - -QString getWebDatovkaUsername(const QString &userId, const QString &accountId) -{ - return DB_MOJEID_NAME_PREFIX + userId + "-" + accountId; -} - -int getWebDatovkaAccountId(const QString &userName) -{ - if (!userName.contains(DB_MOJEID_NAME_PREFIX)) { - return -1; - } - - const QString aID = userName.split("-").at(2); - return aID.toInt(); -} - -int getWebDatovkaUserId(const QString &userName) -{ - if (!userName.contains(DB_MOJEID_NAME_PREFIX)) { - return -1; - } - const QString uID = userName.split("-").at(1); - return uID.toInt(); -} - -QString getWebDatovkaTagDbPrefix(const QString &userName) -{ - if (!userName.contains(DB_MOJEID_NAME_PREFIX)) { - return QString(); - } - - return DB_MOJEID_NAME_PREFIX + userName.split("-").at(1); -} - -bool isWebDatovkaAccount(const QString &userName) -{ - return userName.contains(DB_MOJEID_NAME_PREFIX); -} - bool isValidDatabaseFileName(QString inDbFileName, QString &dbUserName, QString &dbYear, bool &dbTestingFlag, QString &errMsg) { @@ -503,82 +179,6 @@ return true; } -const QString msgStatusToText(int status) -{ - switch (status) { - case 1: - /* Zprava byla podana (vznikla v ISDS). */ - return QObject::tr("Message has been submitted (has been created in ISDS)"); - break; - case 2: - /* - * Datová zprava vcetne pisemnosti podepsana casovym razitkem. - */ - return QObject::tr("Data message including its attachments signed with time-stamp."); - break; - case 3: - /* - * Zprava neprosla AV kontrolou; nakazena pisemnost je smazana; - * konecny stav zpravy pred smazanim. - */ - return QObject::tr("Message did not pass through AV check; " - "infected paper deleted; final status before deletion."); - break; - case 4: - /* Zprava dodana do ISDS (zapsan cas dodani). */ - return QObject::tr("Message handed into ISDS " - "(delivery time recorded)."); - break; - case 5: - /* - * Uplynulo 10 dnu od dodani verejne zpravy, ktera dosud nebyla - * dorucena prihlasenim (predpoklad dorucení fikci u neOVM DS); - * u komercni zpravy nemuze tento stav nastat. - */ - return QObject::tr("10 days have passed since the delivery of " - "the public message which has not been accepted by " - "logging-in (assumption of acceptance through fiction in non-OVM " - "DS); this state cannot occur for commercial messages."); - break; - case 6: - /* - * Osoba opravnena cist tuto zpravu se prihlasila - dodana - * zprava byla dorucena.", - */ - return QObject::tr("A person authorised to read this message " - "has logged in -- delivered message has been accepted."); - break; - case 7: - /* Zprava byla prectena (na portale nebo akci ESS). */ - return QObject::tr("Message has been read (on the portal or " - "by ESS action)."); - break; - case 8: - /* - * Zprava byla oznacena jako nedorucitelna, protoze DS adresata - * byla zpetne znepristupnena. - */ - return QObject::tr("Message marked as undeliverable because " - "the target DS has been made inaccessible."); - break; - case 9: - /* - * Obsah zpravy byl smazan, obalka zpravy vcetne hashu - * presunuta do archivu. - */ - return QObject::tr("Message content deleted, envelope " - "including hashes has been moved into archive."); - break; - case 10: - /* Zprava je v Datovem trezoru. */ - return QObject::tr("Message resides in data vault."); - break; - default: - return QString(); - break; - } -} - QString toBase64(const QString &plain) { return QString::fromUtf8(plain.toUtf8().toBase64()); diff -Nru datovka-4.8.3/src/common.h datovka-4.9.3/src/common.h --- datovka-4.8.3/src/common.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/common.h 2017-09-06 11:49:23.000000000 +0000 @@ -52,21 +52,18 @@ #define CZ_NIC_URL "https://www.nic.cz" #define DATOVKA_ONLINE_HELP_URL "https://secure.nic.cz/files/datove_schranky/redirect/prirucka.html" #define DATOVKA_FAQ_URL "https://secure.nic.cz/files/datove_schranky/redirect/faq.html" -#define DATOVKA_HOMEPAGE_URL "https://labs.nic.cz/cs/datovka.html" +#define DATOVKA_HOMEPAGE_URL "https://www.datovka.cz/" #define DATOVKA_CHECK_NEW_VERSION_URL "https://secure.nic.cz/files/datove_schranky/Version" -#define DATOVKA_DOWNLOAD_URL "https://labs.nic.cz/cs/datovka.html" +#define DATOVKA_DOWNLOAD_URL "https://www.datovka.cz/" #define PWD_EXPIRATION_NOTIFICATION_DAYS 7 // show expiration date dialog before xx days -#define DB_MOJEID_NAME_PREFIX "mojeid-" - /* return values of Datovka login methods */ typedef enum { USER_NAME = 0, CERTIFICATE = 1, USER_CERTIFICATE = 2, HOTP = 3, - TOTP = 4, - MOJEID = 5 + TOTP = 4 } LoginMethodsIndex; @@ -118,29 +115,38 @@ * are displayed as icons. */ +/* Expecting arguments of type QString. */ +#define strongAccountInfoLineNoEscape(title, value) \ + (QLatin1String("
    ") + (title) + \ + QLatin1String(": ") + (value) + \ + QLatin1String("
    ")) #define strongAccountInfoLine(title, value) \ - (QString("
    ") + (title) + ": " + (value) + \ - "
    ") + (QLatin1String("
    ") + (title).toHtmlEscaped() + \ + QLatin1String(": ") + (value).toHtmlEscaped() + \ + QLatin1String("
    ")) #define accountInfoLine(title, value) \ - (QString("
    ") + (title) + ": " + (value) + "
    ") -#define indentDivStart "
    " -#define divEnd "
    " + (QLatin1String("
    ") + (title).toHtmlEscaped() + \ + QLatin1String(": ") + (value).toHtmlEscaped() + QLatin1String("
    ")) +#define indentDivStart QLatin1String("
    ") +#define divEnd QLatin1String("
    ") #define strongMessagePdf(title) \ - (QString("") + (title) + QString("")) + (QLatin1String("") + (title).toHtmlEscaped() + \ + QLatin1String("")) #define messageTableSectionPdf(title) \ - (QString("
    ") + \ - title + QString("
    ")) + (QLatin1String("
    ") + \ + (title).toHtmlEscaped() + QLatin1String("
    ")) #define messageTableInfoStartPdf() \ - (QString("")) + (QLatin1String("
    ")) #define messageTableInfoPdf(title, value) \ - (QString("")) + (QLatin1String("")) -#define messageTableInfoEndPdf() (QString("
    ") + title + QString(": ") + \ - QString("") + value + QString("
    ") + (title).toHtmlEscaped() + \ + QLatin1String(": ") + QLatin1String("") + \ + (value).toHtmlEscaped() + QLatin1String("
    ")) +#define messageTableInfoEndPdf() (QLatin1String("")) /*! * @brief Date/time format used in the application. @@ -162,14 +168,6 @@ const QByteArray &base64, const QString &boundary); /*! - * @brief Translates author type to text. - * - * @param[in] authorType Author type string. - * @return Author type description. - */ -const QString authorTypeToText(const QString &authorType); - -/*! * @brief Computes the size of real (decoded from base64) data. * * @param[in] b64 Data in Base64. @@ -178,94 +176,6 @@ int base64RealSize(const QByteArray &b64); /*! - * @brief Return attachment type as string. - * - * @param[in] value Attachment type value. - * @return Attachment type description. - */ -QString convertAttachmentType(int value); - -/*! - * @brief Convert type of databox to int. - * - * @param[in] value databox type string. - * @return databox int. - */ -int convertDbTypeToInt(QString value); - -/*! - * @brief Convert type of databox to string. - * - * @param[in] value databox type value. - * @return Databox type description. - */ -QString convertDbTypeToString(int value); - -/*! - * @brief Convert event type to string. - * - * @param[in] value event type value. - * @return Event description. - */ -QString convertEventTypeToString(int value); - -/*! - * @brief Return hash algorithm as string. - * - * @param[in] value Hash algorithm value. - * @return Hash algorithm type string. - */ -QString convertHashAlg(int value); - - /*! - * @brief Return hash algorithm as int. - * - * @param[in] value Hash algorithm string. - * @return Hash algorithm type value. - */ -int convertHashAlg2(QString value); - -/*! - * @brief Return dec index from hex. - * - * @param[in] value Decadical value. - * @return Hexadecimal value. - */ -int convertHexToDecIndex(int value); - -/*! - * @brief Return sender databox type as string from number representation. - * - * @param[in] value Sender databox type value. - * @return Sender databox type description. - */ -QString convertSenderDbTypesToString(int value); - -/*! - * @brief Convert type of author to string. - * - * @param[in] value Author type value. - * @return Author type description. - */ -QString convertSenderTypeToString(int value); - -/*! - * @brief Return privilegs as html string from number representation. - * - * @param[in] userPrivils Privilegy value. - * @return Privilegy description. - */ -QString convertUserPrivilsToString(int userPrivils); - -/*! - * Convert type of user to string. - * - * @param[in] value user type value. - * @return User description. - */ -const QString & convertUserTypeToString(int value); - -/*! * @brief Creates email header and message body. * * @param[in,out] message Message body. @@ -276,14 +186,6 @@ const QString &boundary); /*! - * @brief Translates message type to text. - * - * @param[in] dmType Message type value. - * @return Message type description. - */ -const QString dmTypeToText(const QString &dmType); - -/*! * @brief Adds last line into email. * * @param[in,out] message Message body. @@ -300,47 +202,6 @@ QString fromBase64(const QString &base64); /*! - * @brief Convert state box to text - * - * @param[in] value databox status value. - * @return Databox status string. - */ -QString getdbStateText(int value); - -/*! - * @brief Get/create WebDatovka (MojeId) username. - * - * @param[in] userId Wedatovka user ID. - * @param[in] accountId Wedatovka account ID. - * @return Username of account. - */ -QString getWebDatovkaUsername(const QString &userId, const QString &accountId); - -/*! - * Get account id from username of WebDatovka account. - * - * @param[in] userName Account user name. - * @return Account id of webdatovka account. - */ -int getWebDatovkaAccountId(const QString &userName); - -/*! - * Get user id from username of WebDatovka account. - * - * @param[in] userName Account user name. - * @return user id of webdatovka account. - */ -int getWebDatovkaUserId(const QString &userName); - -/*! - * Get name prefix of tag database from username (WebDatovka). - * - * @param[in] userName Account user name. - * @return tag database prefix of webdatovka account. - */ -QString getWebDatovkaTagDbPrefix(const QString &userName); - -/*! * @brief Check valid database filename. * * @param[in] inDbFileName Input database file name. @@ -354,22 +215,6 @@ QString &dbYear, bool &dbTestingFlag, QString &errMsg); /*! - * @brief Test if selected account is WebDatovka (MojeId) account. - * - * @param[in] userName Account user name. - * @return true if account is webdatovka account. - */ -bool isWebDatovkaAccount(const QString &userName); - -/*! - * @brief Returns message status description. - * - * @param[in] status Message status value. - * @return message status description. - */ -const QString msgStatusToText(int status); - -/*! * @brief Converts string to base64. * * @param[in] plain Plain input string. diff -Nru datovka-4.8.3/src/delegates/tag_item.cpp datovka-4.9.3/src/delegates/tag_item.cpp --- datovka-4.8.3/src/delegates/tag_item.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/delegates/tag_item.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -23,34 +23,22 @@ #include /* std::sort */ #include -#include #include "src/delegates/tag_item.h" #include "src/dimensions/dimensions.h" #include "src/localisation/localisation.h" #include "src/log/log.h" -#define DFLT_COLOUR "ffffff" - TagItem::TagItem(void) - : id(-1), - name(), - colour(DFLT_COLOUR) + : TagDb::TagEntry() { } -TagItem::TagItem(int i, const QString &n, const QString &c) - : id(i), - name(n), - colour(isValidColourStr(c) ? c : DFLT_COLOUR) +TagItem::TagItem(const TagDb::TagEntry &entry) + : TagDb::TagEntry(entry) { } -bool TagItem::isValid(void) const -{ - return (id >= 0) && !name.isEmpty() && (6 == colour.size()); -} - int TagItem::paint(class QPainter *painter, const QStyleOptionViewItem &option) const { @@ -121,13 +109,6 @@ return QSize(width, height); } -bool TagItem::isValidColourStr(const QString &colourStr) -{ - QRegExp re("^[a-f0-9]{6,6}$"); - - return re.exactMatch(colourStr); -} - QColor TagItem::adjustForegroundColour(const QColor &fgColour, const QColor &tagColour) { @@ -151,9 +132,12 @@ { } -TagItemList::TagItemList(const QList &tagList) - : QList(tagList) +TagItemList::TagItemList(const QList &tagList) + : QList() { + foreach (const TagDb::TagEntry entry, tagList) { + QList::append(TagItem(entry)); + } } void TagItemList::paint(class QPainter *painter, diff -Nru datovka-4.8.3/src/delegates/tag_item.h datovka-4.9.3/src/delegates/tag_item.h --- datovka-4.8.3/src/delegates/tag_item.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/delegates/tag_item.h 2017-09-06 11:49:23.000000000 +0000 @@ -30,36 +30,25 @@ #include #include +#include "src/io/tag_db.h" + /*! * @brief Describes tag information. */ -class TagItem { +class TagItem : public TagDb::TagEntry { public: /*! * @brief Constructor of invalid tag item. - * - * @note Identifier is -1, has empty name, colour is 'ffffff'; */ TagItem(void); /*! - * @brief Constructs a tag item from supplied parameters. - * - * @param[in] i Tag identifier. - * @param[in] n Tag name. - * @param[in] c Tag colour in hex format without the leading hashtag. - */ - TagItem(int i, const QString &n, const QString &c); - - /*! - * @brief Check for validity. - * - * @note Invalid tag has id equal to -1, empty name and bogus colour. + * @brief Constructor. * - * @return True if tag contains valid data. + * @param[in] entry Tag entry to construct item from. */ - bool isValid(void) const; + explicit TagItem(const TagDb::TagEntry &entry); /*! * @brief Paint tag rectangle. @@ -80,15 +69,6 @@ QSize sizeHint(const QStyleOptionViewItem &option) const; /*! - * @brief Returns true if colour string is valid. - * - * @param[in] colourStr Colour string. - * @return True if colour string is valid. - */ - static - bool isValidColourStr(const QString &colourStr); - - /*! * @brief Adjust foreground colour according to the supplied label * colour. * @@ -99,13 +79,6 @@ static QColor adjustForegroundColour(const QColor &fgColour, const QColor &tagColour); - - int id; /*!< Tag identifier. */ - QString name; /*!< Name of the rag. */ - QString colour; /*!< - * Colour of the tag in hex format without the leading - * hashtag. - */ }; class TagItemList : public QList { @@ -119,9 +92,9 @@ /*! * @brief Constructor. * - * @param[in] tagList List of tag items. + * @param[in] tagList List of tag entries. */ - TagItemList(const QList &tagList); + TagItemList(const QList &tagList); /*! * @brief Paint all list elements. diff -Nru datovka-4.8.3/src/graphics/graphics.cpp datovka-4.9.3/src/graphics/graphics.cpp --- datovka-4.8.3/src/graphics/graphics.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/graphics/graphics.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include + +#include "src/graphics/graphics.h" + +QPixmap Graphics::pixmapFromSvg(const QByteArray &svgData, int edgeLen) +{ + if (svgData.isEmpty()) { + return QPixmap(); + } + + QSvgRenderer renderer; + if (!renderer.load(svgData)) { + return QPixmap(); + } + + QImage image(edgeLen, edgeLen, QImage::Format_ARGB32); + QPainter painter(&image); + renderer.render(&painter); + + QPixmap pixmap; + pixmap.convertFromImage(image); + + return pixmap; +} diff -Nru datovka-4.8.3/src/graphics/graphics.h datovka-4.9.3/src/graphics/graphics.h --- datovka-4.8.3/src/graphics/graphics.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/graphics/graphics.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _GRAPHICS_H_ +#define _GRAPHICS_H_ + +#include +#include + +/*! + * @brief Encapsulates some graphics-related routines. + */ +class Graphics { +public: + /*! + * @brief Draws a pixmap from supplied SVG data. + * + * @param[in] svgData SVG image data. + * @param[in] edgeLen Edge size of the drawn image square. + * @return Null pixmap on error. + */ + static + QPixmap pixmapFromSvg(const QByteArray &svgData, int edgeLen); + +private: + /*! + * @brief Private constructor. + */ + Graphics(void); +}; + +#endif /* _GRAPHICS_H_ */ diff -Nru datovka-4.8.3/src/gui/datovka.cpp datovka-4.9.3/src/gui/datovka.cpp --- datovka-4.8.3/src/gui/datovka.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/datovka.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -50,12 +50,11 @@ #include "src/gui/dlg_change_pwd.h" #include "src/gui/dlg_account_from_db.h" #include "src/gui/dlg_create_account.h" -#include "src/gui/dlg_login_mojeid.h" #include "src/gui/dlg_signature_detail.h" #include "src/gui/dlg_change_directory.h" #include "src/gui/dlg_correspondence_overview.h" #include "src/gui/dlg_ds_search.h" -#include "src/gui/dlg_search_mojeid.h" +#include "src/gui/dlg_msg_box_informative.h" #include "src/gui/dlg_msg_search.h" #include "src/gui/dlg_preferences.h" #include "src/gui/dlg_proxysets.h" @@ -77,29 +76,27 @@ #include "src/io/message_db_single.h" #include "src/io/message_db_set_container.h" #include "src/io/tag_db.h" -#include "src/io/tag_db_container.h" -#include "src/io/wd_sessions.h" +#include "src/isds/isds_conversion.h" +#include "src/model_interaction/account_interaction.h" #include "src/model_interaction/attachment_interaction.h" -#include "src/models/files_model.h" +#include "src/records_management/gui/dlg_records_management.h" +#include "src/records_management/gui/dlg_records_management_stored.h" +#include "src/records_management/gui/dlg_records_management_upload.h" +#include "src/settings/records_management.h" #include "src/views/table_home_end_filter.h" #include "src/views/table_key_press_filter.h" #include "src/worker/message_emitter.h" #include "src/worker/pool.h" #include "src/worker/task_authenticate_message.h" -#include "src/worker/task_erase_message.h" #include "src/worker/task_download_message.h" #include "src/worker/task_download_message_list.h" -#include "src/worker/task_download_message_list_mojeid.h" -#include "src/worker/task_download_message_mojeid.h" -#include "src/worker/task_sync_mojeid.h" -#include "src/worker/task_tag_sync_mojeid.h" +#include "src/worker/task_erase_message.h" #include "src/worker/task_download_owner_info.h" #include "src/worker/task_download_password_info.h" #include "src/worker/task_download_user_info.h" #include "src/worker/task_import_zfo.h" #include "src/worker/task_vacuum_db_set.h" #include "src/worker/task_verify_message.h" -#include "src/worker/task_get_account_list_mojeid.h" #include "src/worker/task_split_db.h" #include "ui_datovka.h" @@ -110,7 +107,7 @@ #define WIN_POSITION_H "h" #define WIN_POSITION_MAX "max" -QNetworkAccessManager* nam; +QNetworkAccessManager *nam; /* * If defined then no message table is going to be generated when clicking @@ -118,11 +115,6 @@ */ #define DISABLE_ALL_TABLE 1 -/* - * If defined then adding of mojeID account will be inaccessible. - */ -#define DISABLE_MOJEID_ACCOUNT_ADDING 1 - /*! * @brief Returns QModelIndex of the currently selected account model node. */ @@ -150,6 +142,41 @@ (ui->messageAttachmentList->selectionModel()->selectedRows(0)) /*! + * @brief Return index for message with given properties. + * + * @param[in] view Message table view. + * @param[in] dmId Message identifier. + * @return Index of given message. + */ +static inline +QModelIndex messageIndex(const QTableView *view, qint64 dmId) +{ + if (Q_UNLIKELY((Q_NULLPTR == view) || (dmId < 0))) { + Q_ASSERT(0); + return QModelIndex(); + } + + const QAbstractItemModel *model = view->model(); + if (Q_UNLIKELY(Q_NULLPTR == model)) { + Q_ASSERT(0); + return QModelIndex(); + } + + /* Find and select the message with the ID. */ + for (int row = 0; row < model->rowCount(); ++row) { + /* + * TODO -- Search in a more resource-saving way. + * Eliminate index copying, use smarter search. + */ + if (model->index(row, 0).data().toLongLong() == dmId) { + return model->index(row, 0); + } + } + + return QModelIndex(); +} + +/*! * @brief Message identifier from index. * * @param[in] msgIdx Index into the message table view. @@ -260,7 +287,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), m_accountModel(this), + m_messageTableModel(DbMsgsTblModel::WORKING_RCVD, this), m_messageListProxyModel(this), + m_attachmentModel(this), m_messageMarker(this), m_lastSelectedMessageId(-1), m_lastStoredMessageId(-1), @@ -283,7 +312,6 @@ m_msgTblAppendedCols(), ui(new Ui::MainWindow), mui_filterLine(0), - mui_clearFilterLineButton(0), mui_statusBar(0), mui_statusDbMode(0), mui_statusOnlineLabel(0), @@ -291,9 +319,12 @@ { setUpUi(); - if (0 != globTagDbPtr) { - m_msgTblAppendedCols.append(tr("Tags")); - } + m_msgTblAppendedCols.append(DbMsgsTblModel::AppendedCol( + QString(), QIcon(ICON_3PARTY_PATH "briefcase_grey_16.png"), + tr("Uploaded to records management service"))); + + m_msgTblAppendedCols.append(DbMsgsTblModel::AppendedCol( + tr("Tags"), QIcon(), tr("User-assigned tags"))); /* Single instance emitter. */ connect(&globSingleInstanceEmitter, SIGNAL(messageReceived(QString)), @@ -307,12 +338,6 @@ SLOT(collectDownloadMessageStatus(QString, qint64, QDateTime, int, QString, bool))); connect(&globMsgProcEmitter, - SIGNAL(downloadMessageFinishedMojeId(QString, qint64, int, - QString, bool)), - this, - SLOT(collectDownloadMessageMojeId(QString, qint64, int, - QString, bool))); - connect(&globMsgProcEmitter, SIGNAL(downloadMessageListFinished(QString, int, int, QString, bool, int, int, int, int)), this, SLOT(collectDownloadMessageListStatus(QString, int, int, QString, @@ -333,9 +358,6 @@ SLOT(collectSendMessageStatus(QString, QString, int, QString, QString, QString, bool, qint64))); connect(&globMsgProcEmitter, - SIGNAL(sendMessageMojeIdFinished(QString, QStringList, QString)), - this, SLOT(sendMessageMojeIdAction(QString, QStringList, QString))); - connect(&globMsgProcEmitter, SIGNAL(refreshAccountList(QString)), this, SLOT(refreshAccountList(QString))); @@ -463,6 +485,10 @@ mui_statusDbMode->setText(tr("Storage:") + " " + msgStrg + " | " + acntStrg + " "); + + /* TODO -- This is only a temporary solution. */ + ui->actionUpdate_records_management_information->setEnabled( + globRecordsManagementSet.isSet()); } void MainWindow::setWindowsAfterInit(void) @@ -636,6 +662,77 @@ dlgProxy->deleteLater(); } +/*! + * @brief Shows all columns except the supplied ones. + * + * @param[in] view Table view. + * @param[in] cols List of negative column indexes. + */ +static +void showAllColumnsExcept(QTableView *view, QList cols) +{ + if (Q_NULLPTR == view) { + Q_ASSERT(0); + return; + } + + QAbstractItemModel *model = view->model(); + if (Q_NULLPTR == model) { + return; + } + + for (int col = 0; col < model->columnCount(); ++col) { + view->setColumnHidden(col, false); + } + + foreach (int negCol, cols) { + int col = model->columnCount() + negCol; + if ((col < 0) || (col >= model->columnCount())) { + Q_ASSERT(0); + continue; + } + view->setColumnHidden(col, true); + } +} + +/*! + * @brief Shows/hides message table columns according to functionality. + * + * @param[in] view Table view. + */ +static +void showColumnsAccordingToFunctionality(QTableView *view) +{ + QList negCols; + + if (!globRecordsManagementSet.isSet()) { + negCols.append(DbMsgsTblModel::REC_MGMT_NEG_COL); + } + + showAllColumnsExcept(view, negCols); +} + +void MainWindow::showRecordsManagementDialogue(void) +{ + debugSlotCall(); + + if (DlgRecordsManagement::updateSettings(globRecordsManagementSet, + this)) { + saveSettings(); + } + + ui->actionUpdate_records_management_information->setEnabled( + globRecordsManagementSet.isSet()); + + m_messageTableModel.setRecordsManagementIcon(); + m_messageTableModel.fillRecordsManagementColumn( + DbMsgsTblModel::REC_MGMT_NEG_COL); + + showColumnsAccordingToFunctionality(ui->messageList); + AccountModel::nodeTypeIsReceived(currentAccountModelIndex()) ? + setReceivedColumnWidths() : setSentColumnWidths(); +} + /* ========================================================================= */ /* * Redraws widgets according to selected account item. @@ -649,7 +746,6 @@ Q_UNUSED(previous); QString html; - QAbstractTableModel *msgTblMdl = 0; if (!current.isValid()) { /* May occur on deleting last account. */ @@ -668,7 +764,7 @@ SLOT(messageItemRestoreSelectionAfterLayoutChange())); /* Decouple model and show banner page. */ - ui->messageList->setModel(0); + ui->messageList->setModel(Q_NULLPTR); ui->messageStackedWidget->setCurrentIndex(0); ui->accountTextInfo->setHtml(createDatovkaBanner( QCoreApplication::applicationVersion())); @@ -678,9 +774,13 @@ const QString userName(m_accountModel.userName(current)); - Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + if (userName.isEmpty()) { + logErrorNL("%s", "Have empty user name."); +// Q_ASSERT(0); + return; + } + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { /* May occur on deleting last account. */ setMessageActionVisibility(0); @@ -697,8 +797,7 @@ SLOT(messageItemRestoreSelectionAfterLayoutChange())); /* Get user name and db location. */ - const AcntSettings &itemSettings( - AccountModel::globAccounts[userName]); + const AcntSettings &itemSettings(globAccounts[userName]); QString dbDir = itemSettings.dbDir(); if (dbDir.isEmpty()) { @@ -707,13 +806,13 @@ } /* Decouple model and show banner page. */ - ui->messageList->setModel(0); + ui->messageList->setModel(Q_NULLPTR); ui->messageStackedWidget->setCurrentIndex(0); QString htmlMessage = "
    " "

    " + tr("Database access error") + "

    " "
    "; htmlMessage += "
    "; htmlMessage += tr("Database files for account '%1' cannot be accessed in location '%2'." - ).arg(userName).arg(dbDir); + ).arg(userName.toHtmlEscaped()).arg(dbDir.toHtmlEscaped()); htmlMessage += "
    "; htmlMessage += tr("The file cannot be accessed or is " "corrupted. Please fix the access privileges or " @@ -740,6 +839,11 @@ ui->messageList->disconnect(SIGNAL(clicked(QModelIndex)), this, SLOT(messageItemClicked(QModelIndex))); + m_messageTableModel.removeRows(0, m_messageTableModel.rowCount()); + m_messageListProxyModel.setSourceModel(&m_messageTableModel); /* TODO */ + m_messageListProxyModel.setSortRole(ROLE_MSGS_DB_PROXYSORT); /* TODO */ + ui->messageList->setModel(&m_messageListProxyModel); /* TODO */ + switch (AccountModel::nodeType(current)) { case AccountModel::nodeAccountTop: setMessageActionVisibility(0); @@ -747,16 +851,20 @@ ui->actionDelete_message_from_db->setEnabled(false); break; case AccountModel::nodeRecentReceived: - msgTblMdl = dbSet->msgsRcvdWithin90DaysModel( - m_msgTblAppendedCols); + m_messageTableModel.appendData( + dbSet->msgsRcvdEntriesWithin90Days(), + m_msgTblAppendedCols.size()); + m_messageTableModel.setRcvdHeader(m_msgTblAppendedCols); //ui->messageList->horizontalHeader()->moveSection(5,3); ui->actionDelete_message_from_db->setEnabled(false); connect(ui->messageList, SIGNAL(clicked(QModelIndex)), this, SLOT(messageItemClicked(QModelIndex))); break; case AccountModel::nodeRecentSent: - msgTblMdl = dbSet->msgsSntWithin90DaysModel( - m_msgTblAppendedCols); + m_messageTableModel.appendData( + dbSet->msgsSntEntriesWithin90Days(), + m_msgTblAppendedCols.size()); + m_messageTableModel.setSntHeader(m_msgTblAppendedCols); ui->actionDelete_message_from_db->setEnabled(false); break; case AccountModel::nodeAll: @@ -777,7 +885,9 @@ MessageDb::TYPE_RECEIVED); ui->actionDelete_message_from_db->setEnabled(false); #else /* !DISABLE_ALL_TABLE */ - msgTblMdl = dbSet->msgsRcvdModel(m_msgTblAppendedCols); + m_messageTableModel.appendData(dbSet->msgsEntriesRcvd(), + m_msgTblAppendedCols.size()); + m_messageTableModel.setRcvdHeader(m_msgTblAppendedCols); ui->actionDelete_message_from_db->setEnabled(true); connect(ui->messageList, SIGNAL(clicked(QModelIndex)), this, SLOT(messageItemClicked(QModelIndex))); @@ -792,35 +902,45 @@ MessageDb::TYPE_SENT); ui->actionDelete_message_from_db->setEnabled(false); #else /* !DISABLE_ALL_TABLE */ - msgTblMdl = dbSet->msgsSntModel(m_msgTblAppendedCols); + m_messageTableModel.appendData(dbSet->msgsSntEntries(), + m_msgTblAppendedCols.size()); + m_messageTableModel.setSntHeader(m_msgTblAppendedCols); ui->actionDelete_message_from_db->setEnabled(true); #endif /* DISABLE_ALL_TABLE */ break; case AccountModel::nodeReceivedYear: + m_messageTableModel.appendData( + dbSet->msgsRcvdEntriesInYear( + current.data(ROLE_PLAIN_DISPLAY).toString()), + m_msgTblAppendedCols.size()); + m_messageTableModel.setRcvdHeader(m_msgTblAppendedCols); /* TODO -- Parameter check. */ - msgTblMdl = dbSet->msgsRcvdInYearModel( - current.data(ROLE_PLAIN_DISPLAY).toString(), - m_msgTblAppendedCols); ui->actionDelete_message_from_db->setEnabled(true); connect(ui->messageList, SIGNAL(clicked(QModelIndex)), this, SLOT(messageItemClicked(QModelIndex))); break; case AccountModel::nodeSentYear: + m_messageTableModel.appendData( + dbSet->msgsSntEntriesInYear( + current.data(ROLE_PLAIN_DISPLAY).toString()), + m_msgTblAppendedCols.size()); + m_messageTableModel.setSntHeader(m_msgTblAppendedCols); /* TODO -- Parameter check. */ - msgTblMdl = dbSet->msgsSntInYearModel( - current.data(ROLE_PLAIN_DISPLAY).toString(), - m_msgTblAppendedCols); ui->actionDelete_message_from_db->setEnabled(true); break; default: - Q_ASSERT(0); + logErrorNL("%s", "Cannot determine account node type."); +// Q_ASSERT(0); + return; break; } - if (0 != msgTblMdl) { - DbMsgsTblModel *mdl = dynamic_cast(msgTblMdl); - Q_ASSERT(0 != mdl); - mdl->fillTagsColumn(userName, -1); + { + m_messageTableModel.setRecordsManagementIcon(); + m_messageTableModel.fillRecordsManagementColumn( + DbMsgsTblModel::REC_MGMT_NEG_COL); + m_messageTableModel.fillTagsColumn(userName, + DbMsgsTblModel::TAGS_NEG_COL); /* TODO -- Add some labels. */ } @@ -871,10 +991,7 @@ #endif /* !DISABLE_ALL_TABLE */ case AccountModel::nodeReceivedYear: /* Set model. */ - Q_ASSERT(0 != msgTblMdl); - m_messageListProxyModel.setSortRole(ROLE_MSGS_DB_PROXYSORT); - m_messageListProxyModel.setSourceModel(msgTblMdl); - ui->messageList->setModel(&m_messageListProxyModel); + showColumnsAccordingToFunctionality(ui->messageList); /* Set specific column width. */ setReceivedColumnWidths(); received = true; @@ -885,10 +1002,7 @@ #endif /* !DISABLE_ALL_TABLE */ case AccountModel::nodeSentYear: /* Set model. */ - Q_ASSERT(0 != msgTblMdl); - m_messageListProxyModel.setSortRole(ROLE_MSGS_DB_PROXYSORT); - m_messageListProxyModel.setSourceModel(msgTblMdl); - ui->messageList->setModel(&m_messageListProxyModel); + showColumnsAccordingToFunctionality(ui->messageList); /* Set specific column width. */ setSentColumnWidths(); received = false; @@ -916,7 +1030,7 @@ /* Select last message in list if there are some messages. */ itemModel = ui->messageList->model(); /* enable/disable buttons */ - if ((0 != itemModel) && (0 < itemModel->rowCount())) { + if ((Q_NULLPTR != itemModel) && (0 < itemModel->rowCount())) { messageItemRestoreSelectionOnModelChange(); ui->actionAuthenticate_message_file->setEnabled(true); ui->actionExport_correspondence_overview-> @@ -928,7 +1042,9 @@ } break; default: - Q_ASSERT(0); + logErrorNL("%s", "Cannot determine account node type."); +// Q_ASSERT(0); + return; break; } @@ -1025,10 +1141,6 @@ menu->addAction(ui->actionImport_ZFO_file_into_database); } else { menu->addAction(ui->actionAdd_account); - menu->addAction(ui->actionAdd_mojeID_account); -#ifdef DISABLE_MOJEID_ACCOUNT_ADDING - ui->actionAdd_mojeID_account->setVisible(false); -#endif /* DISABLE_MOJEID_ACCOUNT_ADDING */ } menu->exec(QCursor::pos()); @@ -1100,8 +1212,8 @@ } MessageDbSet *dbSet = accountDbSet( - m_accountModel.userName(currentAccountModelIndex()), this); - if (0 == dbSet) { + m_accountModel.userName(currentAccountModelIndex())); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -1132,7 +1244,7 @@ } /* Generate and show message information. */ - ui->messageInfo->setHtml(messageDb->descriptionHtml(msgId.dmId, 0)); + ui->messageInfo->setHtml(messageDb->descriptionHtml(msgId.dmId)); ui->messageInfo->setReadOnly(true); if (received) { @@ -1152,9 +1264,10 @@ } /* Show files related to message message. */ - QAbstractTableModel *fileTblMdl = messageDb->flsModel(msgId.dmId); - Q_ASSERT(0 != fileTblMdl); - ui->messageAttachmentList->setModel(fileTblMdl); + m_attachmentModel.removeRows(0, m_attachmentModel.rowCount()); + m_attachmentModel.setHeader(); + m_attachmentModel.appendData(messageDb->attachEntries(msgId.dmId)); + ui->messageAttachmentList->setModel(&m_attachmentModel); /* First three columns contain hidden data. */ ui->messageAttachmentList->setColumnHidden( DbFlsTblModel::ATTACHID_COL, true); @@ -1201,8 +1314,8 @@ m_messageMarker.stop(); MessageDbSet *dbSet = accountDbSet( - m_accountModel.userName(currentAccountModelIndex()), this); - if (0 == dbSet) { + m_accountModel.userName(currentAccountModelIndex())); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -1224,11 +1337,7 @@ * Mark message as read without reloading * the whole model. */ - DbMsgsTblModel *messageModel = dynamic_cast( - m_messageListProxyModel.sourceModel()); - Q_ASSERT(0 != messageModel); - - messageModel->overrideRead(msgId.dmId, !isRead); + m_messageTableModel.overrideRead(msgId.dmId, !isRead); /* * Reload/update account model only for @@ -1298,6 +1407,8 @@ menu->addAction(ui->actionOpen_message_externally); menu->addAction(ui->actionOpen_delivery_info_externally); menu->addSeparator(); + menu->addAction(ui->actionSend_to_records_management); + menu->addSeparator(); } menu->addAction(ui->actionExport_as_ZFO); menu->addAction(ui->actionExport_delivery_info_as_ZFO); @@ -1365,8 +1476,8 @@ MessageDb::MsgId msgId(msgMsgId(msgIndex)); Q_ASSERT(msgId.dmId >= 0); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -1436,7 +1547,7 @@ const QString userName(m_accountModel.userName(acntIdx)); Q_ASSERT(!userName.isEmpty()); - AccountModel::globAccounts[userName].setLastMsg(msgId); + globAccounts[userName].setLastMsg(msgId); } } @@ -1446,7 +1557,7 @@ Q_ASSERT(!userName.isEmpty()); - AcntSettings &accountInfo(AccountModel::globAccounts[userName]); + AcntSettings &accountInfo(globAccounts[userName]); accountInfo.setLastAttachSavePath(m_save_attach_dir); accountInfo.setLastAttachAddPath(m_add_attach_dir); accountInfo.setLastCorrespPath(m_export_correspond_dir); @@ -1557,8 +1668,7 @@ m_accountModel.userName(acntIdx)); Q_ASSERT(!userName.isEmpty()); - msgLastId = AccountModel::globAccounts[userName] - .lastMsg(); + msgLastId = globAccounts[userName].lastMsg(); } else { msgLastId = m_lastStoredMessageId; } @@ -1692,41 +1802,6 @@ return yearIdx; } - -/* ========================================================================= */ -/* - * Return index for message with given properties. - */ -QModelIndex MainWindow::messageIndex(qint64 msgId) const -/* ========================================================================= */ -{ - debugFuncCall(); - - const QAbstractItemModel *model = ui->messageList->model(); - Q_ASSERT(0 != model); - - int rowCount = model->rowCount(); - - if (0 == rowCount) { - /* Do nothing on empty model. */ - return QModelIndex(); - } - - /* Find and select the message with the ID. */ - for (int row = 0; row < rowCount; ++row) { - /* - * TODO -- Search in a more resource-saving way. - * Eliminate index copying, use smarter search. - */ - if (model->index(row, 0).data().toLongLong() == msgId) { - return model->index(row, 0); - } - } - - return QModelIndex(); -} - - /* ========================================================================= */ /* * Select account via userName and focus on message ID from search selection. @@ -1753,8 +1828,7 @@ accountItemCurrentChanged(yearIdx); /* second step: find and select message according to msgId */ - QModelIndex msgIdx(messageIndex(msgId)); - + QModelIndex msgIdx(messageIndex(ui->messageList, msgId)); if (msgIdx.isValid()) { ui->messageList->setCurrentIndex(msgIdx); ui->messageList->scrollTo(msgIdx); @@ -1868,7 +1942,7 @@ const QString dbId( globAccountDbPtr->dbId(AccountDb::keyFromLogin(userName))); - MessageDbSet *dbSet = accountDbSet(userName, this); + MessageDbSet *dbSet = accountDbSet(userName); if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; @@ -1922,7 +1996,7 @@ const QString dbId( globAccountDbPtr->dbId(AccountDb::keyFromLogin(userName))); - MessageDbSet *dbSet = accountDbSet(userName, this); + MessageDbSet *dbSet = accountDbSet(userName); if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; @@ -2040,66 +2114,18 @@ } else { /* Notify the user. */ if (!listScheduled) { - QMessageBox msgBox(this); - showStatusTextWithTimeout(tr("It was not possible download " "complete message \"%1\" from ISDS server.").arg(msgId)); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setWindowTitle(tr("Download message error")); - msgBox.setText(tr("It was not possible to download a complete " - "message \"%1\" from server Datové schránky.").arg(msgId)); - if (!errDesc.isEmpty()) { - msgBox.setInformativeText(tr("ISDS: ") + errDesc); - } else { - msgBox.setInformativeText(tr("A connection error " - "occurred or the message has already been deleted " - "from the server.")); - } - - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); - } else { - showStatusTextWithTimeout( - tr("Couldn't download message '%1'.").arg(msgId)); - } - } -} - -void MainWindow::collectDownloadMessageMojeId(const QString &usrName, - qint64 msgId, int result, const QString &errDesc, bool listScheduled) -{ - debugSlotCall(); - - if (TaskDownloadMessageMojeId::DM_SUCCESS == result) { - /* Refresh account and attachment list. */ - refreshAccountList(usrName); - if (0 <= msgId) { - postDownloadSelectedMessageAttachments(usrName, msgId); - } - } else { - /* Notify the user. */ - if (!listScheduled) { - QMessageBox msgBox(this); - - showStatusTextWithTimeout(tr("It was not possible download " - "complete message \"%1\" from webdatovka server.").arg(msgId)); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setWindowTitle(tr("Download message error")); - msgBox.setText(tr("It was not possible to download a complete " - "message \"%1\" from webdatovka server.").arg(msgId)); - if (!errDesc.isEmpty()) { - msgBox.setInformativeText(tr("Webdatovka: ") + errDesc); - } else { - msgBox.setInformativeText(tr("A connection error " - "occurred or the message has already been deleted " - "from the server.")); - } - - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); + QString infoText(!errDesc.isEmpty() ? + tr("ISDS") + QLatin1String(": ") + errDesc : + tr("A connection error occurred or the message has already been deleted from the server.")); + DlgMsgBox::message(this, QMessageBox::Warning, + tr("Download message error"), + tr("It was not possible to download a complete message \"%1\" from ISDS server.") + .arg(msgId), + infoText, QString(), QMessageBox::Ok, + QMessageBox::Ok); } else { showStatusTextWithTimeout( tr("Couldn't download message '%1'.").arg(msgId)); @@ -2120,8 +2146,6 @@ if (TaskDownloadMessageList::DL_SUCCESS != result) { /* Notify the user. */ - QMessageBox msgBox(this); - QString errorMessage = (MSG_RECEIVED == direction) ? tr("It was not possible download received message list from" " server.") : @@ -2129,19 +2153,13 @@ " server."); showStatusTextWithTimeout(errorMessage); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setWindowTitle(tr("Download message list error")); - msgBox.setText(errorMessage); - if (!errDesc.isEmpty()) { - msgBox.setInformativeText(tr("Server: ") + errDesc); - } else { - msgBox.setInformativeText( - tr("A connection error occurred.")); - } - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); + QString infoText(!errDesc.isEmpty() ? + tr("Server") + QLatin1String(": ") + errDesc : + tr("A connection error occurred.")); + DlgMsgBox::message(this, QMessageBox::Warning, + tr("Download message list error"), errorMessage, infoText, + QString(), QMessageBox::Ok, QMessageBox::Ok); } } @@ -2205,7 +2223,7 @@ if (TaskSendMessage::SM_SUCCESS == result) { showStatusTextWithTimeout(tr( "Message from '%1' (%2) has been successfully sent to '%3' (%4)."). - arg(AccountModel::globAccounts[userName].accountName()). + arg(globAccounts[userName].accountName()). arg(userName).arg(recipientName).arg(dbIDRecipient)); /* Refresh account list. */ @@ -2213,7 +2231,7 @@ } else { showStatusTextWithTimeout(tr( "Error while sending message from '%1' (%2) to '%3' (%4)."). - arg(AccountModel::globAccounts[userName].accountName()). + arg(globAccounts[userName].accountName()). arg(userName).arg(recipientName).arg(dbIDRecipient)); } @@ -2245,13 +2263,10 @@ return; } - DbMsgsTblModel *messageModel = dynamic_cast( - m_messageListProxyModel.sourceModel()); - Q_ASSERT(0 != messageModel); QModelIndex msgIdIdx; /* Find corresponding message in model. */ - for (int row = 0; row < messageModel->rowCount(); ++row) { - QModelIndex index = messageModel->index(row, 0); + for (int row = 0; row < m_messageTableModel.rowCount(); ++row) { + QModelIndex index = m_messageTableModel.index(row, 0); if (index.data().toLongLong() == dmId) { msgIdIdx = index; break; @@ -2266,7 +2281,7 @@ * Mark message as having attachment downloaded without reloading * the whole model. */ - messageModel->overrideDownloaded(dmId, true); + m_messageTableModel.overrideDownloaded(dmId, true); QItemSelection storedMsgSelection = ui->messageList->selectionModel()->selection(); ui->messageList->selectionModel()->select(storedMsgSelection, @@ -2293,8 +2308,8 @@ } MessageDbSet *dbSet = accountDbSet( - m_accountModel.userName(currentAccountModelIndex()), this); - if (0 == dbSet) { + m_accountModel.userName(currentAccountModelIndex())); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -2306,12 +2321,13 @@ } /* Generate and show message information. */ - ui->messageInfo->setHtml(messageDb->descriptionHtml(dmId, 0)); + ui->messageInfo->setHtml(messageDb->descriptionHtml(dmId)); ui->messageInfo->setReadOnly(true); - QAbstractTableModel *fileTblMdl = messageDb->flsModel(dmId); - Q_ASSERT(0 != fileTblMdl); - ui->messageAttachmentList->setModel(fileTblMdl); + m_attachmentModel.removeRows(0, m_attachmentModel.rowCount()); + m_attachmentModel.setHeader(); + m_attachmentModel.appendData(messageDb->attachEntries(dmId)); + ui->messageAttachmentList->setModel(&m_attachmentModel); /* First three columns contain hidden data. */ ui->messageAttachmentList->setColumnHidden( DbFlsTblModel::ATTACHID_COL, true); @@ -2352,9 +2368,8 @@ QModelIndex acntIdx(currentAccountModelIndex()); - MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx), - this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx)); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -2411,9 +2426,8 @@ QModelIndex acntIdx(currentAccountModelIndex()); - MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx), - this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx)); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -2476,9 +2490,8 @@ QModelIndex acntIdx(currentAccountModelIndex()); - MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx), - this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx)); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -2536,9 +2549,8 @@ QModelIndex acntIdx(currentAccountModelIndex()); - MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx), - this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx)); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -2606,9 +2618,8 @@ QModelIndex acntIdx(currentAccountModelIndex()); - MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx), - this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx)); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -2684,9 +2695,8 @@ QModelIndex acntIdx(currentAccountModelIndex()); - MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx), - this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(m_accountModel.userName(acntIdx)); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -2811,7 +2821,7 @@ /* ========================================================================= */ /* - * Delete selected message from local database and ISDS/Webdatovka. + * Delete selected message from local database and ISDS. */ void MainWindow::deleteMessage(void) /* ========================================================================= */ @@ -2825,11 +2835,6 @@ return; } - if (isWebDatovkaAccount(userName)) { - deleteMessageWebdatovka(userName); - return; - } - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); if (firstMsgColumnIdxs.isEmpty()) { @@ -2903,114 +2908,6 @@ refreshAccountList(userName); } - -/* ========================================================================= */ -/* - * Func: Delete selected message from local database and Webdatovka. - */ -void MainWindow::deleteMessageWebdatovka(const QString &userName) -/* ========================================================================= */ -{ - debugFuncCall(); - - if (!wdSessions.isConnectedToWebdatovka(userName)) { - showWebDatovkaInfoDialog(userName, - tr("You have to be logged into the Webdatovka " - "if you want to delete message(s).")); - return; - } - - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - if (firstMsgColumnIdxs.isEmpty()) { - return; - } - - QString dlgTitleText, questionText, detailText; - int msgIdxCnt = firstMsgColumnIdxs.size(); - - if (1 == msgIdxCnt) { - qint64 dmId = firstMsgColumnIdxs.first().data().toLongLong(); - dlgTitleText = tr("Delete message %1").arg(dmId); - questionText = tr("Do you want to delete " - "message '%1'?").arg(dmId); - detailText = tr("Warning: If you delete the message " - "from Webdatovka then this message will be lost forever."); - } else { - dlgTitleText = tr("Delete messages"); - questionText = tr("Do you want to delete selected messages?"); - detailText = tr("Warning: If you delete selected messages " - "from Webdatovka then these messages will be lost forever."); - } - - QMessageBox msgBox(this); - msgBox.setIcon(QMessageBox::Question); - msgBox.setWindowTitle(dlgTitleText); - msgBox.setText(questionText); - msgBox.setInformativeText(detailText); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - if (QMessageBox::No == msgBox.exec()) { - return; - } - - QList msgIds; - foreach (const QModelIndex &idx, firstMsgColumnIdxs) { - msgIds.append(MessageDb::MsgId(idx.data().toLongLong(), - msgDeliveryTime(idx))); - } - - /* Save current account index */ - QModelIndex selectedAcntIndex(currentAccountModelIndex()); - - MessageDbSet *dbSet = accountDbSet(userName, this); - if (Q_NULLPTR == dbSet) { - Q_ASSERT(0); - return; - } - - QString errStr; - foreach (const MessageDb::MsgId &id, msgIds) { - MessageDb *messageDb = - dbSet->accessMessageDb(id.deliveryTime, false); - if (messageDb == Q_NULLPTR) { - Q_ASSERT(0); - return; - } - if (!jsonlayer.deleteMessage(userName, - messageDb->getWebDatokaId(id.dmId), errStr)) { - qDebug() << "WD_DELETE_MESSAGE_ERROR:" << id.dmId - << errStr; - continue; - } - if (eraseMessage(userName, id, false)) { - /* - * Hiding selected line in the message model actually - * does not help. The model contains all the old data - * and causes problems. Therefore the model must be - * regenerated. - */ - if (selectedAcntIndex.isValid()) { - accountItemCurrentChanged(selectedAcntIndex); - } - /* - * TODO -- Remove the year on account list if last - * message was removed. - */ - - /* Delete all tags from message_tags table. - * Tag in the tag table are kept. - */ - TagDb *tagDb = - globWebDatovkaTagDbPtr->accessTagDb(userName); - tagDb->removeAllTagsFromMsg(userName, id.dmId); - } - } - - /* Refresh account list. */ - refreshAccountList(userName); -} - - /* ========================================================================= */ /* * Delete message from long term storage in ISDS and @@ -3024,8 +2921,8 @@ Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return false; } @@ -3164,17 +3061,10 @@ Q_ASSERT(!userName.isEmpty()); /* Skip those that should omitted. */ - if (!AccountModel::globAccounts[userName].syncWithAll()) { + if (!globAccounts[userName].syncWithAll()) { continue; } - // webdatovka sync - if (isWebDatovkaAccount(userName)) { - synchroniseSelectedAccount(userName); - continue; - } - - /* Try connecting to ISDS, just to generate log-in dialogue. */ if (!globIsdsSessions.isConnectedToIsds(userName) && !connectToIsds(userName)) { @@ -3214,13 +3104,8 @@ Q_ASSERT(!userName.isEmpty()); } - // webdatovka sync - if (isWebDatovkaAccount(userName)) { - return wdSyncAccount(userName); - } - - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { return false; } @@ -3284,13 +3169,7 @@ return true; } - -/* ========================================================================= */ -/* - * Downloads the attachments for the selected message. - */ void MainWindow::downloadSelectedMessageAttachments(void) -/* ========================================================================= */ { debugSlotCall(); @@ -3305,63 +3184,34 @@ const QString userName(m_accountModel.userName(acntIdx)); Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); + MessageDbSet *dbSet = accountDbSet(userName); if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } + if (!globIsdsSessions.isConnectedToIsds(userName) && + !connectToIsds(userName)) { + return; + } - if (isWebDatovkaAccount(userName)) { - if (!wdSessions.isConnectedToWebdatovka(userName)) { - loginToMojeId(userName); - } - - if (!wdSessions.isConnectedToWebdatovka(userName)) { - showWebDatovkaInfoDialog(userName, - tr("You have to be logged into the WebDatovka " - "if you want to download complete message.")); - return; - } - - foreach (const MessageDb::MsgId &id, msgMsgIds(firstMsgColumnIdxs)) { - /* Using prepend() just to outrun other jobs. */ - MessageDb *messageDb = dbSet->accessMessageDb(id.deliveryTime, false); - if (messageDb == Q_NULLPTR) { - Q_ASSERT(0); - return; - } - int mId = messageDb->getWebDatokaId(id.dmId); - TaskDownloadMessageMojeId *task; - - task = new (std::nothrow) TaskDownloadMessageMojeId( - userName, dbSet, msgDirect, mId, id.dmId, false); - task->setAutoDelete(true); - globWorkPool.assignLo(task, WorkerPool::PREPEND); - } - } else { - - if (!globIsdsSessions.isConnectedToIsds(userName) && - !connectToIsds(userName)) { - return; - } - - ui->actionSync_all_accounts->setEnabled(false); - ui->actionGet_messages->setEnabled(false); + ui->actionSync_all_accounts->setEnabled(false); + ui->actionGet_messages->setEnabled(false); - foreach (const MessageDb::MsgId &id, msgMsgIds(firstMsgColumnIdxs)) { - /* Using prepend() just to outrun other jobs. */ - TaskDownloadMessage *task; - - task = new (std::nothrow) TaskDownloadMessage( - userName, dbSet, msgDirect, id, false); - task->setAutoDelete(true); - globWorkPool.assignLo(task, WorkerPool::PREPEND); + foreach (const MessageDb::MsgId &id, msgMsgIds(firstMsgColumnIdxs)) { + /* Using prepend() just to outrun other jobs. */ + TaskDownloadMessage *task = + new (std::nothrow) TaskDownloadMessage( + userName, dbSet, msgDirect, id, false); + if (Q_UNLIKELY(task == Q_NULLPTR)) { + Q_ASSERT(0); + continue; } + task->setAutoDelete(true); + globWorkPool.assignLo(task, WorkerPool::PREPEND); } } - /* ========================================================================= */ /* * Generate account info HTML message. @@ -3378,21 +3228,17 @@ html.append(indentDivStart); html.append("

    "); - if (isWebDatovkaAccount(userName)) { - html.append(tr("MojeID account")); - html.append("
    \"mojeID\""); + + if (globAccounts[userName].isTestAccount()) { + html.append(tr("Test account")); } else { - if (AccountModel::globAccounts[userName].isTestAccount()) { - html.append(tr("Test account")); - } else { - html.append(tr("Standard account")); - } - html.append("
    \"ISDS\""); + html.append(tr("Standard account")); } + html.append("
    \"ISDS\""); html.append("

    "); html.append(strongAccountInfoLine(tr("Account name"), - AccountModel::globAccounts[userName].accountName())); + globAccounts[userName].accountName())); const QString acntDbKey(AccountDb::keyFromLogin(userName)); if (globAccountDbPtr->dbId(acntDbKey).isEmpty()) { @@ -3431,10 +3277,10 @@ value(key).toInt()))); } } else if (key == "userPrivils") { - html.append(strongAccountInfoLine( + html.append(strongAccountInfoLineNoEscape( userinfTbl.attrProps[key].desc, - convertUserPrivilsToString(userEntry. - value(key).toInt()))); + IsdsConversion::userPrivilsToText( + userEntry.value(key).toInt()))); } else { html.append(strongAccountInfoLine( userinfTbl.attrProps[key].desc, @@ -3446,8 +3292,8 @@ if (key == "userType") { html.append(strongAccountInfoLine( userinfTbl.attrProps[key].desc, - authorTypeToText( - userEntry.value(key).toString()))); + IsdsConversion::senderTypeStrToText( + userEntry.value(key).toString()))); } else { html.append(strongAccountInfoLine( userinfTbl.attrProps[key].desc, @@ -3481,8 +3327,8 @@ if (key == "dbState") { html.append(strongAccountInfoLine( accntinfTbl.attrProps[key].desc, - getdbStateText( - accountEntry.value(key).toInt()))); + IsdsConversion::boxStateToText( + accountEntry.value(key).toInt()))); } else if (key == "ic") { if (accountEntry.value(key).toInt() > 0) { html.append(strongAccountInfoLine( @@ -3543,8 +3389,8 @@ html.append(strongAccountInfoLine(tr("Password expiration date"), info)); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return QString(); } @@ -3578,9 +3424,9 @@ /* ========================================================================= */ { QString html = indentDivStart; - html.append ("

    " + accountName + "

    "); + html.append ("

    " + accountName.toHtmlEscaped() + "

    "); - html.append(strongAccountInfoLine(tr("Received messages"), "")); + html.append(strongAccountInfoLine(tr("Received messages"), QString())); html.append(indentDivStart); if (0 == receivedCounts.size()) { html.append(tr("none")); @@ -3594,7 +3440,7 @@ html.append("
    "); - html.append(strongAccountInfoLine(tr("Sent messages"), "")); + html.append(strongAccountInfoLine(tr("Sent messages"), QString())); html.append(indentDivStart); if (0 == sentCounts.size()) { html.append(tr("none")); @@ -3620,12 +3466,12 @@ /* ========================================================================= */ { QString html = indentDivStart; - html.append ("

    " + accountName + "

    "); + html.append ("

    " + accountName.toHtmlEscaped() + "

    "); if (type == MessageDb::TYPE_RECEIVED) { - html.append(strongAccountInfoLine(tr("Received messages"), "")); + html.append(strongAccountInfoLine(tr("Received messages"), QString())); } else { - html.append(strongAccountInfoLine(tr("Sent messages"), "")); + html.append(strongAccountInfoLine(tr("Sent messages"), QString())); } html.append(indentDivStart); if (0 == counts.size()) { @@ -3664,297 +3510,97 @@ return html; } - -/* ========================================================================= */ -/* - * Get message db set related to given account. - */ -MessageDbSet * MainWindow::accountDbSet(const QString &userName, - MainWindow *mw) -/* ========================================================================= */ +MessageDbSet *MainWindow::accountDbSet(const QString &userName) { - MessageDbSet *dbSet = NULL; - int flags, dbPresenceCode; + enum AccountInteraction::AccessStatus status = + AccountInteraction::AS_ERR; + QString dbDir, namesStr; - if (userName.isEmpty()) { - Q_ASSERT(0); - return 0; - } - - /* Get user name and db location. */ - AcntSettings &itemSettings(AccountModel::globAccounts[userName]); - - if (!itemSettings.isValid()) { - logWarning( - "Attempting to accessing database for user name '%s'. " - "The account seems not to exist.\n", - userName.toUtf8().constData()); - return 0; - } - - QString dbDir = itemSettings.dbDir(); - if (dbDir.isEmpty()) { - /* Set default directory name. */ - dbDir = globPref.confDir(); - } + MessageDbSet *dbSet = AccountInteraction::accessDbSet(userName, status, + dbDir, namesStr); - flags = 0; - if (itemSettings.isTestAccount()) { - flags |= MDS_FLG_TESTING; - } - if (itemSettings._createdFromScratch()) { - /* Check database structure on account creation. */ - flags |= MDS_FLG_CHECK_QUICK; - } - dbPresenceCode = - MessageDbSet::checkExistingDbFile(dbDir, userName, flags); + dbDir = QDir::toNativeSeparators(dbDir); - switch (dbPresenceCode) { - case MDS_ERR_OK: - { - if (itemSettings._createdFromScratch()) { - /* Notify the user on account creation. */ - QStringList dbFileNames( - MessageDbSet::existingDbFileNamesInLocation( - dbDir, userName, - itemSettings.isTestAccount(), - MessageDbSet::DO_UNKNOWN, true)); - Q_ASSERT(!dbFileNames.isEmpty()); - QString namesStr("'" + dbFileNames[0] + "'"); - for (int i = 1; i < dbFileNames.size(); ++i) { - namesStr += ", '" + dbFileNames[i] + "'"; - } - logInfo("Database files %s for user name " - "'%s' already present in '%s'.\n", - namesStr.toUtf8().constData(), - userName.toUtf8().constData(), - dbDir.toUtf8().constData()); - if (0 != mw) { - QMessageBox::information(mw, - tr("Datovka: Database file present"), - tr("Database file for account '%1' " - "already exists.").arg(userName) + - "\n\n" + - tr("The existing database files %1 in '%2' are " - "going to be used.").arg(namesStr).arg(dbDir) + - "\n\n" + - tr("If you want to use a new blank file " - "then delete, rename or move the " - "existing file so that the " - "application can create a new empty " - "file."), - QMessageBox::Ok); - } - } - dbSet = globMessageDbsPtr->accessDbSet(dbDir, userName, - itemSettings.isTestAccount(), - MessageDbSet::DO_UNKNOWN, - MessageDbSet::CM_MUST_EXIST); - } - break; - case MDS_ERR_MISSFILE: - { - if (!itemSettings._createdFromScratch()) { - /* Not on account creation. */ - logWarning("Missing database files for " - "user name '%s' in '%s'.\n", - userName.toUtf8().constData(), - dbDir.toUtf8().constData()); - if (0 != mw) { - QMessageBox::warning(mw, - tr("Datovka: Problem loading database"), - tr("Could not load data from the database " - "for account '%1'").arg(userName) + - "\n\n" + - tr("Database files are missing in '%1'.").arg( - dbDir) + - "\n\n" + - tr("I'll try to create an empty one."), - QMessageBox::Ok); - } - } - dbSet = globMessageDbsPtr->accessDbSet(dbDir, userName, - itemSettings.isTestAccount(), - MessageDbSet::DO_YEARLY, - MessageDbSet::CM_CREATE_EMPTY_CURRENT); - } + switch (status) { + case AccountInteraction::AS_DB_ALREADY_PRESENT: + QMessageBox::information(this, + tr("Datovka: Database file present"), + tr("Database file for account '%1' already exists.").arg(userName) + + "\n\n" + + tr("The existing database files %1 in '%2' are going to be used.").arg(namesStr).arg(dbDir) + + "\n\n" + + tr("If you want to use a new blank file then delete, rename or move the existing file so that the application can create a new empty file."), + QMessageBox::Ok); break; - case MDS_ERR_NOTAFILE: - { - /* Notify the user that the location is not a file. */ - QStringList dbFileNames( - MessageDbSet::existingDbFileNamesInLocation( - dbDir, userName, - itemSettings.isTestAccount(), - MessageDbSet::DO_UNKNOWN, true)); - Q_ASSERT(!dbFileNames.isEmpty()); - QString namesStr("'" + dbFileNames[0] + "'"); - for (int i = 1; i < dbFileNames.size(); ++i) { - namesStr += ", '" + dbFileNames[i] + "'"; - } - logWarning("Some databases of %s in '%s' related to " - "user name '%s' are not a file.\n", - namesStr.toUtf8().constData(), - dbDir.toUtf8().constData(), - userName.toUtf8().constData()); - if (0 != mw) { - QMessageBox::warning(mw, - tr("Datovka: Problem loading database"), - tr("Could not load data from the database " - "for account '%1'").arg(userName) + - "\n\n" + - tr("Some databases of %1 in '%2' are not a file." - ).arg(namesStr).arg(dbDir), - QMessageBox::Ok); - } - } + case AccountInteraction::AS_DB_NOT_PRESENT: + QMessageBox::warning(this, + tr("Datovka: Problem loading database"), + tr("Could not load data from the database for account '%1'").arg(userName) + + "\n\n" + + tr("Database files are missing in '%1'.").arg(dbDir) + + "\n\n" + + tr("I'll try to create an empty one."), + QMessageBox::Ok); break; - case MDS_ERR_ACCESS: - { - /* Notify that the user does not have enough rights. */ - QStringList dbFileNames( - MessageDbSet::existingDbFileNamesInLocation( - dbDir, userName, - itemSettings.isTestAccount(), - MessageDbSet::DO_UNKNOWN, true)); - Q_ASSERT(!dbFileNames.isEmpty()); - QString namesStr("'" + dbFileNames[0] + "'"); - for (int i = 1; i < dbFileNames.size(); ++i) { - namesStr += ", '" + dbFileNames[i] + "'"; - } - logWarning("Some databases of '%s' in '%s' related to " - "user name '%s' cannot be accessed.\n", - namesStr.toUtf8().constData(), - dbDir.toUtf8().constData(), - userName.toUtf8().constData()); - if (0 != mw) { - QMessageBox::warning(mw, - tr("Datovka: Problem loading database"), - tr("Could not load data from the database " - "for account '%1'").arg(userName) + - "\n\n" + - tr("Some databases of '%1' in '%2' cannot be accessed." - ).arg(namesStr).arg(dbDir) + - "\n\n" + - tr("You don't have enough access rights to use " - "the file."), - QMessageBox::Ok); - } - } + case AccountInteraction::AS_DB_NOT_FILES: + QMessageBox::warning(this, + tr("Datovka: Problem loading database"), + tr("Could not load data from the database for account '%1'").arg(userName) + + "\n\n" + + tr("Some databases of %1 in '%2' are not a file.").arg(namesStr).arg(dbDir), + QMessageBox::Ok); break; - case MDS_ERR_CREATE: - { - /* This error should not be returned. */ - Q_ASSERT(0); - } + case AccountInteraction::AS_DB_FILES_INACCESSIBLE: + QMessageBox::warning(this, + tr("Datovka: Problem loading database"), + tr("Could not load data from the database for account '%1'").arg(userName) + + "\n\n" + + tr("Some databases of '%1' in '%2' cannot be accessed.").arg(namesStr).arg(dbDir) + + "\n\n" + + tr("You don't have enough access rights to use the file."), + QMessageBox::Ok); break; - case MDS_ERR_DATA: - { - /* - * Database file is not a database file or is - * corrupted. - */ - QStringList dbFileNames( - MessageDbSet::existingDbFileNamesInLocation( - dbDir, userName, - itemSettings.isTestAccount(), - MessageDbSet::DO_UNKNOWN, true)); - Q_ASSERT(!dbFileNames.isEmpty()); - QString namesStr("'" + dbFileNames[0] + "'"); - for (int i = 1; i < dbFileNames.size(); ++i) { - namesStr += ", '" + dbFileNames[i] + "'"; - } - logWarning("Some databases of %s in '%s' related to " - "user name '%s' is probably corrupted.\n", - namesStr.toUtf8().constData(), - dbDir.toUtf8().constData(), - userName.toUtf8().constData()); - if (0 != mw) { - QMessageBox::warning(mw, - tr("Datovka: Problem loading database"), - tr("Could not load data from the database " - "for account '%1'").arg(userName) + - "\n\n" + - tr("Some databases of %1 in '%2' cannot be used." - ).arg(namesStr).arg(dbDir) + - "\n\n" + - tr("The file either does not contain an sqlite " - "database or the file is corrupted."), - QMessageBox::Ok); - } - } + case AccountInteraction::AS_DB_FILES_CORRUPT: + QMessageBox::warning(this, + tr("Datovka: Problem loading database"), + tr("Could not load data from the database for account '%1'").arg(userName) + + "\n\n" + + tr("Some databases of %1 in '%2' cannot be used.").arg(namesStr).arg(dbDir) + + "\n\n" + + tr("The file either does not contain an sqlite database or the file is corrupted."), + QMessageBox::Ok); break; - case MDS_ERR_MULTIPLE: - { - /* - * Multiple atabase organisation types resite in the - * same location. - */ - QStringList dbFileNames( - MessageDbSet::existingDbFileNamesInLocation( - dbDir, userName, - itemSettings.isTestAccount(), - MessageDbSet::DO_UNKNOWN, true)); - Q_ASSERT(!dbFileNames.isEmpty()); - QString namesStr("'" + dbFileNames[0] + "'"); - for (int i = 1; i < dbFileNames.size(); ++i) { - namesStr += ", '" + dbFileNames[i] + "'"; - } - logWarning("Multiple databases %s for '%s' have been " - "encountered in the location '%s'.\n", - namesStr.toUtf8().constData(), - userName.toUtf8().constData(), - dbDir.toUtf8().constData()); - if (0 != mw) { - QMessageBox::warning(mw, - tr("Datovka: Problem loading database"), - tr("Could not load data from the database " - "for account '%1'").arg(userName) + - "\n\n" + - tr("Conflicting databases %1 in '%2' cannot be used." - ).arg(namesStr).arg(dbDir) + - "\n\n" + - tr("Please remove the conflicting files."), - QMessageBox::Ok); - } - } + case AccountInteraction::AS_DB_CONFUSING_ORGANISATION: + QMessageBox::warning(this, + tr("Datovka: Problem loading database"), + tr("Could not load data from the database for account '%1'").arg(userName) + + "\n\n" + + tr("Conflicting databases %1 in '%2' cannot be used.").arg(namesStr).arg(dbDir) + + "\n\n" + + tr("Please remove the conflicting files."), + QMessageBox::Ok); break; default: - /* The code should not end here. */ - Q_ASSERT(0); break; } - if (itemSettings._createdFromScratch()) { - /* Notify only once. */ - itemSettings._setCreatedFromScratch(false); - } - /* * TODO -- Give the user some recovery options such as * move/rename/remove the corrupted file or remove/ignore the affected * account. */ - if (NULL == dbSet) { + if (Q_NULLPTR == dbSet) { /* * TODO -- generate notification dialogue and give the user * a choice between aborting program and skipping account? */ - logError("Database files for user name '%s' in '%s' cannot be " - "created or is probably corrupted.\n", - userName.toUtf8().constData(), - dbDir.toUtf8().constData()); - if (0 != mw) { - QMessageBox::critical(mw, - tr("Datovka: Database opening error"), - tr("Could not load data from the database " - "for account '%1'").arg(userName) + - "\n\n" + - tr("Database files in '%1' cannot be created or are " - "corrupted.").arg(dbDir), - QMessageBox::Ok); - } + QMessageBox::critical(this, + tr("Datovka: Database opening error"), + tr("Could not load data from the database for account '%1'").arg(userName) + + "\n\n" + + tr("Database files in '%1' cannot be created or are corrupted.").arg(dbDir), + QMessageBox::Ok); /* * The program has to be aborted right now. The method * QCoreApplication::exit(EXIT_FAILURE) uses the event loop @@ -3978,7 +3624,7 @@ Q_ASSERT(!userName.isEmpty()); - const AcntSettings &itemSettings(AccountModel::globAccounts[userName]); + const AcntSettings &itemSettings(globAccounts[userName]); if (!itemSettings.lastAttachSavePath().isEmpty()) { m_save_attach_dir = itemSettings.lastAttachSavePath(); @@ -3996,30 +3642,6 @@ /* ========================================================================= */ /* - * Create configuration file if not present. - */ -bool MainWindow::ensureConfPresence(void) -/* ========================================================================= */ -{ - if (!QDir(globPref.confDir()).exists()) { - if (!QDir(globPref.confDir()).mkpath(".")) { - return false; - } - } - if (!QFile(globPref.loadConfPath()).exists()) { - QFile file(globPref.loadConfPath()); - if (!file.open(QIODevice::ReadWrite)) { - return false; - } - file.close(); - } - - return true; -} - - -/* ========================================================================= */ -/* * Sets geometry from settings. */ void MainWindow::loadWindowGeometry(const QSettings &settings) @@ -4171,8 +3793,6 @@ /* Separator. */ connect(ui->actionAdd_account, SIGNAL(triggered()), this, SLOT(showAddNewAccountDialog())); - connect(ui->actionAdd_mojeID_account, SIGNAL(triggered()), - this, SLOT(addNewMojeIDAccount())); connect(ui->actionDelete_account, SIGNAL(triggered()), this, SLOT(deleteSelectedAccount())); /* Separator. */ @@ -4181,7 +3801,12 @@ /* Separator. */ connect(ui->actionProxy_settings, SIGNAL(triggered()), this, SLOT(showProxySettingsDialog())); - /* Separator. */ + /* Separator */ + connect(ui->actionRecords_management_settings, SIGNAL(triggered()), + this, SLOT(showRecordsManagementDialogue())); + connect(ui->actionUpdate_records_management_information, SIGNAL(triggered()), + this, SLOT(getStoredMsgInfoFromRecordsManagement())); + /* Separator. */ connect(ui->actionPreferences, SIGNAL(triggered()), this, SLOT(showPreferencesDialog())); /* actionQuit -- connected in ui file. */ @@ -4242,6 +3867,9 @@ connect(ui->actionOpen_delivery_info_externally, SIGNAL(triggered()), this, SLOT(openDeliveryInfoExternally())); /* Separator. */ + connect(ui->actionSend_to_records_management, SIGNAL(triggered()), + this, SLOT(sendSelectedMessageToRecordsManagement())); + /* Separator. */ connect(ui->actionExport_as_ZFO, SIGNAL(triggered()), this, SLOT(exportSelectedMessagesAsZFO())); connect(ui->actionExport_delivery_info_as_ZFO, SIGNAL(triggered()), @@ -4345,6 +3973,8 @@ // Menu: File ui->actionDelete_account->setEnabled(false); ui->actionSync_all_accounts->setEnabled(false); + ui->actionUpdate_records_management_information->setEnabled( + globRecordsManagementSet.isSet()); // Menu: Tools ui->actionFind_databox->setEnabled(false); ui->actionImport_ZFO_file_into_database->setEnabled(false); @@ -4385,6 +4015,9 @@ ui->actionOpen_message_externally->setEnabled(numSelected == 1); ui->actionOpen_delivery_info_externally->setEnabled(numSelected == 1); /* Separator. */ + ui->actionSend_to_records_management->setEnabled( + (numSelected == 1) && globRecordsManagementSet.isSet()); + /* Separator. */ ui->actionExport_as_ZFO->setEnabled(numSelected > 0); ui->actionExport_delivery_info_as_ZFO->setEnabled(numSelected > 0); ui->actionExport_delivery_info_as_PDF->setEnabled(numSelected > 0); @@ -4504,6 +4137,9 @@ /* Proxy settings. */ globProxSet.loadFromSettings(settings); + /* Records management settings. */ + globRecordsManagementSet.loadFromSettings(settings); + /* Accounts. */ m_accountModel.loadFromSettings(settings); ui->accountList->setModel(&m_accountModel); @@ -4600,8 +4236,8 @@ /* Get database id. */ const QString userName(m_accountModel.userName(index)); Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return false; } @@ -4653,8 +4289,8 @@ /* Get database id. */ const QString userName(m_accountModel.userName(index)); Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return false; } @@ -4712,8 +4348,8 @@ Q_ASSERT(topIndex.isValid()); const QString userName(m_accountModel.userName(topIndex)); Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { /* * Skip creation of leaves when no database is present. */ @@ -4789,6 +4425,9 @@ /* Proxy settings. */ globProxSet.saveToSettings(settings); + /* Records management settings. */ + globRecordsManagementSet.saveToSettings(settings); + /* Global preferences. */ globPref.saveToSettings(settings); @@ -4840,16 +4479,16 @@ QModelIndex index = m_accountModel.index(i, 0); const QString uName(m_accountModel.userName(index)); Q_ASSERT(!uName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(uName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(uName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } messageDbList.append(Task::AccountDescr(uName, dbSet)); } } else { - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -4871,8 +4510,8 @@ MessageDb::MsgId msgId(msgMsgId(msgIdx)); /* Check whether full messages are present. */ - MessageDbSet *dbSet = accountDbSet(userName, this); - Q_ASSERT(0 != dbSet); + MessageDbSet *dbSet = accountDbSet(userName); + Q_ASSERT(Q_NULLPTR != dbSet); MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, false); @@ -4882,8 +4521,10 @@ } if (!messageDb->msgsStoredWhole(msgId.dmId)) { - messageMissingOfferDownload(msgId, - tr("Full message not present!")); + if (!messageMissingOfferDownload(msgId, + tr("Full message not present!"))) { + return; + } } msgIds.append(msgId); @@ -4945,20 +4586,6 @@ accountDlg->deleteLater(); } - -/* ========================================================================= */ -/* - * Add mojeID account action and dialog. - */ -void MainWindow::addNewMojeIDAccount(void) -/* ========================================================================= */ -{ - debugSlotCall(); - - loginToMojeId(QString()); -} - - /* ========================================================================= */ /* * Slot: Delete selected account @@ -4989,14 +4616,13 @@ return; } - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } - const QString accountName( - AccountModel::globAccounts[userName].accountName()); + const QString accountName(globAccounts[userName].accountName()); QString dlgTitleText = tr("Remove account ") + accountName; QString questionText = tr("Do you want to remove account") + " '" + @@ -5035,17 +4661,7 @@ .arg(accountName)); } - if (isWebDatovkaAccount(userName)) { - TagDb *tagDbWd = globWebDatovkaTagDbPtr->accessTagDb( - getWebDatovkaTagDbPrefix(userName)); - if (!existsAnotherMojeIdAccountWithSameUserId(userName)) { - globWebDatovkaTagDbPtr->deleteDb(tagDbWd); - } else { - tagDbWd->removeAllMsgTagsFromAccount(userName); - } - } else { - globTagDbPtr->removeAllMsgTagsFromAccount(userName); - } + globTagDbPtr->removeAllMsgTagsFromAccount(userName); if ((DlgYesNoCheckbox::YesChecked == retVal) || (DlgYesNoCheckbox::YesUnchecked == retVal)) { @@ -5082,7 +4698,7 @@ globAccountDbPtr->dbId(AccountDb::keyFromLogin(userName))); Q_ASSERT(!dbId.isEmpty()); - const AcntSettings &accountInfo(AccountModel::globAccounts[userName]); + const AcntSettings &accountInfo(globAccounts[userName]); showStatusTextWithTimeout(tr("Change password of account " "\"%1\".").arg(accountInfo.accountName())); @@ -5107,18 +4723,17 @@ Q_ASSERT(!userName.isEmpty()); showStatusTextWithTimeout(tr("Change properties of account \"%1\".") - .arg(AccountModel::globAccounts[userName].accountName())); + .arg(globAccounts[userName].accountName())); DlgCreateAccount *accountDlg = new DlgCreateAccount( - AccountModel::globAccounts[userName], DlgCreateAccount::ACT_EDIT, - this); + globAccounts[userName], DlgCreateAccount::ACT_EDIT, this); int dlgRet = accountDlg->exec(); if (QDialog::Accepted == dlgRet) { /* Save changes. */ - AccountModel::globAccounts[userName] = accountDlg->getSubmittedData(); - emit AccountModel::globAccounts.accountDataChanged(userName); + globAccounts[userName] = accountDlg->getSubmittedData(); + emit globAccounts.accountDataChanged(userName); showStatusTextWithTimeout(tr("Account \"%1\" was updated.") .arg(userName)); @@ -5178,132 +4793,25 @@ const QString userName( m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - const AcntSettings &itemSettings(AccountModel::globAccounts[userName]); - - QString dbDir = itemSettings.dbDir(); - if (dbDir.isEmpty()) { - /* Set default directory name. */ - dbDir = globPref.confDir(); - } - - showStatusTextWithTimeout(tr("Change data dierctory of account \"%1\".") - .arg(itemSettings.accountName())); - - QDialog *change_directory = new DlgChangeDirectory(dbDir, this); - - connect(change_directory, SIGNAL(sentNewPath(QString, QString, QString)), - this, SLOT(receiveNewDataPath(QString, QString, QString))); - - change_directory->exec(); - change_directory->deleteLater(); -} - - -/* ========================================================================= */ -/* - * Receive and store new account database path. Change data - * directory path in settings. - */ -void MainWindow::receiveNewDataPath(QString oldDir, QString newDir, - QString action) -/* ========================================================================= */ -{ - debugSlotCall(); - - const QString userName( - m_accountModel.userName(currentAccountModelIndex())); - Q_ASSERT(!userName.isEmpty()); - - /* Get current settings. */ - AcntSettings &itemSettings(AccountModel::globAccounts[userName]); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } - /* Move account database into new directory */ - if ("move" == action) { - if (dbSet->moveToLocation(newDir)) { - itemSettings.setDbDir(newDir); - saveSettings(); - - logInfo("Database files for '%s' have been moved " - "from '%s' to '%s'.\n", - userName.toUtf8().constData(), - oldDir.toUtf8().constData(), - newDir.toUtf8().constData()); - - QMessageBox::information(this, - tr("Change data directory for current account"), - tr("Database files for '%1' have been successfully" - " moved to\n\n'%2'.").arg(userName).arg(newDir), - QMessageBox::Ok); - } else { - QMessageBox::critical(this, - tr("Change data directory for current account"), - tr("Database files for '%1' could not be moved " - "to\n\n'%2'.").arg(userName).arg(newDir), - QMessageBox::Ok); - } - - /* Copy account database into new directory */ - } else if ("copy" == action) { - if (dbSet->copyToLocation(newDir)) { - itemSettings.setDbDir(newDir); - saveSettings(); - - logInfo("Database files for '%s' have been copied " - "from '%s' to '%s'.\n", - userName.toUtf8().constData(), - oldDir.toUtf8().constData(), - newDir.toUtf8().constData()); - - QMessageBox::information(this, - tr("Change data directory for current account"), - tr("Database files for '%1' have been successfully" - " copied to\n\n'%2'.").arg(userName).arg(newDir), - QMessageBox::Ok); - } else { - QMessageBox::critical(this, - tr("Change data directory for current account"), - tr("Database files for '%1' could not be copied " - "to\n\n'%2'.").arg(userName).arg(newDir), - QMessageBox::Ok); - } - - /* Create a new account database into new directory */ - } else if ("new" == action) { - if (dbSet->reopenLocation(newDir, - MessageDbSet::DO_YEARLY, - MessageDbSet::CM_CREATE_EMPTY_CURRENT)) { - itemSettings.setDbDir(newDir); - saveSettings(); + const AcntSettings &itemSettings(globAccounts[userName]); + showStatusTextWithTimeout(tr("Change data dierctory of account \"%1\".") + .arg(itemSettings.accountName())); - logInfo("Database files for '%s' have been created " - "in '%s'.\n", userName.toUtf8().constData(), - newDir.toUtf8().constData()); + QModelIndex accountIdx(currentAccountModelIndex()); - QMessageBox::information(this, - tr("Change data directory for current account"), - tr("New database files for '%1' have been " - "successfully created in\n\n'%2'.") - .arg(userName).arg(newDir), - QMessageBox::Ok); - } else { - QMessageBox::critical(this, - tr("Change data directory for current account"), - tr("New database files for '%1' could not be " - "created in\n\n'%2'.").arg(userName).arg(newDir), - QMessageBox::Ok); - } - } else { - Q_ASSERT(0); + if (DlgChangeDirectory::changeDataDirectory(userName, dbSet, this)) { + saveSettings(); + accountItemCurrentChanged(accountIdx); } } - /* ========================================================================= */ /* * Search data box dialog. @@ -5317,22 +4825,9 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - if (!isWebDatovkaAccount(userName)) { - if (!globIsdsSessions.isConnectedToIsds(userName) && - !connectToIsds(userName)) { - return; - } - } else { - if (!wdSessions.isConnectedToWebdatovka(userName)) { - loginToMojeId(userName); - } - - if (!wdSessions.isConnectedToWebdatovka(userName)) { - showWebDatovkaInfoDialog(userName, - tr("You have to be logged into the WebDatovka " - "if you want to find databox.")); - return; - } + if (!globIsdsSessions.isConnectedToIsds(userName) && + !connectToIsds(userName)) { + return; } /* Method connectToIsds() acquires account information. */ @@ -5349,26 +4844,10 @@ bool dbOpenAddressing = (accountData.at(2) == "1") ? true : false; showStatusTextWithTimeout(tr("Find databoxes from account \"%1\".") - .arg(AccountModel::globAccounts[userName].accountName())); + .arg(globAccounts[userName].accountName())); - if (isWebDatovkaAccount(userName)) { - QDialog *dsSearch = - new DlgDsSearchMojeId(DlgDsSearchMojeId::ACT_BLANK, 0, - dbType, dbEffectiveOVM, this, userName); - dsSearch->exec(); - dsSearch->deleteLater(); - } else { - QDialog *dsSearch = new DlgDsSearch(userName, dbType, - dbEffectiveOVM, dbOpenAddressing, Q_NULLPTR, this); - dsSearch->exec(); - dsSearch->deleteLater(); - } -} - -void MainWindow::clearFilterField(void) -{ - debugSlotCall(); - mui_filterLine->clear(); + DlgDsSearch::search(userName, dbType, dbEffectiveOVM, dbOpenAddressing, + this); } /* ========================================================================= */ @@ -5424,11 +4903,16 @@ ui->messageList->resizeColumnToContents(0); ui->messageList->setColumnWidth(1, m_received_1); ui->messageList->setColumnWidth(2, m_received_2); - for (i = 3; i < (DbMsgsTblModel::rcvdItemIds().size() - 3); ++i) { + for (i = 3; i < (MessageDb::rcvdItemIds.size() - 3); ++i) { ui->messageList->resizeColumnToContents(i); } /* Last three columns display icons. */ - for (; i < DbMsgsTblModel::rcvdItemIds().size(); ++i) { + int max = MessageDb::rcvdItemIds.size(); + if (globRecordsManagementSet.isSet()) { + /* Add one column if records management service is activated. */ + ++max; + } + for (; i < max; ++i) { ui->messageList->setColumnWidth(i, 24); } if (m_sort_order == "SORT_ASCENDING") { @@ -5454,11 +4938,16 @@ ui->messageList->resizeColumnToContents(0); ui->messageList->setColumnWidth(1, m_sent_1); ui->messageList->setColumnWidth(2, m_sent_2); - for (i = 3; i < (DbMsgsTblModel::sntItemIds().size() - 1); ++i) { + for (i = 3; i < (MessageDb::sntItemIds.size() - 1); ++i) { ui->messageList->resizeColumnToContents(i); } /* Last column displays an icon. */ - for (; i < DbMsgsTblModel::rcvdItemIds().size(); ++i) { + int max = MessageDb::rcvdItemIds.size(); + if (globRecordsManagementSet.isSet()) { + /* Add one column if records management service is activated. */ + ++max; + } + for (; i < max; ++i) { ui->messageList->setColumnWidth(i, 24); } if (m_sort_order == "SORT_ASCENDING") { @@ -5653,18 +5142,12 @@ settings.endGroup(); } - -/* ========================================================================= */ -/* -* Slot: Refresh AccountList -*/ void MainWindow::refreshAccountList(const QString &userName) -/* ========================================================================= */ { debugSlotCall(); if (userName.isEmpty()) { - logWarning("%s\n", + logWarningNL("%s", "Cannot refresh account list on empty user name."); return; } @@ -5674,7 +5157,7 @@ /* There may be no account selected. */ enum AccountModel::NodeType nodeType = AccountModel::nodeUnknown; - MessageDb::MessageType msgType; + MessageDb::MessageType msgType = MessageDb::TYPE_RECEIVED; QString year; qint64 dmId = -1; @@ -5682,6 +5165,9 @@ /* Currently selected is the one being processed. */ nodeType = AccountModel::nodeType(selectedIdx); switch (nodeType) { + case AccountModel::nodeRecentReceived: + case AccountModel::nodeRecentSent: + break; case AccountModel::nodeReceivedYear: year = selectedIdx.data(ROLE_PLAIN_DISPLAY).toString(); msgType = MessageDb::TYPE_RECEIVED; @@ -5719,17 +5205,19 @@ * TODO -- A better solution? */ ui->accountList->repaint(); - if ((nodeType != AccountModel::nodeUnknown) && !year.isEmpty()) { - QModelIndex yearIdx(accountYearlyIndex(userName, year, - msgType)); - - if (yearIdx.isValid()) { - ui->accountList->setCurrentIndex(yearIdx); - accountItemCurrentChanged(selectedIdx); + if ((nodeType != AccountModel::nodeUnknown) && (dmId != -1)) { + if (!year.isEmpty()) { + QModelIndex yearIdx(accountYearlyIndex(userName, year, + msgType)); + if (yearIdx.isValid()) { + ui->accountList->setCurrentIndex(yearIdx); + } } + accountItemCurrentChanged(selectedIdx); + if (dmId != -1) { - QModelIndex msgIdx(messageIndex(dmId)); + QModelIndex msgIdx(messageIndex(ui->messageList, dmId)); if (msgIdx.isValid()) { ui->messageList->setCurrentIndex(msgIdx); ui->messageList->scrollTo(msgIdx); @@ -5743,183 +5231,24 @@ void MainWindow::showAboutApplicationDialog(void) { - QDialog *da = new DlgAbout(this); - da->exec(); - da->deleteLater(); + DlgAbout::about(this); } + void MainWindow::showImportDatabaseDialog(void) { - QDialog *prepareCreateAccount = new CreateAccountFromDbDialog(this); - connect(prepareCreateAccount, - SIGNAL(returnAction(bool)), this, - SLOT(prepareCreateAccountFromDatabaseFile(bool))); - prepareCreateAccount->exec(); - prepareCreateAccount->deleteLater(); -} + QStringList createdUserNames( + DlgCreateAccountFromDb::createAccount(m_accountModel, + m_on_import_database_dir_activate, this)); -void MainWindow::prepareCreateAccountFromDatabaseFile(bool fromDirectory) -{ - debugSlotCall(); - - QString importDir; - QStringList fileList, filePathList; - QStringList nameFilter("*.db"); - QDir directory(QDir::home()); - fileList.clear(); - filePathList.clear(); - - if (fromDirectory) { - importDir = QFileDialog::getExistingDirectory(this, - tr("Select directory"), m_on_import_database_dir_activate, - QFileDialog::ShowDirsOnly | - QFileDialog::DontResolveSymlinks); - - if (importDir.isEmpty()) { - return; - } - - m_on_import_database_dir_activate = importDir; - directory.setPath(importDir); - fileList = directory.entryList(nameFilter); - - if (fileList.isEmpty()) { - qDebug() << "No *.db selected file(s)"; - /* TODO - show dialog*/ - showStatusTextWithTimeout(tr("Database file(s) not found in " - "selected directory.")); - return; - } - - for (int i = 0; i < fileList.size(); ++i) { - filePathList.append(importDir + "/" + fileList.at(i)); - } - } else { - filePathList = QFileDialog::getOpenFileNames(this, - tr("Select db file(s)"), m_on_import_database_dir_activate, - tr("Database file (*.db)")); - - if (filePathList.isEmpty()) { - qDebug() << "No *.db selected file(s)"; - showStatusTextWithTimeout( - tr("Database file(s) not selected.")); - return; - } - - m_on_import_database_dir_activate = - QFileInfo(filePathList.at(0)).absoluteDir().absolutePath(); - } - - createAccountFromDatabaseFileList(filePathList); -} - - -/* ========================================================================= */ -/* - * Create accounts from list of database directory to application - */ -void MainWindow::createAccountFromDatabaseFileList( - const QStringList &filePathList) -/* ========================================================================= */ -{ - - debugFuncCall(); - - const int dbFilesCnt = filePathList.size(); - - if (0 == dbFilesCnt) { - return; - } - - QStringList currentAccountList; - QString errMsg; - - int accountCount = ui->accountList->model()->rowCount(); - for (int i = 0; i < accountCount; i++) { - QModelIndex index = m_accountModel.index(i, 0); - const QString userName(m_accountModel.userName(index)); - Q_ASSERT(!userName.isEmpty()); - currentAccountList.append(userName); - } - - for (int i = 0; i < dbFilesCnt; ++i) { - - QFileInfo file(filePathList.at(i)); - QString dbFileName = file.fileName(); - QString dbUserName; - QString dbYearFlag; - bool dbTestingFlag; - - /* Split and check the database file name. */ - if (!isValidDatabaseFileName(dbFileName, dbUserName, - dbYearFlag, dbTestingFlag, errMsg)) { - QMessageBox::warning(this, - tr("Create account: %1").arg(dbUserName), - tr("File") + ": " + filePathList.at(i) + - "\n\n" + errMsg, - QMessageBox::Ok); - continue; - } - - /* Check whether account already exists. */ - bool exists = false; - for (int j = 0; j < accountCount; ++j) { - if (currentAccountList.at(j) == dbUserName) { - exists = true; - break; - } - } - - if (exists) { - errMsg = tr( - "Account with user name '%1' and " - "its message database already exist. " - "New account was not created and " - "selected database file was not " - "associated with this account."). - arg(dbUserName); - QMessageBox::warning(this, - tr("Create account: %1").arg(dbUserName), - tr("File") + ": " + filePathList.at(i) + - "\n\n" + errMsg, - QMessageBox::Ok); - continue; - } - - AcntSettings itemSettings; - itemSettings.setTestAccount(dbTestingFlag); - itemSettings.setAccountName(dbUserName); - itemSettings.setUserName(dbUserName); - itemSettings.setLoginMethod(AcntSettings::LIM_UNAME_PWD); - itemSettings.setPassword(""); - itemSettings.setRememberPwd(false); - itemSettings.setSyncWithAll(false); - itemSettings.setDbDir(m_on_import_database_dir_activate); - m_accountModel.addAccount(itemSettings); - errMsg = tr("Account with name '%1' has been " - "created (user name '%1').").arg(dbUserName) - + " " + - tr("This database file has been set as " - "actual message database for this account. " - "Maybe you have to change account " - "properties for correct login to the " - "server Datové schránky."); - - QMessageBox::information(this, - tr("Create account: %1").arg(dbUserName), - tr("File") + ": " + filePathList.at(i) + - "\n\n" + errMsg, - QMessageBox::Ok); - - refreshAccountList(dbUserName); - - saveSettings(); - } + if (!createdUserNames.isEmpty()) { + refreshAccountList(createdUserNames.last()); + saveSettings(); + } activeAccountMenuAndButtons(true); ui->accountList->expandAll(); } - /* ========================================================================= */ /* * Authenticate message from ZFO file. @@ -6037,11 +5366,6 @@ const QString userName( m_accountModel.userName(currentAccountModelIndex())); - if (isWebDatovkaAccount(userName)) { - showWebDatovkaInfoDialog(userName, ""); - return; - } - MessageDb::MsgId msgId(msgMsgId(firstMsgColumnIdxs.first())); Q_ASSERT(!userName.isEmpty()); Q_ASSERT(msgId.dmId >= 0); @@ -6050,8 +5374,8 @@ return; } - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -6155,7 +5479,7 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); + MessageDbSet *dbSet = accountDbSet(userName); if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; @@ -6175,16 +5499,7 @@ { debugSlotCall(); - // webdatovka account cannot import ZFO files - const QString userName = - m_accountModel.userName(currentAccountModelIndex()); - if (isWebDatovkaAccount(userName)) { - showWebDatovkaInfoDialog(userName, ""); - return; - } - - enum ImportZFODialog::ZFOtype zfoType = - ImportZFODialog::IMPORT_MESSAGE_ZFO; + enum Imports::Type zfoType = Imports::IMPORT_MESSAGE; enum ImportZFODialog::ZFOlocation locationType = ImportZFODialog::IMPORT_FROM_DIR; bool checkZfoOnServer = false; @@ -6206,8 +5521,8 @@ if ((!checkZfoOnServer) || globIsdsSessions.isConnectedToIsds(userName) || connectToIsds(userName)) { - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); continue; } @@ -6371,63 +5686,29 @@ const QString userName(m_accountModel.userName(acntIdx)); Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); + MessageDbSet *dbSet = accountDbSet(userName); if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return false; } - bool ret = false; - - if (isWebDatovkaAccount(userName)) { - - if (!wdSessions.isConnectedToWebdatovka(userName)) { - loginToMojeId(userName); - } - - if (!wdSessions.isConnectedToWebdatovka(userName)) { - showWebDatovkaInfoDialog(userName, - tr("You have to be logged into the WebDatovka " - "if you want to download complete message.")); - return ret; - } - - MessageDb *messageDb = - dbSet->accessMessageDb(msgId.deliveryTime, false); - if (messageDb == Q_NULLPTR) { - Q_ASSERT(0); - return false; - } - int mId = messageDb->getWebDatokaId(msgId.dmId); - TaskDownloadMessageMojeId *task; - - task = new (std::nothrow) TaskDownloadMessageMojeId( - userName, dbSet, msgDirect, mId, msgId.dmId, false); - task->setAutoDelete(false); - globWorkPool.runSingle(task); - ret = TaskDownloadMessageMojeId::DM_SUCCESS == task->m_result; - delete task; - - } else { - - if (!globIsdsSessions.isConnectedToIsds(userName) && - !connectToIsds(userName)) { - return false; - } - TaskDownloadMessage *task; - - task = new (std::nothrow) TaskDownloadMessage( - userName, dbSet, msgDirect, msgId, false); - task->setAutoDelete(false); - globWorkPool.runSingle(task); - ret = TaskDownloadMessage::DM_SUCCESS == task->m_result; - if (ret) { - msgId.deliveryTime = task->m_mId.deliveryTime; - } + if (!globIsdsSessions.isConnectedToIsds(userName) && + !connectToIsds(userName)) { + return false; + } + TaskDownloadMessage *task; - delete task; + task = new (std::nothrow) TaskDownloadMessage( + userName, dbSet, msgDirect, msgId, false); + task->setAutoDelete(false); + globWorkPool.runSingle(task); + bool ret = TaskDownloadMessage::DM_SUCCESS == task->m_result; + if (ret) { + msgId.deliveryTime = task->m_mId.deliveryTime; } + delete task; + /* Process all pending events. */ QCoreApplication::processEvents(); @@ -6439,22 +5720,14 @@ { debugFuncCall(); - QMessageBox msgBox(this); - - msgBox.setWindowTitle(title); - msgBox.setText(tr("Complete message '%1' is missing.").arg(msgId.dmId)); - - msgBox.setIcon(QMessageBox::Warning); - msgBox.setInformativeText( + int dlgRet = DlgMsgBox::message(this, QMessageBox::Warning, title, + tr("Complete message '%1' is missing.").arg(msgId.dmId), tr("First you must download the complete message to continue with the action.") + "\n\n" + - tr("Do you want to download the complete message now?")); + tr("Do you want to download the complete message now?"), + QString(), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - - if ((QMessageBox::Yes == msgBox.exec()) && - downloadCompleteMessage(msgId)) { + if ((QMessageBox::Yes == dlgRet) && downloadCompleteMessage(msgId)) { showStatusTextWithTimeout( tr("Complete message '%1' has been downloaded."). arg(msgId.dmId)); @@ -6519,8 +5792,8 @@ return; } - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -6577,8 +5850,8 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -6618,8 +5891,8 @@ } } - QString attachName(dzPrefix(messageDb, msgId.dmId) + - QString("DZ_%1.zfo").arg(msgId.dmId)); + QString attachName( + QString("%1_%2.zfo").arg(dzPrefix(messageDb, msgId.dmId)).arg(msgId.dmId)); if (attachName.isEmpty()) { Q_ASSERT(0); return; @@ -6672,8 +5945,8 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -6808,8 +6081,8 @@ } MessageDbSet *dbSet = accountDbSet( - m_accountModel.userName(currentAccountModelIndex()), this); - if (0 == dbSet) { + m_accountModel.userName(currentAccountModelIndex())); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -6822,19 +6095,16 @@ QByteArray base64 = messageDb->msgsMessageBase64(msgId.dmId); if (base64.isEmpty()) { - QMessageBox msgBox(this);; - msgBox.setWindowTitle(tr("Datovka - Export error!")); - msgBox.setText(tr("Cannot export the message ") + msgId.dmId); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setInformativeText( - tr("First you must download message before its export...")); - msgBox.exec(); + DlgMsgBox::message(this, QMessageBox::Warning, + tr("Datovka - Export error!"), + tr("Cannot export the message '%1'.").arg(msgId.dmId), + tr("First you must download the message before its export..."), + QString()); return; } QString fileName(TMP_ATTACHMENT_PREFIX + - dzPrefix(messageDb, msgId.dmId) + - QString("DZ_%1.zfo").arg(msgId.dmId)); + QString("%1_%2.zfo").arg(dzPrefix(messageDb, msgId.dmId)).arg(msgId.dmId)); if (fileName.isEmpty()) { Q_ASSERT(0); return; @@ -6873,12 +6143,6 @@ const QString userName = m_accountModel.userName(currentAccountModelIndex()); - if (isWebDatovkaAccount(userName)) { - /* TODO - will be supported later */ - showWebDatovkaInfoDialog(userName, ""); - return; - } - /* First column. */ QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); if (1 != firstMsgColumnIdxs.size()) { @@ -6894,8 +6158,8 @@ return; } - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -6908,19 +6172,16 @@ QByteArray base64 = messageDb->msgsGetDeliveryInfoBase64(msgId.dmId); if (base64.isEmpty()) { - QMessageBox msgBox(this); - msgBox.setWindowTitle(tr("Datovka - Export error!")); - msgBox.setText(tr("Cannot export the message ") + msgId.dmId); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setInformativeText( - tr("First you must download message before its export...")); - msgBox.exec(); + DlgMsgBox::message(this, QMessageBox::Warning, + tr("Datovka - Export error!"), + tr("Cannot export the message '%1'.").arg(msgId.dmId), + tr("First you must download the message before its export..."), + QString()); return; } QString fileName(TMP_ATTACHMENT_PREFIX + - dzPrefix(messageDb, msgId.dmId) + - QString("DZ_%1_info.zfo").arg(msgId.dmId)); + QString("%1_%2_info.zfo").arg(dzPrefix(messageDb, msgId.dmId)).arg(msgId.dmId)); if (fileName.isEmpty()) { Q_ASSERT(0); return; @@ -6946,6 +6207,112 @@ } } +void MainWindow::getStoredMsgInfoFromRecordsManagement(void) +{ + debugSlotCall(); + + QStringList userNames; + for (int row = 0; row < m_accountModel.rowCount(); ++row) { + userNames.append( + m_accountModel.userName(m_accountModel.index(row, 0))); + } + + QList accounts; + foreach (const QString &userName, userNames) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { + Q_ASSERT(0); + return; + } + accounts.append(DlgRecordsManagementStored::AcntData( + globAccounts[userName].accountName(), + userName, dbSet)); + } + + DlgRecordsManagementStored::updateStoredInformation( + globRecordsManagementSet, accounts, this); + + m_messageTableModel.fillRecordsManagementColumn( + DbMsgsTblModel::REC_MGMT_NEG_COL); +} + +void MainWindow::sendSelectedMessageToRecordsManagement(void) +{ + debugSlotCall(); + + QModelIndex msgIndex; + { + QModelIndexList msgIndexes(currentFrstColMessageIndexes()); + + if (msgIndexes.size() != 1) { + /* Do nothing when multiple messages selected. */ + return; + } + + msgIndex = msgIndexes.first(); + } + + if (!msgIndex.isValid()) { + Q_ASSERT(0); + return; + } + + const QString userName( + m_accountModel.userName(currentAccountModelIndex())); + Q_ASSERT(!userName.isEmpty()); + + MessageDb::MsgId msgId(msgMsgId(msgIndex)); + Q_ASSERT(msgId.dmId >= 0); + + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { + Q_ASSERT(0); + return; + } + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); + if (Q_NULLPTR == messageDb) { + Q_ASSERT(0); + return; + } + + QByteArray msgRaw(messageDb->msgsMessageRaw(msgId.dmId)); + if (msgRaw.isEmpty()) { + + if (!messageMissingOfferDownload(msgId, + tr("Message export error!"))) { + return; + } + + messageDb = dbSet->accessMessageDb(msgId.deliveryTime, false); + if (Q_NULLPTR == messageDb) { + Q_ASSERT(0); + logErrorNL( + "Could not access database of freshly downloaded message '%" PRId64 "'.", + msgId.dmId); + return; + } + + msgRaw = messageDb->msgsMessageRaw(msgId.dmId); + if (msgRaw.isEmpty()) { + Q_ASSERT(0); + return; + } + } + + /* Show send to records management dialogue. */ + DlgRecordsManagementUpload::uploadMessage(globRecordsManagementSet, + msgId.dmId, + QString("%1_%2.zfo").arg(dzPrefix(messageDb, msgId.dmId)).arg(msgId.dmId), + msgRaw, this); + + QList msgIdList; + msgIdList.append(msgId.dmId); + + m_messageTableModel.refillRecordsManagementColumn(msgIdList, + DbMsgsTblModel::REC_MGMT_NEG_COL); +} + void MainWindow::showSignatureDetailsDialog(void) { debugSlotCall(); @@ -6960,8 +6327,8 @@ } MessageDbSet *dbSet = accountDbSet( - m_accountModel.userName(currentAccountModelIndex()), this); - if (0 == dbSet) { + m_accountModel.userName(currentAccountModelIndex())); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -7222,21 +6589,21 @@ bool MainWindow::connectToIsds(const QString &userName) { - AcntSettings settingsCopy(AccountModel::globAccounts[userName]); + AcntSettings settingsCopy(globAccounts[userName]); if (!logInGUI(globIsdsSessions, settingsCopy)) { return false; } /* Logged in. */ - AccountModel::globAccounts[userName] = settingsCopy; + globAccounts[userName] = settingsCopy; /* * Catching the following signal is required only when account has * changed. * * The account model catches the signal. */ - emit AccountModel::globAccounts.accountDataChanged(userName); + emit globAccounts.accountDataChanged(userName); saveSettings(); /* Get account information if possible. */ @@ -7333,22 +6700,19 @@ { debugFuncCall(); - QMessageBox msgBox(this); - msgBox.setWindowTitle(tr("Datovka")); - /* * Check whether currently some tasks are being processed or are * pending. If nothing works finish immediately, else show question. */ if (globWorkPool.working()) { - msgBox.setIcon(QMessageBox::Question); - msgBox.setText( - tr("Datovka is currently processing some tasks.")); - msgBox.setInformativeText(tr( - "Do you want to abort pending actions and close Datovka?")); - msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); - msgBox.setDefaultButton(QMessageBox::No); - if (QMessageBox::Yes == msgBox.exec()) { + int dlgRet = DlgMsgBox::message(this, QMessageBox::Question, + tr("Datovka"), + tr("Datovka is currently processing some tasks."), + tr("Do you want to abort pending actions and close Datovka?"), + QString(), QMessageBox::No | QMessageBox::Yes, + QMessageBox::No); + + if (QMessageBox::Yes == dlgRet) { globWorkPool.stop(); globWorkPool.clear(); } else { @@ -7512,8 +6876,8 @@ } MessageDbSet *dbSet = accountDbSet( - m_accountModel.userName(currentAccountModelIndex()), this); - if (0 == dbSet) { + m_accountModel.userName(currentAccountModelIndex())); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -7521,10 +6885,6 @@ QItemSelection storedMsgSelection = ui->messageList->selectionModel()->selection(); - DbMsgsTblModel *messageModel = dynamic_cast( - m_messageListProxyModel.sourceModel()); - Q_ASSERT(0 != messageModel); - for (QModelIndexList::const_iterator it = firstMsgColumnIdxs.begin(); it != firstMsgColumnIdxs.end(); ++it) { const MessageDb::MsgId msgId(msgMsgId(*it)); @@ -7543,7 +6903,7 @@ * Mark message as read without reloading * the whole model. */ - messageModel->overrideRead(msgId.dmId, read); + m_messageTableModel.overrideRead(msgId.dmId, read); } ui->messageList->selectionModel()->select(storedMsgSelection, @@ -7573,8 +6933,8 @@ } MessageDbSet *dbSet = accountDbSet( - m_accountModel.userName(currentAccountModelIndex()), this); - if (0 == dbSet) { + m_accountModel.userName(currentAccountModelIndex())); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -7582,10 +6942,6 @@ QItemSelection storedMsgSelection = ui->messageList->selectionModel()->selection(); - DbMsgsTblModel *messageModel = dynamic_cast( - m_messageListProxyModel.sourceModel()); - Q_ASSERT(0 != messageModel); - for (QModelIndexList::const_iterator it = firstMsgColumnIdxs.begin(); it != firstMsgColumnIdxs.end(); ++it) { const MessageDb::MsgId msgId(msgMsgId(*it)); @@ -7604,7 +6960,7 @@ * Mark message as read without reloading * the whole model. */ - messageModel->overrideProcessing(msgId.dmId, state); + m_messageTableModel.overrideProcessing(msgId.dmId, state); } ui->messageList->selectionModel()->select(storedMsgSelection, @@ -7647,8 +7003,8 @@ const QString currentUserName( m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!currentUserName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(currentUserName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(currentUserName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -7662,8 +7018,8 @@ const QString userName(m_accountModel.userName(index)); Q_ASSERT(!userName.isEmpty()); if (currentUserName != userName) { - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); continue; } @@ -7700,35 +7056,33 @@ { debugFuncCall(); - QMessageBox msgBox(this); - msgBox.setWindowTitle(tr("Password expiration")); - msgBox.setIcon(QMessageBox::Information); + int dlgRet = QMessageBox::No; + if (days < 0) { - msgBox.setText(tr("According to the last available information, " - "your password for account '%1' (login '%2') " - "expired %3 days ago (%4).") - .arg(accountName).arg(userName).arg(days*(-1)) - .arg(dateTime.toString("dd.MM.yyyy hh:mm:ss"))); - msgBox.setInformativeText(tr("You have to change your password " - "from the ISDS web interface. " - "Your new password will be valid for 90 days.")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - } else { - msgBox.setText(tr("According to the last available information, " - "your password for account '%1' (login '%2') " - "will expire in %3 days (%4).") - .arg(accountName).arg(userName).arg(days) - .arg(dateTime.toString("dd.MM.yyyy hh:mm:ss"))); - msgBox.setInformativeText(tr("You can change your password now, " - "or later using the 'Change password' command. " - "Your new password will be valid for 90 days.\n\n" - "Change password now?")); - msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); - msgBox.setDefaultButton(QMessageBox::No); + DlgMsgBox::message(this, QMessageBox::Information, + tr("Password expiration"), + tr("According to the last available information, " + "your password for account '%1' (login '%2') expired %3 days ago (%4).") + .arg(accountName).arg(userName).arg(days*(-1)) + .arg(dateTime.toString("dd.MM.yyyy hh:mm:ss")), + tr("You have to change your password from the ISDS web interface. " + "Your new password will be valid for 90 days."), + QString(), QMessageBox::Ok, QMessageBox::Ok); + } else { + dlgRet = DlgMsgBox::message(this, QMessageBox::Information, + tr("Password expiration"), + tr("According to the last available information, " + "your password for account '%1' (login '%2') will expire in %3 days (%4).") + .arg(accountName).arg(userName).arg(days) + .arg(dateTime.toString("dd.MM.yyyy hh:mm:ss")), + tr("You can change your password now or later using the '%1' command. " + "Your new password will be valid for 90 days.\n\n" + "Change password now?").arg(ui->actionChange_password->text()), + QString(), QMessageBox::No | QMessageBox::Yes, + QMessageBox::No); } - return msgBox.exec(); + return dlgRet; } @@ -7778,7 +7132,7 @@ Q_ASSERT(!userName.isEmpty()); showStatusTextPermanently(tr("Checking time stamps in " "account '%1'...").arg( - AccountModel::globAccounts[userName].accountName())); + globAccounts[userName].accountName())); checkMsgsTmstmpExpiration(userName, QStringList()); break; @@ -7789,7 +7143,7 @@ Q_ASSERT(!userName.isEmpty()); showStatusTextPermanently( tr("Checking time stamps in account '%1'...").arg( - AccountModel::globAccounts[userName].accountName())); + globAccounts[userName].accountName())); checkMsgsTmstmpExpiration(userName, QStringList()); } break; @@ -7863,7 +7217,7 @@ QByteArray tstData; int msgCnt = 0; - QString infoText; + QString dlgText; bool showExportOption = true; if (userName.isEmpty()) { @@ -7885,7 +7239,7 @@ for (int i = 0; i < msgCnt; ++i) { message = loadZfoFile(dummy_session, filePathList.at(i), - ImportZFODialog::IMPORT_MESSAGE_ZFO); + Imports::IMPORT_MESSAGE); if (NULL == message || message->envelope == NULL) { errorMsgFileNames.append(filePathList.at(i)); continue; @@ -7915,8 +7269,7 @@ isds_message_free(&message); isds_ctx_free(&dummy_session); - infoText = tr("Time stamp expiration check of ZFO files " - "finished with result:") + dlgText = tr("Time stamp expiration check of ZFO files finished with result:") + "

    " + tr("Total of ZFO files: %1").arg(msgCnt) + "
    " + @@ -7929,8 +7282,8 @@ showExportOption = false; } else { - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -7956,9 +7309,9 @@ } } - infoText = tr("Time stamp expiration check " + dlgText = tr("Time stamp expiration check " "in account '%1' finished with result:").arg( - AccountModel::globAccounts[userName].accountName()) + globAccounts[userName].accountName()) + "

    " + tr("Total of messages in database: %1").arg(msgCnt) + "
    " + @@ -7969,10 +7322,10 @@ tr("Unchecked messages: %1").arg(errorMsgIds.count()); } - QMessageBox msgBox(this); - msgBox.setIcon(QMessageBox::Information); - msgBox.setWindowTitle(tr("Time stamp expiration check results")); - msgBox.setText(infoText); + QString infoText; + QString detailText; + QMessageBox::StandardButtons buttons = QMessageBox::Ok; + enum QMessageBox::StandardButton dfltDutton = QMessageBox::Ok; if (!expirMsgIds.isEmpty() || !expirMsgFileNames.isEmpty() || !errorMsgIds.isEmpty() || !errorMsgFileNames.isEmpty()) { @@ -7982,58 +7335,52 @@ tr("Do you want to export the expiring " "messages to ZFO?") + "

    "; } - msgBox.setInformativeText(infoText); - infoText.clear(); if (!expirMsgIds.isEmpty() || !errorMsgIds.isEmpty()) { for (int i = 0; i < expirMsgIds.count(); ++i) { - infoText += tr("Time stamp of message %1 expires " + detailText += tr("Time stamp of message %1 expires " "within specified interval.").arg(expirMsgIds.at(i).dmId); if (((expirMsgIds.count() - 1) != i) || errorMsgIds.count()) { - infoText += "\n"; + detailText += "\n"; } } for (int i = 0; i < errorMsgIds.count(); ++i) { - infoText += tr("Time stamp of message %1 " + detailText += tr("Time stamp of message %1 " "is not present.").arg(errorMsgIds.at(i).dmId); if ((expirMsgIds.count() - 1) != i) { - infoText += "\n"; + detailText += "\n"; } } } else { for (int i = 0; i < expirMsgFileNames.count(); ++i) { - infoText += tr("Time stamp of message %1 expires " + detailText += tr("Time stamp of message %1 expires " "within specified interval.").arg(expirMsgFileNames.at(i)); if (((expirMsgFileNames.count() - 1) != i) || errorMsgFileNames.count()) { - infoText += "\n"; + detailText += "\n"; } } for (int i = 0; i < errorMsgFileNames.count(); ++i) { - infoText += tr("Time stamp of message %1 " + detailText += tr("Time stamp of message %1 " "is not present.").arg(errorMsgFileNames.at(i)); if ((expirMsgFileNames.count() - 1) != i) { - infoText += "\n"; + detailText += "\n"; } } } - msgBox.setDetailedText(infoText); if (!expirMsgIds.isEmpty() && showExportOption) { - msgBox.setStandardButtons(QMessageBox::Yes - | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - } else { - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); + buttons = QMessageBox::No | QMessageBox::Yes; + dfltDutton = QMessageBox::No; } - } else { - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); } - if (QMessageBox::Yes == msgBox.exec()) { + int dlgRet = DlgMsgBox::message(this, QMessageBox::Information, + tr("Time stamp expiration check results"), dlgText, infoText, + detailText, buttons, dfltDutton); + + if (QMessageBox::Yes == dlgRet) { if (!userName.isEmpty()) { exportExpirMessagesToZFO(userName, expirMsgIds); } @@ -8053,8 +7400,8 @@ return; } - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -8092,24 +7439,17 @@ const QString userName = m_accountModel.userName(currentAccountModelIndex()); - if (isWebDatovkaAccount(userName)) { - showWebDatovkaInfoDialog(userName, ""); - return; - } - - QMessageBox msgBox(this); - msgBox.setIcon(QMessageBox::Question); - msgBox.setWindowTitle(tr("Import of mesages from database")); - msgBox.setText(tr("This action allow to import messages from selected" - " database files into current account. Keep in mind that this " - "action may takes a few minutes based on number of messages " - "in the imported database. Import progress will be displayed " - "in the status bar.")); - msgBox.setInformativeText(tr("Do you want to continue?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - if (QMessageBox::No == msgBox.exec()) { - return; + { + int dlgRet = DlgMsgBox::message(this, QMessageBox::Question, + tr("Import messages from database"), + tr("This action allow to import messages from selected database files into current account. " + "Keep in mind that this action may take a while based on number of messages in the imported database. " + "Import progress will be displayed in the status bar."), + tr("Do you want to continue?"), QString(), + QMessageBox::No | QMessageBox::Yes, QMessageBox::No); + if (QMessageBox::No == dlgRet) { + return; + } } /* get list of selected database files */ @@ -8127,8 +7467,8 @@ m_on_import_database_dir_activate = QFileInfo(dbFileList.at(0)).absoluteDir().absolutePath(); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -8146,39 +7486,35 @@ { debugSlotCall(); - QMessageBox msgBox(this); - msgBox.setIcon(QMessageBox::Question); - msgBox.setWindowTitle(tr("Database split")); - msgBox.setText(tr("This action split current account message database " - "into several new databases which will contain messages relevant " - "by year only. It is recommended for large database because the " - "performance of application will be better.")); - msgBox.setInformativeText(tr("Original database file will copy to " - "selected directory and new database files will created in " - "the same location. If action finished with success, new databases" - " will be used instead of original. Restart of application " - "is required.") - +"\n\n" + - tr("Note: Keep in mind that this action may " - "takes a few minutes based on number of messages in the database.") - + "\n\n" + tr("Do you want to continue?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - if (QMessageBox::No == msgBox.exec()) { - return; + { + int dlgRet = DlgMsgBox::message(this, QMessageBox::Question, + tr("Database split"), + tr("This action splits current account message database into several separate databases which will contain messages relevant to one year only. " + "It is recommended for large databases in order to improve the performance."), + tr("The original database file will be copied to selected directory and new database files will be created in the original location. " + "If action finishes with success then new databases will be used instead of the original. " + "Application restart is required.") + + "\n\n" + + tr("Note: Keep in mind that this action may take a while based on the number of messages in the database.") + + "\n\n" + tr("Do you want to continue?"), QString(), + QMessageBox::No | QMessageBox::Yes, QMessageBox::No); + + if (QMessageBox::No == dlgRet) { + return; + } } QString newDbDir; QString userName = m_accountModel.userName(currentAccountModelIndex()); /* get current db file location */ - AcntSettings &itemSettings(AccountModel::globAccounts[userName]); + AcntSettings &itemSettings(globAccounts[userName]); QString dbDir = itemSettings.dbDir(); if (dbDir.isEmpty()) { dbDir = globPref.confDir(); } /* get origin message db set based on username */ - MessageDbSet *msgDbSet = accountDbSet(userName, this); + MessageDbSet *msgDbSet = accountDbSet(userName); if (Q_NULLPTR == msgDbSet) { return; } @@ -8200,12 +7536,13 @@ clearProgressBar(); showStatusTextWithTimeout(tr("Split of message database " "finished with error")); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setWindowTitle(tr("Database file error")); - msgBox.setText(tr("Database file cannot split into same directory.")); - msgBox.setInformativeText(tr("Please, you must choose another directory.")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.exec(); + + DlgMsgBox::message(this, QMessageBox::Critical, + tr("Database file error"), + tr("Database file cannot be split into original directory."), + tr("Please choose another directory."), QString(), + QMessageBox::Ok); + clearStatusBar(); } } while (dbDir == newDbDir); @@ -8224,30 +7561,29 @@ QApplication::restoreOverrideCursor(); + /* Show final notification. */ if (task->m_success) { showStatusTextWithTimeout(tr("Split of message database finished")); - msgBox.setIcon(QMessageBox::Information); - msgBox.setText(tr("Congratulation: message database for " - "account '%1' was split successfully. Please, restart the " - "application for loading of new databases.").arg(userName)); - msgBox.setInformativeText(tr("Note: Original database file was backup to:") - + "\n" + newDbDir); - } else { - msgBox.setIcon(QMessageBox::Critical); - msgBox.setText(tr("Split of message database for " - "account '%1' was not successfully. Please, restart the " - "application for loading original database.").arg(userName)); - msgBox.setInformativeText(task->m_error); + + DlgMsgBox::message(this, QMessageBox::Information, + tr("Database split result"), + tr("Congratulation: message database for account '%1' was split successfully. " + "Please, restart the application for loading of new databases.") + .arg(userName), + tr("Note: Original database file was backed up to:") + "\n" + newDbDir, + QString(), QMessageBox::Ok); + } else { + DlgMsgBox::message(this, QMessageBox::Critical, + tr("Database split result"), + tr("Splitting of message database for account '%1' was not successful. " + "Please, restart the application in order to reload the original database.") + .arg(userName), + task->m_error, QString(), QMessageBox::Ok); } delete task; clearProgressBar(); - /* show final notification */ - msgBox.setWindowTitle(tr("Database split result")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.exec(); - clearStatusBar(); /* refresh account model and account list */ @@ -8352,16 +7688,8 @@ this, SLOT(filterMessages(QString))); mui_filterLine->setFixedWidth(200); mui_filterLine->setToolTip(tr("Enter sought expression")); + mui_filterLine->setClearButtonEnabled(true); ui->toolBar->addWidget(mui_filterLine); - - /* Clear message filter button. */ - mui_clearFilterLineButton = new QPushButton(this); - mui_clearFilterLineButton->setIcon( - QIcon(ICON_3PARTY_PATH "delete_16.png")); - mui_clearFilterLineButton->setToolTip(tr("Clear search field")); - ui->toolBar->addWidget(mui_clearFilterLineButton); - connect(mui_clearFilterLineButton, SIGNAL(clicked()), this, - SLOT(clearFilterField())); } void MainWindow::setMenuActionIcons(void) @@ -8377,16 +7705,25 @@ } /* Separator. */ ui->actionAdd_account->isEnabled(); - ui->actionAdd_mojeID_account->isEnabled(); -#ifdef DISABLE_MOJEID_ACCOUNT_ADDING - ui->actionAdd_mojeID_account->setVisible(false); -#endif /* DISABLE_MOJEID_ACCOUNT_ADDING */ ui->actionDelete_account->isEnabled(); /* Separator. */ ui->actionImport_database_directory->isEnabled(); /* Separator. */ ui->actionProxy_settings->isEnabled(); - /* Separator. */ + /* Separator. */ + { + QIcon ico; + ico.addFile(QStringLiteral(":/icons/3party/briefcase_16.png"), QSize(), QIcon::Normal, QIcon::Off); + ico.addFile(QStringLiteral(":/icons/3party/briefcase_32.png"), QSize(), QIcon::Normal, QIcon::Off); + ui->actionRecords_management_settings->setIcon(ico); + } + { + QIcon ico; + ico.addFile(QStringLiteral(":/icons/3party/briefcase_16.png"), QSize(), QIcon::Normal, QIcon::Off); + ico.addFile(QStringLiteral(":/icons/3party/briefcase_32.png"), QSize(), QIcon::Normal, QIcon::Off); + ui->actionUpdate_records_management_information->setIcon(ico); + } + /* Separator. */ { QIcon ico; ico.addFile(QStringLiteral(":/icons/3party/gear_16.png"), QSize(), QIcon::Normal, QIcon::Off); @@ -8474,6 +7811,13 @@ ui->actionOpen_message_externally->isEnabled(); ui->actionOpen_delivery_info_externally->isEnabled(); /* Separator. */ + { + QIcon ico; + ico.addFile(QStringLiteral(":/icons/3party/briefcase_16.png"), QSize(), QIcon::Normal, QIcon::Off); + ico.addFile(QStringLiteral(":/icons/3party/briefcase_32.png"), QSize(), QIcon::Normal, QIcon::Off); + ui->actionSend_to_records_management->setIcon(ico); + } + /* Separator. */ ui->actionExport_as_ZFO->isEnabled(); ui->actionExport_delivery_info_as_ZFO->isEnabled(); ui->actionExport_delivery_info_as_PDF->isEnabled(); @@ -8533,7 +7877,7 @@ { debugSlotCall(); modifyTags(m_accountModel.userName(currentAccountModelIndex()), - QList(), QList()); + QList()); } /* ========================================================================= */ @@ -8546,37 +7890,15 @@ debugSlotCall(); QList msgIdList; - QList msgIdWebDatovkaList; const QString userName( m_accountModel.userName(currentAccountModelIndex())); - const bool webdatovkaAccount = isWebDatovkaAccount(userName); - MessageDbSet *dbSet = Q_NULLPTR; - if (webdatovkaAccount) { - dbSet = accountDbSet(userName, this); - if (Q_NULLPTR == dbSet) { - Q_ASSERT(0); - return; - } - } foreach (const QModelIndex &idx, currentFrstColMessageIndexes()) { msgIdList.append(idx.data().toLongLong()); - if (webdatovkaAccount) { - Q_ASSERT(Q_NULLPTR != dbSet); - QDateTime deliveryTime(msgDeliveryTime(idx)); - MessageDb *messageDb = - dbSet->accessMessageDb(deliveryTime, false); - if (messageDb == Q_NULLPTR) { - Q_ASSERT(0); - return; - } - qint64 mId = messageDb->getWebDatokaId(idx.data().toLongLong()); - msgIdWebDatovkaList.append(mId); - } } - modifyTags(userName, msgIdList, msgIdWebDatovkaList); + modifyTags(userName, msgIdList); } void MainWindow::vacuumMsgDbSlot(void) @@ -8586,23 +7908,19 @@ if (!globPref.store_messages_on_disk) { showStatusTextWithTimeout(tr("Vacuum cannot be performed on databases in memory.")); - QMessageBox msgBox(this); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setWindowTitle(tr("Database operation error")); - msgBox.setText(tr("Database clean-up cannot be performed on database in memory.")); - msgBox.setInformativeText(tr("Cannot call VACUUM on database in memory.")); - - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); + DlgMsgBox::message(this, QMessageBox::Warning, + tr("Database operation error"), + tr("Database clean-up cannot be performed on database in memory."), + tr("Cannot call VACUUM on database in memory."), QString(), + QMessageBox::Ok, QMessageBox::Ok); return; } const QString userName = m_accountModel.userName(currentAccountModelIndex()); - MessageDbSet *msgDbSet = accountDbSet(userName, this); - if (0 == msgDbSet) { + MessageDbSet *msgDbSet = accountDbSet(userName); + if (Q_NULLPTR == msgDbSet) { return; } @@ -8621,17 +7939,16 @@ } { - QMessageBox msgBox(this); - msgBox.setIcon(QMessageBox::Question); - msgBox.setWindowTitle(tr("Clean message database")); - msgBox.setText(tr("Performs a message database clean-up for the selected account. " - "This action will block the entire application. " - "The action may take several minutes to be completed. " - "Furthermore, it requires more than %1 of free disk space to successfully proceed.").arg(size)); - msgBox.setInformativeText(tr("Do you want to continue?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - if (QMessageBox::Yes != msgBox.exec()) { + int dlgRet = DlgMsgBox::message(this, QMessageBox::Question, + tr("Clean message database"), + tr("Performs a message database clean-up for the selected account. " + "This action will block the entire application. " + "The action may take several minutes to be completed. " + "Furthermore, it requires more than %1 of free disk space to successfully proceed.") + .arg(size), + tr("Do you want to continue?"), QString(), + QMessageBox::No | QMessageBox::Yes, QMessageBox::No); + if (QMessageBox::Yes != dlgRet) { return; } } @@ -8663,76 +7980,35 @@ delete task; } -void MainWindow::modifyTags(const QString &userName, QList msgIdList, - QList msgIdWebDatovkaList) +void MainWindow::modifyTags(const QString &userName, QList msgIdList) { - TagDb *tagDb = Q_NULLPTR; - - if (isWebDatovkaAccount(userName)) { - if (!wdSessions.isConnectedToWebdatovka(userName)) { - loginToMojeId(userName); - } - - if (!wdSessions.isConnectedToWebdatovka(userName)) { - showWebDatovkaInfoDialog(userName, - tr("You have to be logged into the WebDatovka if you want to modify tags.")); - return; - } - - tagDb = globWebDatovkaTagDbPtr->accessTagDb( - getWebDatovkaTagDbPrefix(userName)); - } else { - tagDb = globTagDbPtr; - } - if (tagDb == Q_NULLPTR) { + if (globTagDbPtr == Q_NULLPTR) { Q_ASSERT(0); return; } - QDialog *tagsDlg = Q_NULLPTR; + int dlgRet = DlgTags::NO_ACTION; - if (msgIdList.isEmpty() && msgIdWebDatovkaList.isEmpty()) { - tagsDlg = new DlgTags(userName, tagDb, this); - } else if (!msgIdList.isEmpty() && !msgIdWebDatovkaList.isEmpty()) { - Q_ASSERT(0); - return; - } else if ((!userName.isEmpty() && !msgIdList.isEmpty()) || - (!userName.isEmpty() && !msgIdWebDatovkaList.isEmpty())) { - /* - * FIXME -- The tags dialogue as it now exists is not suitable - * for adding tags to messages. - */ - tagsDlg = new DlgTags(userName, tagDb, msgIdList, - msgIdWebDatovkaList, this); + if (msgIdList.isEmpty()) { + dlgRet = DlgTags::editAvailable(userName, globTagDbPtr, this); + } else if ((!userName.isEmpty() && !msgIdList.isEmpty()) || (!userName.isEmpty())) { + dlgRet = DlgTags::editAssignment(userName, globTagDbPtr, + msgIdList, this); } else { Q_ASSERT(0); return; } - if (tagsDlg == Q_NULLPTR) { - Q_ASSERT(0); - return; - } - - int dlgRet = tagsDlg->exec(); - tagsDlg->deleteLater(); if (userName.isEmpty() || (dlgRet == DlgTags::NO_ACTION)) { /* Nothing else to do. */ return; } - DbMsgsTblModel *messageModel = qobject_cast( - m_messageListProxyModel.sourceModel()); - if (messageModel == Q_NULLPTR) { - Q_ASSERT(0); - return; - } - if (dlgRet == DlgTags::TAGS_CHANGED) { /* May affect all rows. */ msgIdList.clear(); - for (int row = 0; row < messageModel->rowCount(); ++row) { - msgIdList.append(messageModel->index(row, + for (int row = 0; row < m_messageTableModel.rowCount(); ++row) { + msgIdList.append(m_messageTableModel.index(row, DbMsgsTblModel::DMID_COL).data().toLongLong()); } } @@ -8741,328 +8017,8 @@ return; } - messageModel->refillTagsColumn(userName, msgIdList, -1); -} - -/* ========================================================================= */ -/* - * Func: Download and update all accounts from webdatovka. - */ -bool MainWindow::wdGetAccountList(const QString &userName, - const QNetworkCookie &sessionid, bool syncWithAll) -/* ========================================================================= */ -{ - debugFuncCall(); - - bool ret = false; - QStringList deletedAccounts; - deletedAccounts.clear(); - - /* list of accounts task */ - TaskGetAccountListMojeId *task; - task = new (std::nothrow) TaskGetAccountListMojeId(userName, sessionid, - syncWithAll, &m_accountModel, deletedAccounts); - task->setAutoDelete(false); - globWorkPool.runSingle(task); - - QString msgBoxTitle = tr("Add account(s) error"); - if (!userName.isEmpty()) { - msgBoxTitle = - AccountModel::globAccounts[userName].accountName() + " : " - + userName; - } - - QMessageBox msgBox(this); - QString msgBoxText = task->m_error; - TaskGetAccountListMojeId::Result retVal = task->m_return; - QString delAcntName = "\n"; - - delete task; - - switch (retVal) { - case TaskGetAccountListMojeId::ACNTLIST_WEBDAT_ERR: - showStatusTextWithTimeout(msgBoxText); - QMessageBox::warning(this, msgBoxTitle, msgBoxText, - QMessageBox::Ok); - break; - case TaskGetAccountListMojeId::ACNTLIST_NONEXIST: - msgBoxText = tr("There aren't any Webdatovka accounts for this " - "mojeID identity."); - showStatusTextWithTimeout(msgBoxText); - QMessageBox::warning(this, msgBoxTitle, msgBoxText, - QMessageBox::Ok); - break; - case TaskGetAccountListMojeId::ACNTLIST_WRONGUSER: - msgBoxText = tr("You are login into wrong mojeID identity."); - showStatusTextWithTimeout(msgBoxText); - QMessageBox::warning(this, msgBoxTitle, - msgBoxText + " " + tr("Please enter correct mojeID " - "login for account '%1'."). - arg(AccountModel::globAccounts[userName].accountName()), - QMessageBox::Ok); - break; - case TaskGetAccountListMojeId::ACNTLIST_WU_HAS_ACNT: - msgBoxText = tr("You are login into wrong mojeID identity."); - showStatusTextWithTimeout(msgBoxText); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setWindowTitle(msgBoxTitle); - msgBox.setText(msgBoxText + " " + - tr("New mojeID identity has some account(s).")); - msgBox.setInformativeText(tr("Do you want to add account(s) " - "for this mojeID identity to Datovka?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - if (QMessageBox::Yes == msgBox.exec()) { - ret = wdGetAccountList(QString(), sessionid, syncWithAll); - } - break; - case TaskGetAccountListMojeId::ACNTLIST_DELETE_ACNT: - foreach (const QString &username, deletedAccounts) { - delAcntName.append("\n"); - delAcntName.append(AccountModel::globAccounts[username] - .accountName()); - delAcntName.append(" (" + username + ")"); - } - msgBoxText = tr("Some account(s) were removed from Webdatovka " - "for this mojeID identity."); - showStatusTextWithTimeout(msgBoxText); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setWindowTitle(msgBoxTitle); - msgBox.setText(msgBoxText + delAcntName); - msgBox.setInformativeText(tr("Do you want to also " - "remove these accounts from Datovka?")); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - if (QMessageBox::Yes == msgBox.exec()) { - foreach (const QString &username, deletedAccounts) { - deleteAccount(username); - } - } - ret = true; - break; - default: - ret = true; - break; - } - - return ret; -} - - -/* ========================================================================= */ -/* - * Func: Download all messsages for selected account from webdatovka. - */ -bool MainWindow::wdGetMessageList(const QString &userName) -/* ========================================================================= */ -{ - debugFuncCall(); - - if (!isWebDatovkaAccount(userName)) { - return false; - } - - /* list of tags task */ - TaskTagSyncAccount *tagtask; - tagtask = new (std::nothrow) TaskTagSyncAccount(userName); - tagtask->setAutoDelete(true); - globWorkPool.assignHi(tagtask); - - int accountID = getWebDatovkaAccountId(userName); - - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { - Q_ASSERT(0); - return false; - } - - /* list of received messages task */ - TaskDownloadMessageListMojeID *task; - task = new (std::nothrow) TaskDownloadMessageListMojeID(userName, dbSet, - MSG_RECEIVED, globPref.auto_download_whole_messages, - MESSAGE_LIST_LIMIT, - accountID, 0); - task->setAutoDelete(true); - globWorkPool.assignLo(task); - - /* list of sent messages task */ - task = new (std::nothrow) TaskDownloadMessageListMojeID(userName, dbSet, - MSG_SENT, globPref.auto_download_whole_messages, - MESSAGE_LIST_LIMIT, - accountID, 0); - task->setAutoDelete(true); - globWorkPool.assignLo(task); - - return true; -} - - -/* ========================================================================= */ -/* - * Func: Sync selected account in webdatovka server. - */ -bool MainWindow::wdSyncAccount(const QString &userName) -/* ========================================================================= */ -{ - debugFuncCall(); - - if (!isWebDatovkaAccount(userName)) { - return false; - } - - if (!wdSessions.isConnectedToWebdatovka(userName)) { - loginToMojeId(userName); - } - - if (!wdSessions.isConnectedToWebdatovka(userName)) { - return false; - } - - int accountID = getWebDatovkaAccountId(userName); - - /* sync account task */ - TaskSyncAccount *task; - task = new (std::nothrow) TaskSyncAccount(userName, accountID); - task->setAutoDelete(true); - globWorkPool.assignHi(task); - - return wdGetMessageList(userName); -} - - -/* ========================================================================= */ -/* - * Func: Show dialog for webdatovka account, that action is not supported. - */ -void MainWindow::showWebDatovkaInfoDialog(const QString &userName, QString txt) -/* ========================================================================= */ -{ - debugFuncCall(); - - if (txt.isEmpty()) { - txt = tr("This action is not supported for MojeID account " - "'%1'").arg(AccountModel::globAccounts[userName].accountName()); - } - showStatusTextWithTimeout(txt); - QMessageBox::warning(this, - AccountModel::globAccounts[userName].accountName() + " : " - + userName, txt, QMessageBox::Ok); -} - - -/* ========================================================================= */ -/* - * Slot: Performs action depending on webdatovka message send outcome. - */ -void MainWindow::sendMessageMojeIdAction(const QString &userName, - const QStringList &result, const QString &error) -/* ========================================================================= */ -{ - debugSlotCall(); - - if (!error.isEmpty()) { - qDebug() << error; - return; - } - - if (result.isEmpty()) { - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { - return; - } - - TaskDownloadMessageListMojeID *task; - task = new (std::nothrow) TaskDownloadMessageListMojeID( - userName, dbSet, MSG_SENT, - globPref.auto_download_whole_messages, MESSAGE_LIST_LIMIT, - getWebDatovkaAccountId(userName), 0); - task->setAutoDelete(true); - globWorkPool.assignLo(task); - } -} - - -/* ========================================================================= */ -/* - * Slot: Login to MojeID - first step. - */ -void MainWindow::loginToMojeId(const QString &userName) -/* ========================================================================= */ -{ - debugSlotCall(); - - QUrl lastUrl; - jsonlayer.startLoginToWebDatovka(lastUrl); - - QDialog *mojeIDLoginDialog = new DlgLoginToMojeId(userName, - lastUrl.toString(), this); - - connect(mojeIDLoginDialog, SIGNAL(callMojeId(QString, QString, QString, - QString, QString, QString, bool, QString)), - this, SLOT(callMojeId(QString, - QString, QString, QString, QString, QString, bool, QString))); - - mojeIDLoginDialog->exec(); -} - - -/* ========================================================================= */ -/* - * Slot: Login to MojeID - second step. - */ -void MainWindow::callMojeId(const QString &user, - const QString &lastUrl, const QString &token, - QString userName, QString pwd, QString otp, bool syncALL, - const QString &certPath) -/* ========================================================================= */ -{ - debugSlotCall(); - - QString error; - - QNetworkCookie sessionid; - - if (!jsonlayer.loginToMojeID(lastUrl, token, userName, pwd, otp, - certPath, error, sessionid)) { - showStatusTextWithTimeout(error); - QMessageBox::critical(this, tr("Login problem"), - error, QMessageBox::Ok); - return; - } else { - mui_statusOnlineLabel->setText(tr("Mode: online")); - } - - wdGetAccountList(user, sessionid, syncALL); - - if (ui->accountList->model()->rowCount() > 0) { - activeAccountMenuAndButtons(true); - } -} - - -/* ========================================================================= */ -/* - * Func: Test if exists another mojeID account with same userId - * when we delete any mojeID acccount. - */ -bool MainWindow::existsAnotherMojeIdAccountWithSameUserId( - const QString &userName) -/* ========================================================================= */ -{ - AccountsMap::iterator i; - int cnt = 0; - int userId = getWebDatovkaUserId(userName); - - for (i = m_accountModel.globAccounts.begin(); - i != m_accountModel.globAccounts.end(); ++i) { - if (isWebDatovkaAccount(i->userName())) { - if (userId == getWebDatovkaUserId(i->userName())) { - cnt++; - } - } - } - - return (cnt > 1); + m_messageTableModel.refillTagsColumn(userName, msgIdList, + DbMsgsTblModel::TAGS_NEG_COL); } void MainWindow::doExportOfSelectedFiles( @@ -9077,20 +8033,14 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - if (isWebDatovkaAccount(userName)) { - /* TODO - will be supported later */ - showWebDatovkaInfoDialog(userName, ""); - return; - } - const QList msgIds( msgMsgIds(currentFrstColMessageIndexes())); if (0 == msgIds.size()) { return; } - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + MessageDbSet *dbSet = accountDbSet(userName); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } @@ -9140,29 +8090,22 @@ void MainWindow::showImportMessageResults(const QString &userName, const QStringList &errImportList, int totalMsgs, int importedMsgs) { - showStatusTextPermanently(tr("Import of messages to account %1 " - "finished").arg(userName)); + showStatusTextPermanently( + tr("Import of messages to account %1 finished").arg(userName)); - QMessageBox msgBox(this); - msgBox.setIcon(QMessageBox::Information); - msgBox.setWindowTitle(tr("Messages import result")); - QString msg = tr("Import of messages into account '%1' " - "finished with result:").arg(userName); - msgBox.setText(msg); - msg = tr("Total of messages in database: %1").arg(totalMsgs) - + "
    " + - tr("Imported messages: %1").arg(importedMsgs) - + "
    " + - tr("Non-imported messages: %1").arg(errImportList.count()) + - "

    "; - msgBox.setInformativeText(msg); + QString detailText; if (errImportList.count() > 0) { - msg = ""; for (int m = 0; m < errImportList.count(); ++ m) { - msg += errImportList.at(m) + "\n"; + detailText += errImportList.at(m) + "\n"; } - msgBox.setDetailedText(msg); } - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.exec(); + + DlgMsgBox::message(this, QMessageBox::Information, + tr("Messages import result"), + tr("Import of messages into account '%1' finished with result:") + .arg(userName), + tr("Total of messages in database: %1").arg(totalMsgs) + "
    " + + tr("Imported messages: %1").arg(importedMsgs) + "
    " + + tr("Non-imported messages: %1").arg(errImportList.count()) + "

    ", + detailText, QMessageBox::Ok); } diff -Nru datovka-4.8.3/src/gui/datovka.h datovka-4.9.3/src/gui/datovka.h --- datovka-4.8.3/src/gui/datovka.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/datovka.h 2017-09-06 11:49:23.000000000 +0000 @@ -24,7 +24,6 @@ #ifndef _DATOVKA_H_ #define _DATOVKA_H_ - #include #include #include @@ -44,10 +43,11 @@ #include "src/gui/dlg_import_zfo.h" #include "src/gui/dlg_timestamp_expir.h" #include "src/models/accounts_model.h" +#include "src/models/files_model.h" +#include "src/models/messages_model.h" #include "src/models/sort_filter_proxy_model.h" #include "src/settings/preferences.h" #include "src/single/single_instance.h" -#include "src/web/json.h" #include "src/worker/task.h" /* TODO -- remove this header file. */ /* Forward declaration as we don;t wan to pull-in all header file content. */ @@ -57,21 +57,14 @@ class MainWindow; } - class MainWindow : public QMainWindow { Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget *parent = Q_NULLPTR); ~MainWindow(void); /*! - * @brief Create configuration file if not present. - */ - static - bool ensureConfPresence(void); - - /*! * @brief Connects to ISDS and downloads basic information about the * user. * @@ -82,20 +75,9 @@ /*! * @brief Get message db set related to given account. * - * @note If pointer to main window is not specified, then all dialogues - * will be suppressed. - * * @param userName Account login. - * @param mw Pointer to main window. */ - static - MessageDbSet *accountDbSet(const QString &userName, MainWindow *mw); - - /*! - * @brief Get account list from Webdatovka. - */ - bool wdGetAccountList(const QString &userName, - const QNetworkCookie &sessionid, bool syncWithAll); + MessageDbSet *accountDbSet(const QString &userName); protected: /*! @@ -119,18 +101,11 @@ /*! * @brief Check window geometry, adjust size if window is too large for - * desktop.. + * desktop. */ virtual void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; -public slots: - - /*! - * @brief Login to mojeID. - */ - void loginToMojeId(const QString &userName); - private slots: /*! * @brief Refresh AccountList. @@ -156,14 +131,6 @@ bool listScheduled); /*! - * @brief Performs action depending on message download outcome - * for webdatovka. - */ - void collectDownloadMessageMojeId(const QString &usrName, - qint64 msgId, int result, const QString &errDesc, - bool listScheduled); - - /*! * @brief Performs action depending on message list download outcome. */ void collectDownloadMessageListStatus(const QString &usrName, @@ -185,12 +152,6 @@ bool isPDZ, qint64 dmId); /*! - * @brief Performs action depending on webdatovka message send outcome. - */ - void sendMessageMojeIdAction(const QString &userName, - const QStringList &result, const QString &error); - - /*! * @brief Version response slot. */ void datovkaVersionResponce(QNetworkReply* reply); @@ -399,11 +360,6 @@ void deleteMessage(void); /*! - * @brief Delete selected message(s) from local database and Webdatovka. - */ - void deleteMessageWebdatovka(const QString &userName); - - /*! * @brief Downloads new messages from server for all accounts. */ void synchroniseAllAccounts(void); @@ -419,7 +375,7 @@ bool synchroniseSelectedAccount(QString userName = QString()); /*! - * @brief Downloads the attachments for the selected message. + * @brief Downloads attachments of selected messages. */ void downloadSelectedMessageAttachments(void); @@ -470,11 +426,6 @@ void showAddNewAccountDialog(void); /*! - * @brief Add mojeID account action and dialog. - */ - void addNewMojeIDAccount(void); - - /*! * @brief Deletion confirmation dialog. */ void deleteSelectedAccount(void); @@ -490,11 +441,6 @@ void showImportDatabaseDialog(void); /*! - * @brief Prepare import database directory. - */ - void prepareCreateAccountFromDatabaseFile(bool fromDirectory); - - /*! * @brief Prepare import of messages from database. */ void prepareMsgsImportFromDatabase(void); @@ -505,6 +451,11 @@ void showProxySettingsDialog(void); /*! + * @brief Records management dialogue. + */ + void showRecordsManagementDialogue(void); + + /*! * @brief Move selected account up. */ void moveSelectedAccountUp(void); @@ -576,6 +527,17 @@ void openDeliveryInfoExternally(void); /*! + * @brief Obtain information about stored messages from records + * management. + */ + void getStoredMsgInfoFromRecordsManagement(void); + + /*! + * @brief Send message to records management. + */ + void sendSelectedMessageToRecordsManagement(void); + + /*! * @brief Search data box dialog. */ void findDatabox(void); @@ -616,11 +578,6 @@ void goHome(void); /*! - * @brief Clear message filter field. - */ - void clearFilterField(void); - - /*! * @brief Filter listed messages. */ void filterMessages(const QString &text); @@ -661,13 +618,6 @@ void setWindowsAfterInit(void); /*! - * @brief Receive and store new account database path. Change data - * directory path in settings. - */ - void receiveNewDataPath(QString oldDir, QString newDir, - QString action); - - /*! * @brief set message process state into db */ void msgSetSelectedMessageProcessState(int stateIndex); @@ -718,10 +668,6 @@ */ void vacuumMsgDbSlot(void); - void callMojeId(const QString &user, const QString &lastUrl, - const QString &token, QString userName, QString pwd, QString otp, - bool syncALL, const QString &certPath); - /*! * @brief Show information about import message results. */ @@ -742,21 +688,8 @@ * @param[in] userName Account login string. Must be supplied when * message identifiers are passed. * @param[in] msgIdList Messages whose tags should be edited. - * @param[in] msgIdWebDatovkaList Webdatovka messages whose tags should - * be edited. - */ - void modifyTags(const QString &userName, QList msgIdList, - QList msgIdWebDatovkaList); - - /*! - * @brief Get message list from webdatovka server. - */ - bool wdGetMessageList(const QString &userName); - - /*! - * @brief Do sync of account in the webdatovka server. */ - bool wdSyncAccount(const QString &userName); + void modifyTags(const QString &userName, QList msgIdList); /*! * @brief Show status bar text with timeout. @@ -807,11 +740,6 @@ const QString &year, int msgType); /*! - * @brief Return index for message with given properties. - */ - QModelIndex messageIndex(qint64 msgId) const; - - /*! * @brief Check message time stamp expiration for account. */ void checkMsgsTmstmpExpiration(const QString &userName, @@ -1061,12 +989,6 @@ void checkNewDatovkaVersion(void); /*! - * @brief Sent and check a new version of Datovka. - */ - void createAccountFromDatabaseFileList( - const QStringList &filePathList); - - /*! * @brief Download complete message synchronously * without worker and thread. * @@ -1115,23 +1037,6 @@ const QList &expirMsgIds); /*! - * @brief Show dialog for webdatovka account - * that action is not implemented. - * @param[in] userName - account username. - * @param[in] txt additional info text. - */ - void showWebDatovkaInfoDialog(const QString &userName, QString txt); - - /*! - * @brief Test if exists another mojeID account with same userId - * when we delete any mojeID acccount. - * - * @param[in] userName - account username. - * @return true if any account exists - */ - bool existsAnotherMojeIdAccountWithSameUserId(const QString &userName); - - /*! * @brief Export selected messages to disk. * * @param[in] expFileType - export file type. @@ -1153,10 +1058,12 @@ * Account tree view model. Generated from * configuration file. */ + DbMsgsTblModel m_messageTableModel; /*!< Message table model. */ SortFilterProxyModel m_messageListProxyModel; /*!< * Used for message * sorting and filtering. */ + DbFlsTblModel m_attachmentModel; /*! Attachment table model. */ QTimer m_messageMarker; /*!< Used for marking messages as read. */ qint64 m_lastSelectedMessageId; /*!< Id of the last selected message. */ @@ -1182,7 +1089,7 @@ QString m_import_zfo_path; QRect m_geometry; /* Non-maximised window geometry. */ - QStringList m_msgTblAppendedCols; /*< Appended columns. */ + QList m_msgTblAppendedCols; /*< Appended columns. */ QSet m_zfoFilesToImport; /*!< Set of files to be imported. */ int m_numFilesToImport; /*!< Input ZFO count. */ @@ -1196,7 +1103,6 @@ /* User interface elements. */ Ui::MainWindow *ui; /*!< User interface as generated from ui files. */ QLineEdit *mui_filterLine; /*!< Search filter line object. */ - QPushButton *mui_clearFilterLineButton; /*!< Clear filter button. */ QStatusBar *mui_statusBar; /*!< Status bar. */ QLabel *mui_statusDbMode; /*!< Database status label. */ QLabel *mui_statusOnlineLabel; /*< On-line/off-line status label. */ diff -Nru datovka-4.8.3/src/gui/dlg_about.cpp datovka-4.9.3/src/gui/dlg_about.cpp --- datovka-4.8.3/src/gui/dlg_about.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_about.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,27 +21,19 @@ * the two. */ -#if defined(__APPLE__) || defined(__clang__) -# define __USE_C99_MATH -# define _Bool bool -#else /* !__APPLE__ */ -# include -#endif /* __APPLE__ */ - -#include -#include -#include /* SSLeay_version(3) */ -#include - +#include "src/about.h" +#include "src/common.h" #include "src/gui/dlg_about.h" #include "src/io/filesystem.h" +#include "ui_dlg_about.h" DlgAbout::DlgAbout(QWidget *parent) - : QDialog(parent) + : QDialog(parent), + m_ui(new (std::nothrow) Ui::DlgAbout) { - setupUi(this); + m_ui->setupUi(this); - this->labelVersion->setText( + m_ui->labelVersion->setText( "Datovka" #ifdef PORTABLE_APPLICATION " - " + tr("Portable version") + @@ -51,12 +43,12 @@ "" + tr("Version") + ": " VERSION "" "
    " + tr("Free client for Czech eGov data boxes.")); - this->labelVersion->setAlignment(Qt::AlignHCenter); - this->labelVersion->setTextFormat(Qt::RichText); - this->labelVersion->setTextInteractionFlags(Qt::TextBrowserInteraction); + m_ui->labelVersion->setAlignment(Qt::AlignHCenter); + m_ui->labelVersion->setTextFormat(Qt::RichText); + m_ui->labelVersion->setTextInteractionFlags(Qt::TextBrowserInteraction); QString copyrightHtml( - "Copyright © 2014–2016 CZ.NIC, z. s. p. o. " + "Copyright © 2014–2017 CZ.NIC, z. s. p. o. " "<" CZ_NIC_URL ">"); copyrightHtml += "
    " + tr("Additional informations") + ": " "" + tr("home page") + "" @@ -66,52 +58,58 @@ "" + tr("FAQ") + ""; copyrightHtml += "
    " + tr("Support") + ": " "<" SUPPORT_MAIL ">"; - this->labelCopy->setText(copyrightHtml); - this->labelCopy->setTextFormat(Qt::RichText); - this->labelCopy->setTextInteractionFlags(Qt::TextBrowserInteraction); - this->labelCopy->setOpenExternalLinks(true); + m_ui->labelCopy->setText(copyrightHtml); + m_ui->labelCopy->setTextFormat(Qt::RichText); + m_ui->labelCopy->setTextInteractionFlags(Qt::TextBrowserInteraction); + m_ui->labelCopy->setOpenExternalLinks(true); QString librariesStr(""); librariesStr += QObject::tr("Depends on libraries:"); librariesStr += "
    "; - this->labelLibs->setText(librariesStr + + m_ui->labelLibs->setText(librariesStr + libraryDependencies().join("
    ")); - this->labelLibs->setTextFormat(Qt::RichText); - this->labelLibs->setTextInteractionFlags(Qt::TextBrowserInteraction); - this->labelLibs->setAlignment(Qt::AlignHCenter); - this->labelLibs->setWordWrap(true); + m_ui->labelLibs->setTextFormat(Qt::RichText); + m_ui->labelLibs->setTextInteractionFlags(Qt::TextBrowserInteraction); + m_ui->labelLibs->setAlignment(Qt::AlignHCenter); + m_ui->labelLibs->setWordWrap(true); - connect(this->pushButtonLicence, SIGNAL(clicked()), this, + connect(m_ui->pushButtonLicence, SIGNAL(clicked()), this, SLOT(showLicence())); - connect(this->pushButtonCredits, SIGNAL(clicked()), this, + connect(m_ui->pushButtonCredits, SIGNAL(clicked()), this, SLOT(showCredits())); - connect(this->buttonBox, SIGNAL(accepted()), this, SLOT(close())); + connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(close())); } -QStringList DlgAbout::libraryDependencies(void) +DlgAbout::~DlgAbout(void) { - QStringList libs; - - libs.append(QStringLiteral("Qt ") + qVersion()); - - char *isdsVer = isds_version(); - libs.append(QStringLiteral("libisds ") + isdsVer); - free(isdsVer); isdsVer = NULL; - - libs.append(SSLeay_version(SSLEAY_VERSION)); + delete m_ui; +} - return libs; +void DlgAbout::about(QWidget *parent) +{ + DlgAbout dlg(parent); + dlg.exec(); } void DlgAbout::showLicence(void) { - this->textEdit->setPlainText( + m_ui->textEdit->setPlainText( suppliedTextFileContent(TEXT_FILE_LICENCE)); + if (m_ui->textEdit->toPlainText().isEmpty()) { + m_ui->textEdit->setPlainText( + tr("File '%1' either doesn't exist or is empty.") + .arg(expectedTextFilePath(TEXT_FILE_LICENCE))); + } } void DlgAbout::showCredits(void) { - this->textEdit->setPlainText( + m_ui->textEdit->setPlainText( suppliedTextFileContent(TEXT_FILE_CREDITS)); + if (m_ui->textEdit->toPlainText().isEmpty()) { + m_ui->textEdit->setPlainText( + tr("File '%1' either doesn't exist or is empty.") + .arg(expectedTextFilePath(TEXT_FILE_CREDITS))); + } } diff -Nru datovka-4.8.3/src/gui/dlg_about.h datovka-4.9.3/src/gui/dlg_about.h --- datovka-4.8.3/src/gui/dlg_about.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_about.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,33 +25,38 @@ #define _DLG_ABOUT_H_ #include -#include -#include "src/common.h" -#include "ui_dlg_about.h" +namespace Ui { + class DlgAbout; +} /*! * @brief About dialogue. */ -class DlgAbout : public QDialog, public Ui::AboutDialog { +class DlgAbout : public QDialog { Q_OBJECT -public: +private: /*! * @brief Constructor. * * @param[in] parent Parent object. */ - explicit DlgAbout(QWidget *parent = 0); + explicit DlgAbout(QWidget *parent = Q_NULLPTR); + +public: + /*! + * @brief Destructor. + */ + ~DlgAbout(void); /*! - * @brief Obtain list of strings containing libraries which the - * application depends on. + * @brief View about dialogue. * - * @return List of strings containing library descriptions. + * @param[in] parent Window parent widget. */ static - QStringList libraryDependencies(void); + void about(QWidget *parent = Q_NULLPTR); private slots: /*! @@ -63,6 +68,9 @@ * @brief Displays credits information in the text field. */ void showCredits(void); + +private: + Ui::DlgAbout *m_ui; /*!< UI generated from UI file. */ }; #endif /* _DLG_ABOUT_H_ */ diff -Nru datovka-4.8.3/src/gui/dlg_account_from_db.cpp datovka-4.9.3/src/gui/dlg_account_from_db.cpp --- datovka-4.8.3/src/gui/dlg_account_from_db.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_account_from_db.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,32 +21,228 @@ * the two. */ +#include +#include -#include "dlg_account_from_db.h" #include "src/common.h" +#include "src/gui/dlg_account_from_db.h" +#include "src/log/log.h" +#include "ui_dlg_account_from_db.h" -CreateAccountFromDbDialog::CreateAccountFromDbDialog(QWidget *parent) : - QDialog(parent) +DlgCreateAccountFromDb::DlgCreateAccountFromDb(QWidget *parent) + : QDialog(parent), + m_ui(new (std::nothrow) Ui::DlgCreateAccountFromDb) { - setupUi(this); - this->info->setText(tr("A new account will be created according to " - "the name and the content of the database file. This account will " - "operate over the selected database. Should such an account or " - "database file already exist in Datovka then the association will fail." - " During the association no database file copy is created nor is the " - "content of the database file modified. Nevertheless, we strongly" - " advice you to back-up all important files before associating a " - "database file. In order for the association to succeed you will need " - "an active connection to the ISDS server.")); - connect(this->buttonBox, SIGNAL(accepted()), - this, SLOT(CreateAccountFromDbDialogAction())); + m_ui->setupUi(this); + m_ui->info->setText(tr( + "A new account will be created according to the name and the content of the database file. " + "This account will operate over the selected database. " + "Should such an account or database file already exist in Datovka then the association will fail. " + "During the association no database file copy is created nor is the content of the database file modified. " + "Nevertheless, we strongly advice you to back-up all important files before associating a database file. " + "In order for the association to succeed you will need an active connection to the ISDS server.")); } -void CreateAccountFromDbDialog::CreateAccountFromDbDialogAction(void) +DlgCreateAccountFromDb::~DlgCreateAccountFromDb(void) { - if (this->directory->isChecked()) { - emit returnAction(true); + delete m_ui; +} + +/*! + * @brief Obtain full path to directory where a file lies in. + * + * @param[in] filePath File path. + * @return Absolute directory path. + */ +#define absoluteDirPath(filePath) \ + QFileInfo((filePath)).absoluteDir().absolutePath() + +/*! + * @brief Get all database files in user-selected location. + * + * @param[in] fromDirectory True if whole directories should be scanned, + * false if only selected files should be used. + * @param[in,out] lastImportDir Import location directory. + * @param[in] parent Parent widget. + * @return List of database files. + */ +static +QStringList getDatabaseFilesFromLocation(bool fromDirectory, + QString &lastImportDir, QWidget *parent = Q_NULLPTR) +{ + QStringList filePathList; + + if (fromDirectory) { + QString importDir = QFileDialog::getExistingDirectory(parent, + DlgCreateAccountFromDb::tr("Select directory"), lastImportDir, + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + if (importDir.isEmpty()) { + return QStringList(); + } + + lastImportDir = importDir; + QStringList fileList( + QDir(importDir).entryList(QStringList("*.db"))); + + if (fileList.isEmpty()) { + logWarningNL("%s", "No selected *.db files."); + QMessageBox::warning(parent, + DlgCreateAccountFromDb::tr("No database file found"), + DlgCreateAccountFromDb::tr("No database file found in selected directory '%1'.") + .arg(importDir), + QMessageBox::Ok); + return QStringList(); + } + + foreach (const QString &fileName, fileList) { + filePathList.append(importDir + "/" + fileName); + } + } else { + filePathList = QFileDialog::getOpenFileNames(parent, + DlgCreateAccountFromDb::tr("Select database files"), lastImportDir, + DlgCreateAccountFromDb::tr("Database file (*.db)")); + + if (filePathList.isEmpty()) { + logWarningNL("%s", "No selected *.db files."); + return QStringList(); + } + + lastImportDir = absoluteDirPath(filePathList.at(0)); + } + + return filePathList; +} + +/*! + * @brief Create accounts from supplied database files. + * + * @param[in,out] accountModel Account model to add account data into. + * @param[in] filePathList List of database file paths. + * @param[in] parent Parent widget. + * @return List of user names of newly created accounts. + */ +static +QStringList createAccountsFromDatabaseFiles(AccountModel &accountModel, + const QStringList &filePathList, QWidget *parent = Q_NULLPTR) +{ + if (filePathList.isEmpty()) { + return QStringList(); + } + + QStringList accountUserNames; + const int accountCount = accountModel.rowCount(); + for (int i = 0; i < accountCount; ++i) { + const QModelIndex index(accountModel.index(i, 0)); + const QString userName(accountModel.userName(index)); + Q_ASSERT(!userName.isEmpty()); + accountUserNames.append(userName); + } + + QStringList createdAccountUserNames; + + foreach (const QString &filePath, filePathList) { + const QString dbFileName(QFileInfo(filePath).fileName()); + QString dbUserName; + QString dbYearFlag; + bool dbTestingFlag; + QString errMsg; + + /* Split and check the database file name. */ + if (!isValidDatabaseFileName(dbFileName, dbUserName, + dbYearFlag, dbTestingFlag, errMsg)) { + QMessageBox::warning(parent, + DlgCreateAccountFromDb::tr("Create account: %1") + .arg(dbUserName), + DlgCreateAccountFromDb::tr("File") + ": " + + filePath + "\n\n" + errMsg, + QMessageBox::Ok); + continue; + } + + /* Check whether account already exists. */ + bool exists = false; + for (int j = 0; j < accountCount; ++j) { + if (accountUserNames.at(j) == dbUserName) { + exists = true; + break; + } + } + if (exists) { + errMsg = DlgCreateAccountFromDb::tr( + "Account with user name '%1' and its message database already exist. " + "New account was not created and selected database file was not associated with this account.") + .arg(dbUserName); + QMessageBox::warning(parent, + DlgCreateAccountFromDb::tr("Create account: %1") + .arg(dbUserName), + DlgCreateAccountFromDb::tr("File") + ": " + + filePath + "\n\n" + errMsg, + QMessageBox::Ok); + continue; + } + + AcntSettings itemSettings; + itemSettings.setTestAccount(dbTestingFlag); + itemSettings.setAccountName(dbUserName); + itemSettings.setUserName(dbUserName); + itemSettings.setLoginMethod(AcntSettings::LIM_UNAME_PWD); + itemSettings.setPassword(""); + itemSettings.setRememberPwd(false); + itemSettings.setSyncWithAll(false); + itemSettings.setDbDir(absoluteDirPath(filePath)); + accountModel.addAccount(itemSettings); + errMsg = DlgCreateAccountFromDb::tr( + "Account with name '%1' has been created (user name '%1').") + .arg(dbUserName) + " " + + DlgCreateAccountFromDb::tr( + "This database file has been set as the actual message database for this account. " + "You'll probably have to modify the account properties in order to log in to the ISDS server correctly."); + + QMessageBox::information(parent, + DlgCreateAccountFromDb::tr("Create account: %1") + .arg(dbUserName), + DlgCreateAccountFromDb::tr("File") + ": " + + filePath + "\n\n" + errMsg, + QMessageBox::Ok); + + createdAccountUserNames.append(dbUserName); + } + + return createdAccountUserNames; +} + +QStringList DlgCreateAccountFromDb::createAccount(AccountModel &accountModel, + QString &lastImportDir, QWidget *parent) +{ + QStringList dbFilePathList; + + switch (chooseAction(parent)) { + case ACT_FROM_DIRECTORY: + dbFilePathList = getDatabaseFilesFromLocation(true, + lastImportDir, parent); + break; + case ACT_FROM_FILES: + dbFilePathList = getDatabaseFilesFromLocation(false, + lastImportDir, parent); + break; + default: + /* Do nothing. */ + return QStringList(); + } + + return createAccountsFromDatabaseFiles(accountModel, dbFilePathList, + parent); +} + +enum DlgCreateAccountFromDb::Action DlgCreateAccountFromDb::chooseAction( + QWidget *parent) +{ + DlgCreateAccountFromDb dlg(parent); + if (QDialog::Accepted == dlg.exec()) { + return dlg.m_ui->directory->isChecked() ? ACT_FROM_DIRECTORY : + ACT_FROM_FILES; } else { - emit returnAction(false); + return ACT_NOTHING; } } diff -Nru datovka-4.8.3/src/gui/dlg_account_from_db.h datovka-4.9.3/src/gui/dlg_account_from_db.h --- datovka-4.8.3/src/gui/dlg_account_from_db.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_account_from_db.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,25 +21,72 @@ * the two. */ - #ifndef _DLG_ACCOUNT_FROM_DB_H_ #define _DLG_ACCOUNT_FROM_DB_H_ #include -#include "src/common.h" -#include "ui_dlg_account_from_db.h" +#include + +#include "src/models/accounts_model.h" + +namespace Ui { + class DlgCreateAccountFromDb; +} -class CreateAccountFromDbDialog : public QDialog, public Ui::CreateAccountFromDb -{ +/*! + * @brief Provides interface for account creation from database. + */ +class DlgCreateAccountFromDb : public QDialog { Q_OBJECT +private: + /*! + * @brief Constructor. + * + * @param[in] parent Parent widget. + */ + explicit DlgCreateAccountFromDb(QWidget *parent = Q_NULLPTR); + public: - CreateAccountFromDbDialog(QWidget *parent = 0); -signals: - void returnAction(bool); + /*! + * @brief Destructor. + */ + virtual + ~DlgCreateAccountFromDb(void); + + /*! + * @brief Creates an accounts from database files and adds them into + * account model. + * + * @param[in,out] accountModel Account model to add data into. + * @param[in,out] lastImportDir Import location directory. + * @param[in] parent Parent widget. + * @return List of user names of newly created accounts. + */ + static + QStringList createAccount(AccountModel &accountModel, + QString &lastImportDir, QWidget *parent = Q_NULLPTR); + +private: + /*! + * @brief Action chosen by the user. + */ + enum Action { + ACT_NOTHING, /*!< Nothing to be performed. */ + ACT_FROM_DIRECTORY, /*!< Read directory content. */ + ACT_FROM_FILES /*!< Read selected files. */ + }; + + /*! + * @brief Select source to import database from. + * + * @param[in] parent Parent widget. + * @return Chosen action. + */ + static + enum Action chooseAction(QWidget *parent = Q_NULLPTR); -private slots: - void CreateAccountFromDbDialogAction(void); + Ui::DlgCreateAccountFromDb *m_ui; /*!< UI generated from UI file. */ }; #endif /* _DLG_ACCOUNT_FROM_DB_H_ */ diff -Nru datovka-4.8.3/src/gui/dlg_change_directory.cpp datovka-4.9.3/src/gui/dlg_change_directory.cpp --- datovka-4.8.3/src/gui/dlg_change_directory.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_change_directory.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,92 +21,210 @@ * the two. */ - #include +#include -#include "dlg_change_directory.h" +#include "src/gui/dlg_change_directory.h" +#include "src/io/message_db_set.h" #include "src/log/log.h" +#include "src/settings/accounts.h" +#include "src/settings/preferences.h" +#include "ui_dlg_change_directory.h" + +DlgChangeDirectory::DlgChangeDirectory(const QString ¤tDir, + QWidget *parent) + : QDialog(parent), + m_ui(new (std::nothrow) Ui::DlgChangeDirectory) +{ + m_ui->setupUi(this); + + m_ui->newPath->setText(""); + m_ui->currentPath->setText(currentDir); + m_ui->labelWarning->setStyleSheet("QLabel { color: red }"); + + if (m_ui->newPath->text().isEmpty()) { + m_ui->labelWarning->hide(); + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } else if (m_ui->currentPath->text() != m_ui->newPath->text()) { + m_ui->labelWarning->hide(); + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } else { + m_ui->labelWarning->show(); + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + + connect(m_ui->chooseButton, SIGNAL(clicked()), this, + SLOT(chooseNewDirectory(void))); +} -DlgChangeDirectory::DlgChangeDirectory(QString dirPath, QWidget *parent) : - QDialog(parent), - m_dirPath(dirPath) +DlgChangeDirectory::~DlgChangeDirectory(void) { - setupUi(this); - initDialog(); + delete m_ui; } -/* ========================================================================= */ -/* - * Init dialog - */ -void DlgChangeDirectory::initDialog(void) -/* ========================================================================= */ +bool DlgChangeDirectory::changeDataDirectory(const QString &userName, + MessageDbSet *dbSet, QWidget *parent) { - this->newPath->setText(""); - this->currentPath->setText(m_dirPath); - this->labelWarning->setStyleSheet("QLabel { color: red }"); - - if (this->newPath->text().isEmpty() || this->newPath->text().isNull()) { - this->labelWarning->hide(); - this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - } else if (this->currentPath->text() != this->newPath->text()) { - this->labelWarning->hide(); - this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); - } else { - this->labelWarning->show(); - this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + if (Q_UNLIKELY(userName.isEmpty() || (dbSet == Q_NULLPTR))) { + Q_ASSERT(0); + return false; } - connect(this->chooseButton, SIGNAL(clicked()), this, - SLOT(onDirectoryChange(void))); + enum Action action = ACT_MOVE; + QString newDirPath; - connect(this->buttonBox, SIGNAL(accepted()), this, - SLOT(setNewDataDirectory(void))); -} + /* Get current settings. */ + const AcntSettings &itemSettings(globAccounts[userName]); + QString oldDbDir(itemSettings.dbDir()); + if (oldDbDir.isEmpty()) { + /* Set default directory name. */ + oldDbDir = globPref.confDir(); + } -/* ========================================================================= */ -/* - * Choose new data directory - */ -void DlgChangeDirectory::onDirectoryChange(void) -/* ========================================================================= */ + if (!chooseAction(oldDbDir, newDirPath, action, parent)) { + return false; + } + + if (Q_UNLIKELY(newDirPath.isEmpty())) { + Q_ASSERT(0); + return false; + } + + return relocateDatabase(userName, dbSet, oldDbDir, newDirPath, action, + parent); +} + +void DlgChangeDirectory::chooseNewDirectory(void) { - QString newdir = QFileDialog::getExistingDirectory(this, - tr("Open Directory"), NULL, QFileDialog::ShowDirsOnly | - QFileDialog::DontResolveSymlinks); - this->newPath->setText(newdir); - - if (this->newPath->text().isEmpty() || this->newPath->text().isNull()) { - this->labelWarning->hide(); - this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - } else if (this->currentPath->text() != this->newPath->text()) { - this->labelWarning->hide(); - this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + QString newDir(QFileDialog::getExistingDirectory(this, + tr("Open Directory"), QString(), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks)); + m_ui->newPath->setText(newDir); + + if (m_ui->newPath->text().isEmpty()) { + m_ui->labelWarning->hide(); + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } else if (m_ui->currentPath->text() != m_ui->newPath->text()) { + m_ui->labelWarning->hide(); + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); } else { - this->labelWarning->show(); - this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + m_ui->labelWarning->show(); + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); } } +bool DlgChangeDirectory::chooseAction(const QString ¤tDir, + QString &newDir, enum Action &action, QWidget *parent) +{ + DlgChangeDirectory dlg(currentDir, parent); + if (QDialog::Accepted == dlg.exec()) { + newDir = dlg.m_ui->newPath->text(); + if (dlg.m_ui->moveDataRadioButton->isChecked()) { + action = ACT_MOVE; + } else if (dlg.m_ui->copyDataRadioButton->isChecked()) { + action = ACT_COPY; + } else { + action = ACT_NEW; + } + return true; + } else { + return false; + } +} -/* ========================================================================= */ -/* - * Set new data directory and save path - */ -void DlgChangeDirectory::setNewDataDirectory(void) -/* ========================================================================= */ +bool DlgChangeDirectory::relocateDatabase(const QString &userName, + MessageDbSet *dbSet, const QString &oldDir, const QString &newDir, + enum Action action, QWidget *parent) { - debugSlotCall(); + if (Q_UNLIKELY(userName.isEmpty()) || (dbSet == Q_NULLPTR)) { + Q_ASSERT(0); + return false; + } - QString action; - if (this->moveDataRadioButton->isChecked()) { - action = "move"; - } else if (this->copyDataRadioButton->isChecked()) { - action = "copy"; - } else { - action = "new"; + /* Get current settings. */ + AcntSettings &itemSettings(globAccounts[userName]); + + switch (action) { + case ACT_MOVE: + /* Move account database into new directory. */ + if (dbSet->moveToLocation(newDir)) { + itemSettings.setDbDir(newDir); + + logInfo("Database files for '%s' have been moved from '%s' to '%s'.\n", + userName.toUtf8().constData(), + oldDir.toUtf8().constData(), + newDir.toUtf8().constData()); + + QMessageBox::information(parent, + tr("Change data directory for current account"), + tr("Database files for '%1' have been successfully moved to\n\n'%2'.") + .arg(userName).arg(newDir), + QMessageBox::Ok); + + return true; + } else { + QMessageBox::critical(parent, + tr("Change data directory for current account"), + tr("Database files for '%1' could not be moved to\n\n'%2'.") + .arg(userName).arg(newDir), + QMessageBox::Ok); + } + break; + case ACT_COPY: + /* Copy account database into new directory. */ + if (dbSet->copyToLocation(newDir)) { + itemSettings.setDbDir(newDir); + + logInfo("Database files for '%s' have been copied from '%s' to '%s'.\n", + userName.toUtf8().constData(), + oldDir.toUtf8().constData(), + newDir.toUtf8().constData()); + + QMessageBox::information(parent, + tr("Change data directory for current account"), + tr("Database files for '%1' have been successfully copied to\n\n'%2'.") + .arg(userName).arg(newDir), + QMessageBox::Ok); + + return true; + } else { + QMessageBox::critical(parent, + tr("Change data directory for current account"), + tr("Database files for '%1' could not be copied to\n\n'%2'.") + .arg(userName).arg(newDir), + QMessageBox::Ok); + } + break; + case ACT_NEW: + /* Create a new account database into new directory. */ + if (dbSet->reopenLocation(newDir, MessageDbSet::DO_YEARLY, + MessageDbSet::CM_CREATE_EMPTY_CURRENT)) { + itemSettings.setDbDir(newDir); + + logInfo("Database files for '%s' have been created in '%s'.\n", + userName.toUtf8().constData(), + newDir.toUtf8().constData()); + + QMessageBox::information(parent, + tr("Change data directory for current account"), + tr("New database files for '%1' have been successfully created in\n\n'%2'.") + .arg(userName).arg(newDir), + QMessageBox::Ok); + + return true; + } else { + QMessageBox::critical(parent, + tr("Change data directory for current account"), + tr("New database files for '%1' could not be created in\n\n'%2'.") + .arg(userName).arg(newDir), + QMessageBox::Ok); + } + break; + default: + Q_ASSERT(0); + break; } - emit sentNewPath(m_dirPath, this->newPath->text(), action); + return false; } diff -Nru datovka-4.8.3/src/gui/dlg_change_directory.h datovka-4.9.3/src/gui/dlg_change_directory.h --- datovka-4.8.3/src/gui/dlg_change_directory.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_change_directory.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,34 +21,99 @@ * the two. */ - #ifndef _DLG_CHANGE_DIRECTORY_H_ #define _DLG_CHANGE_DIRECTORY_H_ - #include +#include -#include "src/common.h" -#include "ui_dlg_change_directory.h" +class MessageDbSet; /* Forward declaration. */ +namespace Ui { + class DlgChangeDirectory; +} -class DlgChangeDirectory : public QDialog, public Ui::ChangeDirectory { - Q_OBJECT +/*! + * @brief Provides interface for database file location change. + */ +class DlgChangeDirectory : public QDialog { + Q_OBJECT public: - DlgChangeDirectory(QString dirPath, QWidget *parent = 0); + /*! + * @brief Constructor. + * + * @param[in] currentDir Current database location directory. + * @param[in] parent Parent widget. + */ + explicit DlgChangeDirectory(const QString ¤tDir, + QWidget *parent = Q_NULLPTR); + + /*! + * @brief Destructor. + */ + virtual + ~DlgChangeDirectory(void); + + /*! + * @brief Asks the user for the new database location and relocates it. + * + * @param[in] userName User name identifying related account. + * @param[in] dbSet Affected database set. + * @param[in] parent Parent widget. + * @return True on success. + */ + static + bool changeDataDirectory(const QString &userName, MessageDbSet *dbSet, + QWidget *parent = Q_NULLPTR); private slots: - void onDirectoryChange(void); - void setNewDataDirectory(void); - -signals: - void sentNewPath(QString, QString, QString); + /*! + * @brief Choose new data directory. + */ + void chooseNewDirectory(void); private: - QString m_dirPath; - void initDialog(void); -}; + /*! + * @brief Identifies chosen action. + */ + enum Action { + ACT_MOVE, /*!< Move database location, delete in original location. */ + ACT_COPY, /*!< Copy database to new location, leave in original location. */ + ACT_NEW /*!< Start new database in new location, leave in original location. */ + }; + + /*! + * @brief Generates a dialogue asking the user for new location. + * + * @param[in] currentDir Current directory. + * @param[out] newDir Chosen new directory. + * @param[out] action Chosen relocation action. + * @param[in] parent Parent widget. + * @return True if a new directory and relocation action has been + * selected. + */ + static + bool chooseAction(const QString ¤tDir, QString &newDir, + enum Action &action, QWidget *parent = Q_NULLPTR); + + /*! + * @brief Performs a database relocation. + * + * @param[in] userName User name identifying related account. + * @param[in] dbSet Affected database set. + * @param[in] oldDir Old location. + * @param[in] newDir New location. + * @param[in] action Type or relocation operation. + * @param[in] parent Parent widget. + * @return True on success. + */ + static + bool relocateDatabase(const QString &userName, MessageDbSet *dbSet, + const QString &oldDir, const QString &newDir, enum Action action, + QWidget *parent = Q_NULLPTR); + Ui::DlgChangeDirectory *m_ui; /*!< UI generated from UI file. */ +}; #endif /* _DLG_CHANGE_DIRECTORY_H_ */ diff -Nru datovka-4.8.3/src/gui/dlg_change_pwd.cpp datovka-4.9.3/src/gui/dlg_change_pwd.cpp --- datovka-4.8.3/src/gui/dlg_change_pwd.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_change_pwd.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -21,16 +21,14 @@ * the two. */ - #include -#include "dlg_change_pwd.h" +#include "src/gui/dlg_change_pwd.h" #include "src/io/isds_sessions.h" -#include "src/models/accounts_model.h" +#include "src/settings/accounts.h" #include "src/worker/pool.h" #include "src/worker/task_change_pwd.h" - DlgChangePwd::DlgChangePwd(const QString &boxId, const QString &userName, QWidget *parent) : QDialog(parent), @@ -41,7 +39,6 @@ initPwdChangeDialog(); } - /* ========================================================================= */ /* * Init dialog @@ -72,14 +69,14 @@ this->otpLabel->setEnabled(false); this->smsPushButton->setEnabled(false); - if (AccountModel::globAccounts[m_userName].loginMethod() == + if (globAccounts[m_userName].loginMethod() == AcntSettings::LIM_UNAME_PWD_HOTP) { this->secCodeLineEdit->setEnabled(true); this->otpLabel->setText(tr("Enter security code:")); this->otpLabel->setEnabled(true); } - if (AccountModel::globAccounts[m_userName].loginMethod() == + if (globAccounts[m_userName].loginMethod() == AcntSettings::LIM_UNAME_PWD_TOTP) { this->secCodeLineEdit->setEnabled(true); this->smsPushButton->setEnabled(true); @@ -159,9 +156,9 @@ Q_ASSERT(!m_userName.isEmpty()); - if (AccountModel::globAccounts[m_userName].loginMethod() == + if (globAccounts[m_userName].loginMethod() == AcntSettings::LIM_UNAME_PWD_HOTP || - AccountModel::globAccounts[m_userName].loginMethod() == + globAccounts[m_userName].loginMethod() == AcntSettings::LIM_UNAME_PWD_TOTP) { buttonEnabled = buttonEnabled && !this->secCodeLineEdit->text().isEmpty(); @@ -203,10 +200,10 @@ /* show Premium SMS request dialog */ QMessageBox::StandardButton reply = QMessageBox::question(this, tr("SMS code for account ") + - AccountModel::globAccounts[m_userName].accountName(), + globAccounts[m_userName].accountName(), tr("Account \"%1\" requires authentication via security code " "for connection to databox.") - .arg(AccountModel::globAccounts[m_userName].accountName()) + .arg(globAccounts[m_userName].accountName()) + "
    " + tr("Security code will be sent you via Premium SMS.") + "

    " + @@ -235,11 +232,11 @@ QMessageBox::information(this, tr("Enter SMS security code"), tr("SMS security code for account \"%1\"
    " "has been sent on your mobile phone...") - .arg(AccountModel::globAccounts[m_userName].accountName()) + .arg(globAccounts[m_userName].accountName()) + "

    " + tr("Enter SMS security code for account") + "
    " - + AccountModel::globAccounts[m_userName].accountName() + + globAccounts[m_userName].accountName() + " (" + m_userName + ").", QMessageBox::Ok); this->otpLabel->setText(tr("Enter SMS code:")); @@ -268,14 +265,14 @@ QString errorStr, longErrorStr; TaskChangePwd *task; - if (AccountModel::globAccounts[m_userName].loginMethod() == + if (globAccounts[m_userName].loginMethod() == AcntSettings::LIM_UNAME_PWD_HOTP || - AccountModel::globAccounts[m_userName].loginMethod() == + globAccounts[m_userName].loginMethod() == AcntSettings::LIM_UNAME_PWD_TOTP) { task = new (std::nothrow) TaskChangePwd(m_userName, this->currentPwdLineEdit->text().toUtf8().constData(), this->newPwdLineEdit->text().toUtf8().constData(), - (AccountModel::globAccounts[m_userName].loginMethod() == AcntSettings::LIM_UNAME_PWD_HOTP) ? OTP_HMAC : OTP_TIME, + (globAccounts[m_userName].loginMethod() == AcntSettings::LIM_UNAME_PWD_HOTP) ? OTP_HMAC : OTP_TIME, this->secCodeLineEdit->text()); } else { task = new (std::nothrow) TaskChangePwd(m_userName, @@ -300,7 +297,7 @@ "into your data box via the web interface."), QMessageBox::Ok); - AccountModel::globAccounts[m_userName].setPassword( + globAccounts[m_userName].setPassword( this->newPwdLineEdit->text()); /* TODO - delete and create new @@ -310,7 +307,8 @@ Q_ASSERT(!m_userName.isEmpty()); QString error = tr("Error: ") + errorStr; if (!longErrorStr.isEmpty()) { - error = tr("ISDS returns: ") + longErrorStr; + error = tr("ISDS returns") + QLatin1String(": ") + + longErrorStr; } QMessageBox::warning(this, tr("Password error"), diff -Nru datovka-4.8.3/src/gui/dlg_contacts.cpp datovka-4.9.3/src/gui/dlg_contacts.cpp --- datovka-4.8.3/src/gui/dlg_contacts.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_contacts.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -21,6 +21,7 @@ * the two. */ +#include #include "src/gui/dlg_contacts.h" #include "src/views/table_home_end_filter.h" @@ -66,11 +67,13 @@ true); this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - this->clearPushButton->setEnabled(false); fillContactsFromMessageDb(); - connect(this->filterLineEdit, SIGNAL(textChanged(QString)), + this->filterLine->setToolTip(tr("Enter sought expression")); + this->filterLine->setClearButtonEnabled(true); + + connect(this->filterLine, SIGNAL(textChanged(QString)), this, SLOT(filterContact(QString))); connect(&m_contactTableModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), @@ -80,8 +83,6 @@ this, SLOT(setFirstColumnActive(QItemSelection, QItemSelection))); connect(this->contactTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(contactItemDoubleClicked(QModelIndex))); - connect(this->clearPushButton, SIGNAL(clicked()), - this, SLOT(clearContactText())); connect(this->buttonBox, SIGNAL(accepted()), this, SLOT(addSelectedDbIDs())); @@ -132,29 +133,21 @@ void DlgContacts::filterContact(const QString &text) { - this->clearPushButton->setEnabled(!text.isEmpty()); - m_contactListProxyModel.setFilterRegExp(QRegExp(text, Qt::CaseInsensitive, QRegExp::FixedString)); /* Set filter field background colour. */ if (text.isEmpty()) { - this->filterLineEdit->setStyleSheet( + this->filterLine->setStyleSheet( SortFilterProxyModel::blankFilterEditStyle); } else if (m_contactListProxyModel.rowCount() != 0) { - this->filterLineEdit->setStyleSheet( + this->filterLine->setStyleSheet( SortFilterProxyModel::foundFilterEditStyle); } else { - this->filterLineEdit->setStyleSheet( + this->filterLine->setStyleSheet( SortFilterProxyModel::notFoundFilterEditStyle); } } -void DlgContacts::clearContactText(void) -{ - this->filterLineEdit->clear(); - this->clearPushButton->setEnabled(false); -} - void DlgContacts::fillContactsFromMessageDb(void) { this->contactTableView->setEnabled(false); diff -Nru datovka-4.8.3/src/gui/dlg_contacts.h datovka-4.9.3/src/gui/dlg_contacts.h --- datovka-4.8.3/src/gui/dlg_contacts.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_contacts.h 2017-09-06 11:49:23.000000000 +0000 @@ -77,11 +77,6 @@ */ void filterContact(const QString &text); - /*! - * @brief Clear search text in the filter input line. - */ - void clearContactText(void); - private: /*! * @brief Get contacts from message database and fill table model. diff -Nru datovka-4.8.3/src/gui/dlg_correspondence_overview.cpp datovka-4.9.3/src/gui/dlg_correspondence_overview.cpp --- datovka-4.8.3/src/gui/dlg_correspondence_overview.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_correspondence_overview.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -27,10 +27,12 @@ #include #include +#include "src/delegates/tag_item.h" #include "src/gui/dlg_correspondence_overview.h" +#include "src/gui/dlg_msg_box_informative.h" #include "src/io/exports.h" #include "src/io/filesystem.h" -#include "src/models/accounts_model.h" +#include "src/settings/accounts.h" #include "src/settings/preferences.h" #define CSV_LITERAL QStringLiteral("CSV") @@ -48,8 +50,7 @@ Q_ASSERT(!userName.isEmpty()); - this->accountName->setText( - AccountModel::globAccounts[userName].accountName() + + this->accountName->setText(globAccounts[userName].accountName() + QStringLiteral(" (") + userName + QStringLiteral(")")); this->toCalendarWidget->setMinimumDate(this->fromCalendarWidget->selectedDate()); @@ -507,28 +508,28 @@ { switch (fileType) { case Exports::ZFO_MESSAGE: - qWarning( + qWarning("%s", QString("DZ '%1' export error.").arg(dmId).toUtf8().constData()); errList.append( QObject::tr("Message '%1' does not contain data necessary for ZFO export.") .arg(dmId)); break; case Exports::ZFO_DELIVERY: - qWarning( + qWarning("%s", QString("DZ '%1' export error").arg(dmId).toUtf8().constData()); errList.append( QObject::tr("Message '%1' does not contain acceptance info data necessary for ZFO export.") .arg(dmId)); break; case Exports::PDF_ENVELOPE: - qWarning( + qWarning("%s", QString("OZ '%1' export error").arg(dmId).toUtf8().constData()); errList.append( QObject::tr("Message '%1' does not contain message envelope data necessary for PDF export.") .arg(dmId)); break; case Exports::PDF_DELIVERY: - qWarning( + qWarning("%s", QString("DD '%1' export error").arg(dmId).toUtf8().constData()); errList.append( QObject::tr("Message '%1' does not contain acceptance info data necessary for PDF export.") @@ -708,12 +709,6 @@ } finish: - QMessageBox msgBox(this); - msgBox.setIcon(QMessageBox::Information); - msgBox.setWindowTitle(tr("Export results")); - msgBox.setText( - tr("Export of correspondence overview finished with these results:")); - if (!errorList.isEmpty()) { summaryMsg += QStringLiteral("
    ") + tr("Some errors occurred during export.") + @@ -721,17 +716,13 @@ tr("See detail for more info...") + QStringLiteral("

    "); } - msgBox.setInformativeText(summaryMsg); - - QString msg; + QString detailMsg; if (!errorList.isEmpty()) { for (int i = 0; i < errorList.count(); ++i) { - msg += errorList.at(i) + QStringLiteral("\n"); + detailMsg += errorList.at(i) + QStringLiteral("\n"); } - msgBox.setDetailedText(msg); } - - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); + DlgMsgBox::message(this, QMessageBox::Information, tr("Export results"), + tr("Export of correspondence overview finished with these results:"), + summaryMsg, detailMsg, QMessageBox::Ok, QMessageBox::Ok); } diff -Nru datovka-4.8.3/src/gui/dlg_create_account.cpp datovka-4.9.3/src/gui/dlg_create_account.cpp --- datovka-4.8.3/src/gui/dlg_create_account.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_create_account.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -55,17 +55,6 @@ m_loginmethod = loginMethodIdx; switch (m_loginmethod) { - case MOJEID: - this->certificateLabel->setEnabled(false); - this->addCertificateButton->setEnabled(false); - this->passwordLabel->setEnabled(false); - this->passwordLineEdit->setEnabled(false); - this->rememberPswcheckBox->setEnabled(false); - this->usernameLineEdit->setEnabled(false); - this->accountLineEdit->setEnabled(false); - this->testAccountCheckBox->setEnabled(false); - this->loginmethodComboBox->setEnabled(false); - break; case CERTIFICATE: this->certificateLabel->setEnabled(true); this->addCertificateButton->setEnabled(true); @@ -99,12 +88,6 @@ bool buttonEnabled; switch (m_loginmethod) { - case MOJEID: - buttonEnabled = true; - if (m_action == ACT_EDIT) { - this->accountLineEdit->setEnabled(true); - } - break; case CERTIFICATE: buttonEnabled = !this->accountLineEdit->text().isEmpty() && !this->usernameLineEdit->text().isEmpty() @@ -239,10 +222,6 @@ case AcntSettings::LIM_UNAME_PWD_TOTP: itemIdx = TOTP; break; - case AcntSettings::LIM_MOJE_ID: - this->loginmethodComboBox->addItem(tr("mojeID")); - itemIdx = MOJEID; - break; default: Q_ASSERT(0); itemIdx = USER_NAME; diff -Nru datovka-4.8.3/src/gui/dlg_create_account.h datovka-4.9.3/src/gui/dlg_create_account.h --- datovka-4.8.3/src/gui/dlg_create_account.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_create_account.h 2017-09-06 11:49:23.000000000 +0000 @@ -46,8 +46,7 @@ CERTIFICATE = 1, USER_CERTIFICATE = 2, HOTP = 3, - TOTP = 4, - MOJEID = 5 + TOTP = 4 }; /*! diff -Nru datovka-4.8.3/src/gui/dlg_ds_search.cpp datovka-4.9.3/src/gui/dlg_ds_search.cpp --- datovka-4.8.3/src/gui/dlg_ds_search.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_ds_search.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -29,7 +29,7 @@ #include "src/views/table_home_end_filter.h" #include "src/views/table_space_selection_filter.h" #include "src/worker/pool.h" -#include "src/worker/task_keep_alive.h" +#include "ui_dlg_ds_search.h" #define CBOX_TARGET_ALL 0 #define CBOX_TARGET_ADDRESS 1 @@ -42,26 +42,46 @@ #define CBOX_TYPE_PFO 3 #define CBOX_TYPE_FO 4 +FulltextSearchThread::FulltextSearchThread(DlgDsSearch *dlg) + : m_dlg(dlg) +{ + Q_ASSERT(dlg != Q_NULLPTR); +} + +void FulltextSearchThread::run(void) +{ + if (Q_UNLIKELY(m_dlg == Q_NULLPTR)) { + Q_ASSERT(0); + return; + } + DlgDsSearch::SearchResultFt searchResult(m_dlg->searchDataBoxFulltext()); + + emit searchFinished(searchResult.result, searchResult.longErrMsg); +} + DlgDsSearch::DlgDsSearch(const QString &userName, const QString &dbType, bool dbEffectiveOVM, bool dbOpenAddressing, QStringList *dbIdList, QWidget *parent) : QDialog(parent), + m_ui(new (std::nothrow) Ui::DlgDsSearch), + m_fulltextThread(this), m_userName(userName), m_dbType(dbType), m_dbEffectiveOVM(dbEffectiveOVM), m_dbOpenAddressing(dbOpenAddressing), + m_contactListProxyModel(this), m_contactTableModel(this), m_boxTypeCBoxModel(this), m_fulltextCBoxModel(this), m_dbIdList(dbIdList), m_breakDownloadLoop(false), - m_pingTimer(Q_NULLPTR), m_showInfoLabel(false) { - setupUi(this); + m_ui->setupUi(this); + /* Set default line height for table views/widgets. */ - this->contactTableView->setNarrowedLineHeight(); - this->contactTableView->setSelectionBehavior( + m_ui->contactTableView->setNarrowedLineHeight(); + m_ui->contactTableView->setSelectionBehavior( QAbstractItemView::SelectRows); m_boxTypeCBoxModel.appendRow( @@ -79,7 +99,7 @@ m_boxTypeCBoxModel.appendRow( tr("FO") + QStringLiteral(" - ") + tr("Fyzická osoba"), CBOX_TYPE_FO); - this->dataBoxTypeCBox->setModel(&m_boxTypeCBoxModel); + m_ui->dataBoxTypeCBox->setModel(&m_boxTypeCBoxModel); m_fulltextCBoxModel.appendRow( tr("All") + QStringLiteral(" - ") + tr("Search in all fields"), @@ -93,68 +113,93 @@ m_fulltextCBoxModel.appendRow( tr("ID") + QStringLiteral(" - ") + tr("Box identifier"), CBOX_TARGET_BOX_ID); - this->fulltextTargetCBox->setModel(&m_fulltextCBoxModel); + m_ui->fulltextTargetCBox->setModel(&m_fulltextCBoxModel); m_contactTableModel.setHeader(); - this->contactTableView->setModel(&m_contactTableModel); + m_contactListProxyModel.setSortRole(ROLE_MSGS_DB_PROXYSORT); + m_contactListProxyModel.setSourceModel(&m_contactTableModel); + { + QList columnList; + columnList.append(BoxContactsModel::BOX_ID_COL); + columnList.append(BoxContactsModel::BOX_NAME_COL); + columnList.append(BoxContactsModel::ADDRESS_COL); + m_contactListProxyModel.setFilterKeyColumns(columnList); + } + m_ui->contactTableView->setModel(&m_contactListProxyModel); - connect(this->contactTableView->selectionModel(), + connect(m_ui->contactTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(setFirstColumnActive(QItemSelection, QItemSelection))); - connect(this->textLineEdit, SIGNAL(textChanged(QString)), + connect(m_ui->textLineEdit, SIGNAL(textChanged(QString)), + this, SLOT(checkInputFields())); + connect(m_ui->iDLineEdit, SIGNAL(textChanged(QString)), this, SLOT(checkInputFields())); - connect(this->iDLineEdit, SIGNAL(textChanged(QString)), + connect(m_ui->iCLineEdit, SIGNAL(textChanged(QString)), this, SLOT(checkInputFields())); - connect(this->iCLineEdit, SIGNAL(textChanged(QString)), + connect(m_ui->nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(checkInputFields())); - connect(this->nameLineEdit, SIGNAL(textChanged(QString)), + connect(m_ui->pscLineEdit, SIGNAL(textChanged(QString)), this, SLOT(checkInputFields())); - connect(this->pscLineEdit, SIGNAL(textChanged(QString)), + connect(m_ui->dataBoxTypeCBox, SIGNAL(currentIndexChanged(int)), this, SLOT(checkInputFields())); - connect(this->dataBoxTypeCBox, SIGNAL(currentIndexChanged (int)), + connect(m_ui->fulltextTargetCBox, SIGNAL(currentIndexChanged(int)), this, SLOT(checkInputFields())); connect(&m_contactTableModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(enableOkButton())); - connect(this->contactTableView, SIGNAL(doubleClicked(QModelIndex)), + connect(m_ui->contactTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(contactItemDoubleClicked(QModelIndex))); - connect(this->buttonBox, SIGNAL(accepted()), + connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(addSelectedDbIDs())); - connect(this->buttonBox, SIGNAL(rejected()), + connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(setBreakDownloadLoop())); - connect(this->searchPushButton, SIGNAL(clicked()), + connect(m_ui->searchPushButton, SIGNAL(clicked()), this, SLOT(searchDataBox())); - connect(this->useFulltextCheckBox, SIGNAL(stateChanged(int)), + connect(&m_fulltextThread, SIGNAL(searchFinished(int, QString)), + this, SLOT(collectFulltextThreadOutcome(int, QString))); + + connect(m_ui->useFulltextCheckBox, SIGNAL(stateChanged(int)), this, SLOT(makeSearchElelementsVisible(int))); - this->useFulltextCheckBox->setCheckState(Qt::Checked); + m_ui->useFulltextCheckBox->setCheckState(Qt::Checked); - this->contactTableView->installEventFilter( + m_ui->contactTableView->installEventFilter( new TableHomeEndFilter(this)); - this->contactTableView->installEventFilter( + m_ui->contactTableView->installEventFilter( new TableSpaceSelectionFilter(this)); -#if 0 /* Don't use the timer. */ - m_pingTimer = new QTimer(this); - m_pingTimer->start(DLG_ISDS_KEEPALIVE_MS); + m_ui->filterLine->setFixedWidth(200); + m_ui->filterLine->setToolTip(tr("Enter sought expression")); + m_ui->filterLine->setClearButtonEnabled(true); - connect(m_pingTimer, SIGNAL(timeout()), this, SLOT(pingIsdsServer())); -#endif + connect(m_ui->filterLine, SIGNAL(textChanged(QString)), + this, SLOT(filterContact(QString))); initContent(); } DlgDsSearch::~DlgDsSearch(void) { - if (m_pingTimer != Q_NULLPTR) { - delete m_pingTimer; - } + m_fulltextThread.wait(); + delete m_ui; +} + +QStringList DlgDsSearch::search(const QString &userName, const QString &dbType, + bool dbEffectiveOVM, bool dbOpenAddressing, QWidget *parent) +{ + QStringList dbIdList; + + DlgDsSearch dlg(userName, dbType, dbEffectiveOVM, dbOpenAddressing, + &dbIdList, parent); + dlg.exec(); + + return dbIdList; } void DlgDsSearch::enableOkButton(void) { - this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled( + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled( m_contactTableModel.somethingChecked()); } @@ -166,35 +211,79 @@ if (selected.isEmpty()) { return; } - this->contactTableView->selectColumn(BoxContactsModel::CHECKBOX_COL); - this->contactTableView->selectRow(selected.first().top()); + m_ui->contactTableView->selectColumn(BoxContactsModel::CHECKBOX_COL); + m_ui->contactTableView->selectRow(selected.first().top()); } void DlgDsSearch::checkInputFields(void) { - if (Qt::Checked == this->useFulltextCheckBox->checkState()) { + if (Qt::Checked == m_ui->useFulltextCheckBox->checkState()) { checkInputFieldsFulltext(); } else { checkInputFieldsNormal(); } } +/*! + * @brief Enables/disables search controls. + * + * @param[in,out] ui User interface. + * @param[in] enabled State to be set. + */ +static inline +void setSearchControlsEnabled(Ui::DlgDsSearch *ui, bool enabled) +{ + if (Q_UNLIKELY(Q_NULLPTR == ui)) { + Q_ASSERT(0); + return; + } + ui->useFulltextCheckBox->setEnabled(enabled); + ui->searchPushButton->setEnabled(enabled); +} + +void DlgDsSearch::collectFulltextThreadOutcome(int result, + const QString &longErrMsg) +{ + displaySearchResultFt(result, longErrMsg); + + setSearchControlsEnabled(m_ui, true); +} + void DlgDsSearch::searchDataBox(void) { - this->useFulltextCheckBox->setEnabled(false); - this->searchPushButton->setEnabled(false); + setSearchControlsEnabled(m_ui, false); QCoreApplication::processEvents(); - if (Qt::Checked == this->useFulltextCheckBox->checkState()) { - searchDataBoxFulltext(); + if (Qt::Checked == m_ui->useFulltextCheckBox->checkState()) { +#if 0 + displaySearchResultFt(searchDataBoxFulltext()); + setSearchControlsEnabled(m_ui, true); +#else + /* Signal stop to any possibly running thread. */ + setBreakDownloadLoop(); + /* Wait for thread to finish. */ + m_fulltextThread.wait(); + /* Just in case the thread was not running. */ + m_breakDownloadLoop = false; + /* Execute search thread. */ + searchDataBoxFulltextThread(); +#endif } else { - searchDataBoxNormal(); + if (m_ui->iDLineEdit->text() == ID_ISDS_SYS_DATABOX) { + QMessageBox::information(this, tr("Search result"), + tr("This is a special ID for a ISDS system data box. " + "You can't use this ID for message delivery. Try again."), + QMessageBox::Ok); + } else { + displaySearchResult(searchDataBoxNormal()); + } + setSearchControlsEnabled(m_ui, true); } - this->useFulltextCheckBox->setEnabled(true); - this->searchPushButton->setEnabled(true); } void DlgDsSearch::contactItemDoubleClicked(const QModelIndex &index) { + setBreakDownloadLoop(); /* Break download loop. */ + if (index.isValid() && (m_dbIdList != Q_NULLPTR)) { m_dbIdList->append(index.sibling(index.row(), BoxContactsModel::BOX_ID_COL).data( @@ -218,88 +307,98 @@ m_breakDownloadLoop = true; } -void DlgDsSearch::pingIsdsServer(void) const -{ - TaskKeepAlive *task = new (std::nothrow) TaskKeepAlive(m_userName); - task->setAutoDelete(true); - globWorkPool.assignHi(task); -} - void DlgDsSearch::makeSearchElelementsVisible(int fulltextState) { - labelSearchInfo->hide(); + m_ui->labelSearchInfo->hide(); - fulltextTargetLabel->hide(); - fulltextTargetCBox->hide(); + m_ui->fulltextTargetLabel->hide(); + m_ui->fulltextTargetCBox->hide(); - iDLineLabel->hide(); - iDLineEdit->clear(); - iDLineEdit->hide(); + m_ui->iDLineLabel->hide(); + m_ui->iDLineEdit->clear(); + m_ui->iDLineEdit->hide(); - iCLineLabel->hide(); - iCLineEdit->clear(); - iCLineEdit->hide(); + m_ui->iCLineLabel->hide(); + m_ui->iCLineEdit->clear(); + m_ui->iCLineEdit->hide(); - nameLineLabel->hide(); - nameLineEdit->clear(); - nameLineEdit->hide(); + m_ui->nameLineLabel->hide(); + m_ui->nameLineEdit->clear(); + m_ui->nameLineEdit->hide(); - pscLineLabel->hide(); - pscLineEdit->clear(); - pscLineEdit->hide(); + m_ui->pscLineLabel->hide(); + m_ui->pscLineEdit->clear(); + m_ui->pscLineEdit->hide(); - textLineLabel->hide(); - textLineEdit->clear(); - textLineEdit->hide(); + m_ui->textLineLabel->hide(); + m_ui->textLineEdit->clear(); + m_ui->textLineEdit->hide(); - searchResultText->setText(QString()); + m_ui->searchResultText->setText(QString()); m_contactTableModel.removeRows(0, m_contactTableModel.rowCount()); if (Qt::Checked == fulltextState) { - labelSearchDescr->setText( + m_ui->labelSearchDescr->setText( tr("Full-text data box search. Enter phrase for finding and set optional restrictions:")); m_boxTypeCBoxModel.setEnabled(CBOX_TYPE_ALL, true); - contactTableView->setColumnHidden( + m_ui->contactTableView->setColumnHidden( BoxContactsModel::POST_CODE_COL, true); - contactTableView->setColumnHidden(BoxContactsModel::PDZ_COL, + m_ui->contactTableView->setColumnHidden(BoxContactsModel::PDZ_COL, true); - fulltextTargetLabel->show(); - fulltextTargetCBox->show(); + m_ui->fulltextTargetLabel->show(); + m_ui->fulltextTargetCBox->show(); - textLineLabel->show(); - textLineEdit->show(); + m_ui->textLineLabel->show(); + m_ui->textLineEdit->show(); } else { - labelSearchDescr->setText( + m_ui->labelSearchDescr->setText( tr("Enter the ID, IČ or at least three letters from the name of the data box you look for:")); /* Cannot search for all data box types. */ m_boxTypeCBoxModel.setEnabled(CBOX_TYPE_ALL, false); - if (dataBoxTypeCBox->currentData(CBoxModel::valueRole).toInt() == + if (m_ui->dataBoxTypeCBox->currentData(CBoxModel::valueRole).toInt() == CBOX_TYPE_ALL) { - dataBoxTypeCBox->setCurrentIndex( + m_ui->dataBoxTypeCBox->setCurrentIndex( m_boxTypeCBoxModel.findRow(CBOX_TYPE_OVM)); } - contactTableView->setColumnHidden( + m_ui->contactTableView->setColumnHidden( BoxContactsModel::POST_CODE_COL, false); - contactTableView->setColumnHidden(BoxContactsModel::PDZ_COL, + m_ui->contactTableView->setColumnHidden(BoxContactsModel::PDZ_COL, true); - iDLineLabel->show(); - iDLineEdit->show(); + m_ui->iDLineLabel->show(); + m_ui->iDLineEdit->show(); + + m_ui->iCLineLabel->show(); + m_ui->iCLineEdit->show(); - iCLineLabel->show(); - iCLineEdit->show(); + m_ui->nameLineLabel->show(); + m_ui->nameLineEdit->show(); - nameLineLabel->show(); - nameLineEdit->show(); + m_ui->pscLineLabel->show(); + m_ui->pscLineEdit->show(); + } +} - pscLineLabel->show(); - pscLineEdit->show(); +void DlgDsSearch::filterContact(const QString &text) +{ + m_contactListProxyModel.setFilterRegExp(QRegExp(text, + Qt::CaseInsensitive, QRegExp::FixedString)); + /* Set filter field background colour. */ + if (text.isEmpty()) { + m_ui->filterLine->setStyleSheet( + SortFilterProxyModel::blankFilterEditStyle); + } else if (m_contactListProxyModel.rowCount() != 0) { + m_ui->filterLine->setStyleSheet( + SortFilterProxyModel::foundFilterEditStyle); + } else { + m_ui->filterLine->setStyleSheet( + SortFilterProxyModel::notFoundFilterEditStyle); } } @@ -333,124 +432,115 @@ m_showInfoLabel = true; } - this->accountInfo->setText("" + m_userName + - "" + " - " + m_dbType + dbOpenAddressing); + m_ui->accountInfo->setText("" + m_userName + "" + + " - " + m_dbType + dbOpenAddressing); - this->labelSearchInfo->setStyleSheet("QLabel { color: red }"); - this->labelSearchInfo->setToolTip(toolTipInfo); - this->labelSearchInfo->hide(); - - this->contactTableView->setColumnWidth(BoxContactsModel::CHECKBOX_COL, 20); - this->contactTableView->setColumnWidth(BoxContactsModel::BOX_ID_COL, 60); - this->contactTableView->setColumnWidth(BoxContactsModel::BOX_TYPE_COL, 70); - this->contactTableView->setColumnWidth(BoxContactsModel::BOX_NAME_COL, 120); - this->contactTableView->setColumnWidth(BoxContactsModel::ADDRESS_COL, 100); - - this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - this->contactTableView-> - setEditTriggers(QAbstractItemView::NoEditTriggers); + m_ui->labelSearchInfo->setStyleSheet("QLabel { color: red }"); + m_ui->labelSearchInfo->setToolTip(toolTipInfo); + m_ui->labelSearchInfo->hide(); + + m_ui->contactTableView->setColumnWidth(BoxContactsModel::CHECKBOX_COL, 20); + m_ui->contactTableView->setColumnWidth(BoxContactsModel::BOX_ID_COL, 60); + m_ui->contactTableView->setColumnWidth(BoxContactsModel::BOX_TYPE_COL, 70); + m_ui->contactTableView->setColumnWidth(BoxContactsModel::BOX_NAME_COL, 120); + m_ui->contactTableView->setColumnWidth(BoxContactsModel::ADDRESS_COL, 100); + + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + m_ui->contactTableView->setEditTriggers( + QAbstractItemView::NoEditTriggers); checkInputFields(); } void DlgDsSearch::checkInputFieldsNormal(void) { - this->nameLineEdit->setEnabled(true); - this->pscLineEdit->setEnabled((true)); - this->iCLineEdit->setEnabled((true)); - this->iDLineEdit->setEnabled((true)); + m_ui->nameLineEdit->setEnabled(true); + m_ui->pscLineEdit->setEnabled((true)); + m_ui->iCLineEdit->setEnabled((true)); + m_ui->iDLineEdit->setEnabled((true)); - switch (this->dataBoxTypeCBox->currentData(CBoxModel::valueRole).toInt()) { + switch (m_ui->dataBoxTypeCBox->currentData(CBoxModel::valueRole).toInt()) { case CBOX_TYPE_OVM: - this->iCLineEdit->setEnabled(true); - this->nameLineLabel->setText(tr("Subject Name:")); - this->nameLineLabel->setToolTip(tr("Enter name of subject")); - this->nameLineEdit->setToolTip(tr("Enter name of subject")); - this->labelSearchInfo->hide(); + m_ui->iCLineEdit->setEnabled(true); + m_ui->nameLineLabel->setText(tr("Subject Name:")); + m_ui->nameLineLabel->setToolTip(tr("Enter name of subject")); + m_ui->nameLineEdit->setToolTip(tr("Enter name of subject")); + m_ui->labelSearchInfo->hide(); break; case CBOX_TYPE_PO: - this->iCLineEdit->setEnabled(true); - this->nameLineLabel->setText(tr("Subject Name:")); - this->nameLineLabel->setToolTip(tr("Enter name of subject")); - this->nameLineEdit->setToolTip(tr("Enter name of subject")); - this->labelSearchInfo->setVisible(m_showInfoLabel); + m_ui->iCLineEdit->setEnabled(true); + m_ui->nameLineLabel->setText(tr("Subject Name:")); + m_ui->nameLineLabel->setToolTip(tr("Enter name of subject")); + m_ui->nameLineEdit->setToolTip(tr("Enter name of subject")); + m_ui->labelSearchInfo->setVisible(m_showInfoLabel); break; case CBOX_TYPE_PFO: - this->iCLineEdit->setEnabled(true); - this->nameLineLabel->setText(tr("Name:")); - this->nameLineLabel->setToolTip(tr("Enter last name of the PFO or company name.")); - this->nameLineEdit->setToolTip(tr("Enter last name of the PFO or company name.")); - this->labelSearchInfo->setVisible(m_showInfoLabel); + m_ui->iCLineEdit->setEnabled(true); + m_ui->nameLineLabel->setText(tr("Name:")); + m_ui->nameLineLabel->setToolTip(tr("Enter last name of the PFO or company name.")); + m_ui->nameLineEdit->setToolTip(tr("Enter last name of the PFO or company name.")); + m_ui->labelSearchInfo->setVisible(m_showInfoLabel); break; case CBOX_TYPE_FO: - this->iCLineEdit->setEnabled(false); - this->nameLineLabel->setText(tr("Last Name:")); - this->nameLineLabel->setToolTip(tr("Enter last name or last name at birth of the FO.")); - this->nameLineEdit->setToolTip(tr("Enter last name or last name at birth of the FO.")); - this->labelSearchInfo->setVisible(m_showInfoLabel); + m_ui->iCLineEdit->setEnabled(false); + m_ui->nameLineLabel->setText(tr("Last Name:")); + m_ui->nameLineLabel->setToolTip(tr("Enter last name or last name at birth of the FO.")); + m_ui->nameLineEdit->setToolTip(tr("Enter last name or last name at birth of the FO.")); + m_ui->labelSearchInfo->setVisible(m_showInfoLabel); break; default: break; } - if (!this->iDLineEdit->text().isEmpty()) { - this->nameLineEdit->setEnabled(false); - this->pscLineEdit->setEnabled(false); - this->iCLineEdit->setEnabled(false); + if (!m_ui->iDLineEdit->text().isEmpty()) { + m_ui->nameLineEdit->setEnabled(false); + m_ui->pscLineEdit->setEnabled(false); + m_ui->iCLineEdit->setEnabled(false); - if (this->iDLineEdit->text().length() == 7) { - this->searchPushButton->setEnabled(true); + if (m_ui->iDLineEdit->text().length() == 7) { + m_ui->searchPushButton->setEnabled(true); } else { - this->searchPushButton->setEnabled(false); + m_ui->searchPushButton->setEnabled(false); } - } else if (!this->iCLineEdit->text().isEmpty()) { - this->iDLineEdit->setEnabled(false); - this->nameLineEdit->setEnabled(false); - this->pscLineEdit->setEnabled(false); + } else if (!m_ui->iCLineEdit->text().isEmpty()) { + m_ui->iDLineEdit->setEnabled(false); + m_ui->nameLineEdit->setEnabled(false); + m_ui->pscLineEdit->setEnabled(false); - if (this->iCLineEdit->text().length() == 8) { - this->searchPushButton->setEnabled(true); + if (m_ui->iCLineEdit->text().length() == 8) { + m_ui->searchPushButton->setEnabled(true); } else { - this->searchPushButton->setEnabled(false); + m_ui->searchPushButton->setEnabled(false); } - } else if (!this->nameLineEdit->text().isEmpty()) { - this->iDLineEdit->setEnabled(false); + } else if (!m_ui->nameLineEdit->text().isEmpty()) { + m_ui->iDLineEdit->setEnabled(false); - if (this->nameLineEdit->text().length() > 2) { - this->searchPushButton->setEnabled(true); + if (m_ui->nameLineEdit->text().length() > 2) { + m_ui->searchPushButton->setEnabled(true); } else { - this->searchPushButton->setEnabled(false); + m_ui->searchPushButton->setEnabled(false); } } else { - this->searchPushButton->setEnabled(false); - this->iDLineEdit->setEnabled(true); - this->nameLineEdit->setEnabled(true); - this->pscLineEdit->setEnabled(true); + m_ui->searchPushButton->setEnabled(false); + m_ui->iDLineEdit->setEnabled(true); + m_ui->nameLineEdit->setEnabled(true); + m_ui->pscLineEdit->setEnabled(true); } } void DlgDsSearch::checkInputFieldsFulltext(void) { - this->searchPushButton->setEnabled( - this->textLineEdit->text().size() > 2); + m_ui->searchPushButton->setEnabled( + m_ui->textLineEdit->text().size() > 2); } -void DlgDsSearch::searchDataBoxNormal(void) +DlgDsSearch::SearchResult DlgDsSearch::searchDataBoxNormal(void) { - if (this->iDLineEdit->text() == ID_ISDS_SYS_DATABOX) { - QMessageBox::information(this, tr("Search result"), - tr("This is a special ID for system databox of " - "Datové schránky. You can't use this ID for " - "message delivery. Try again."), - QMessageBox::Ok); - return; - } - enum TaskSearchOwner::BoxType boxType = TaskSearchOwner::BT_OVM; - switch (this->dataBoxTypeCBox->currentData(CBoxModel::valueRole).toInt()) { + switch (m_ui->dataBoxTypeCBox->currentData(CBoxModel::valueRole).toInt()) { case CBOX_TYPE_FO: boxType = TaskSearchOwner::BT_FO; break; @@ -466,16 +556,16 @@ break; } - queryBoxNormal(this->iDLineEdit->text(), boxType, - this->iCLineEdit->text(), this->nameLineEdit->text(), - this->pscLineEdit->text()); + return queryBoxNormal(m_ui->iDLineEdit->text(), boxType, + m_ui->iCLineEdit->text(), m_ui->nameLineEdit->text(), + m_ui->pscLineEdit->text()); } -void DlgDsSearch::searchDataBoxFulltext(void) +DlgDsSearch::SearchResultFt DlgDsSearch::searchDataBoxFulltext(void) { enum TaskSearchOwnerFulltext::FulltextTarget target = TaskSearchOwnerFulltext::FT_ALL; - switch (this->fulltextTargetCBox->currentData(CBoxModel::valueRole).toInt()) { + switch (m_ui->fulltextTargetCBox->currentData(CBoxModel::valueRole).toInt()) { case CBOX_TARGET_ALL: target = TaskSearchOwnerFulltext::FT_ALL; break; @@ -493,7 +583,7 @@ enum TaskSearchOwnerFulltext::BoxType boxType = TaskSearchOwnerFulltext::BT_ALL; - switch (this->dataBoxTypeCBox->currentData(CBoxModel::valueRole).toInt()) { + switch (m_ui->dataBoxTypeCBox->currentData(CBoxModel::valueRole).toInt()) { case CBOX_TYPE_FO: boxType = TaskSearchOwnerFulltext::BT_FO; break; @@ -512,47 +602,84 @@ break; } - queryBoxFulltextAll(target, boxType, this->textLineEdit->text()); + return queryBoxFulltextAll(target, boxType, m_ui->textLineEdit->text()); +} + +void DlgDsSearch::searchDataBoxFulltextThread(void) +{ + m_fulltextThread.start(); } -void DlgDsSearch::queryBoxNormal(const QString &boxId, +DlgDsSearch::SearchResult DlgDsSearch::queryBoxNormal(const QString &boxId, enum TaskSearchOwner::BoxType boxType, const QString &ic, const QString &name, const QString &zipCode) { - this->contactTableView->setEnabled(false); + m_ui->contactTableView->setEnabled(false); m_contactTableModel.removeRows(0, m_contactTableModel.rowCount()); - QString resultString(tr("Total found") + QStringLiteral(": ")); - this->searchResultText->setText(resultString + QStringLiteral("0")); + m_ui->searchResultText->setText(totalFoundStr(0)); TaskSearchOwner::SoughtOwnerInfo soughtInfo(boxId, boxType, ic, name, name, name, zipCode); - TaskSearchOwner *task = - new (std::nothrow) TaskSearchOwner(m_userName, soughtInfo); + TaskSearchOwner *task = new (std::nothrow) TaskSearchOwner(m_userName, + soughtInfo); + if (Q_UNLIKELY(task == Q_NULLPTR)) { + Q_ASSERT(0); + m_ui->contactTableView->setEnabled(true); + return SearchResult(TaskSearchOwner::SO_ERROR, QString()); + } task->setAutoDelete(false); globWorkPool.runSingle(task); - enum TaskSearchOwner::Result result = task->m_result; - QString errMsg = task->m_isdsError; - QString longErrMsg = task->m_isdsLongError; + enum TaskSearchOwner::Result taskResult = task->m_result; + QString longErrMsg(task->m_isdsLongError); QList foundBoxes(task->m_foundBoxes); delete task; task = Q_NULLPTR; - switch (result) { + if (taskResult != TaskSearchOwner::SO_SUCCESS) { + return SearchResult(taskResult, longErrMsg); + } + + bool selectFirstRow = m_contactTableModel.rowCount() == 0; + m_contactTableModel.appendData(foundBoxes); + + m_ui->searchResultText->setText(totalFoundStr(foundBoxes.size())); + + if (m_contactTableModel.rowCount() > 0) { + m_ui->contactTableView->selectColumn( + BoxContactsModel::CHECKBOX_COL); + if (selectFirstRow) { + m_ui->contactTableView->selectRow(0); + } + } + + m_ui->contactTableView->setEnabled(true); + + //m_ui->contactTableView->resizeColumnsToContents(); + + return SearchResult(taskResult, QString()); +} + +void DlgDsSearch::displaySearchResult(const SearchResult &searchResult) +{ + switch (searchResult.result) { case TaskSearchOwner::SO_SUCCESS: + /* Don't display anything on success. */ break; case TaskSearchOwner::SO_BAD_DATA: QMessageBox::information(this, tr("Search result"), - longErrMsg, QMessageBox::Ok); + searchResult.longErrMsg, QMessageBox::Ok); + m_ui->contactTableView->setEnabled(true); return; break; case TaskSearchOwner::SO_COM_ERROR: QMessageBox::information(this, tr("Search result"), tr("It was not possible find any data box because") + - QStringLiteral(":\n\n") + longErrMsg, + QStringLiteral(":\n\n") + searchResult.longErrMsg, QMessageBox::Ok); + m_ui->contactTableView->setEnabled(true); return; break; case TaskSearchOwner::SO_ERROR: @@ -560,99 +687,76 @@ QMessageBox::critical(this, tr("Search error"), tr("It was not possible find any data box because an error occurred during the search process!"), QMessageBox::Ok); + m_ui->contactTableView->setEnabled(true); return; break; } - - m_contactTableModel.appendData(foundBoxes); - - this->searchResultText->setText( - resultString + QString::number(foundBoxes.size())); - - if (m_contactTableModel.rowCount() > 0) { - this->contactTableView->selectColumn( - BoxContactsModel::CHECKBOX_COL); - this->contactTableView->selectRow(0); - } - - this->contactTableView->setEnabled(true); - - //this->contactTableView->resizeColumnsToContents(); } -bool DlgDsSearch::queryBoxFulltextPage( - enum TaskSearchOwnerFulltext::FulltextTarget target, - enum TaskSearchOwnerFulltext::BoxType boxType, - const QString &phrase, qint64 pageNum) +DlgDsSearch::SearchResultFt DlgDsSearch::queryBoxFulltextPage( + enum TaskSearchOwnerFulltext::FulltextTarget target, + enum TaskSearchOwnerFulltext::BoxType boxType, + const QString &phrase, qint64 pageNum) { - QString resultString(tr("Total found") + QStringLiteral(": ")); - this->searchResultText->setText(resultString + QStringLiteral("0")); - TaskSearchOwnerFulltext *task = new (std::nothrow) TaskSearchOwnerFulltext(m_userName, phrase, target, boxType, pageNum, false); + if (Q_UNLIKELY(task == Q_NULLPTR)) { + Q_ASSERT(0); + return SearchResultFt(TaskSearchOwnerFulltext::SOF_ERROR, + QString(), false); + } task->setAutoDelete(false); globWorkPool.runSingle(task); - enum TaskSearchOwnerFulltext::Result result = task->m_result; - QString errMsg = task->m_isdsError; - QString longErrMsg = task->m_isdsLongError; + enum TaskSearchOwnerFulltext::Result taskResult = task->m_result; + QString longErrMsg(task->m_isdsLongError); QList foundBoxes(task->m_foundBoxes); quint64 totalDb = task->m_totalMatchingBoxes; bool gotLastPage = task->m_gotLastPage; delete task; task = Q_NULLPTR; - switch (result) { - case TaskSearchOwnerFulltext::SOF_SUCCESS: - break; - case TaskSearchOwnerFulltext::SOF_BAD_DATA: - QMessageBox::information(this, tr("Search result"), - longErrMsg, QMessageBox::Ok); - return false; - break; - case TaskSearchOwnerFulltext::SOF_COM_ERROR: - QMessageBox::information(this, tr("Search result"), - tr("It was not possible find any data box because") + - QStringLiteral(":\n\n") + longErrMsg, - QMessageBox::Ok); - return false; - break; - case TaskSearchOwnerFulltext::SOF_ERROR: - default: - QMessageBox::critical(this, tr("Search error"), - tr("It was not possible find any data box because an error occurred during the search process!"), - QMessageBox::Ok); - return false; - break; + /* + * No dialogue can be raised here because this method can be called + * from a non-GUI thread. + */ + if (taskResult != TaskSearchOwnerFulltext::SOF_SUCCESS) { + return SearchResultFt(taskResult, longErrMsg, gotLastPage); } + bool selectFirstRow = m_contactTableModel.rowCount() == 0; m_contactTableModel.appendData(foundBoxes); - this->searchResultText->setText( - resultString + QString::number(totalDb) + QStringLiteral("; ") + - tr("Displayed") + QStringLiteral(": ") + + m_ui->searchResultText->setText(totalFoundStr(totalDb) + QLatin1String("; ") + + tr("Displayed") + QLatin1String(": ") + QString::number(m_contactTableModel.rowCount())); if (m_contactTableModel.rowCount() > 0) { - this->contactTableView->selectColumn( + m_ui->contactTableView->selectColumn( BoxContactsModel::CHECKBOX_COL); - this->contactTableView->selectRow(0); + if (selectFirstRow) { + m_ui->contactTableView->selectRow(0); + } } - return !gotLastPage; /* Return false when last page received. */ + return SearchResultFt(taskResult, QString(), gotLastPage); } -void DlgDsSearch::queryBoxFulltextAll( +DlgDsSearch::SearchResultFt DlgDsSearch::queryBoxFulltextAll( enum TaskSearchOwnerFulltext::FulltextTarget target, enum TaskSearchOwnerFulltext::BoxType boxType, const QString &phrase) { - this->contactTableView->setEnabled(false); m_contactTableModel.removeRows(0, m_contactTableModel.rowCount()); + m_ui->searchResultText->setText(totalFoundStr(0)); + qint64 pageNum = 0; - while (queryBoxFulltextPage(target, boxType, phrase, pageNum)) { - QCoreApplication::processEvents(); + SearchResultFt searchResult(TaskSearchOwnerFulltext::SOF_ERROR, + QString(), false); + while (searchResult = queryBoxFulltextPage(target, boxType, phrase, pageNum), + ((searchResult.result == TaskSearchOwnerFulltext::SOF_SUCCESS) && !searchResult.lastPage)) { + //QCoreApplication::processEvents(); ++pageNum; if (m_breakDownloadLoop) { m_breakDownloadLoop = false; @@ -660,7 +764,41 @@ } } - this->contactTableView->setEnabled(true); + //m_ui->contactTableView->resizeColumnsToContents(); + + return searchResult; +} + +void DlgDsSearch::displaySearchResultFt(int result, const QString &longErrMsg) +{ + switch (result) { + case TaskSearchOwnerFulltext::SOF_SUCCESS: + /* Don't display anything on success. */ + break; + case TaskSearchOwnerFulltext::SOF_BAD_DATA: + QMessageBox::information(this, tr("Search result"), + longErrMsg, QMessageBox::Ok); + return; + break; + case TaskSearchOwnerFulltext::SOF_COM_ERROR: + QMessageBox::information(this, tr("Search result"), + tr("It was not possible find any data box because") + + QStringLiteral(":\n\n") + longErrMsg, + QMessageBox::Ok); + return; + break; + case TaskSearchOwnerFulltext::SOF_ERROR: + default: + QMessageBox::critical(this, tr("Search error"), + tr("It was not possible find any data box because an error occurred during the search process!"), + QMessageBox::Ok); + return; + break; + } +} - //this->contactTableView->resizeColumnsToContents(); +QString DlgDsSearch::totalFoundStr(int total) +{ + return tr("Total found") + QLatin1String(": ") + + QString::number(total); } diff -Nru datovka-4.8.3/src/gui/dlg_ds_search.h datovka-4.9.3/src/gui/dlg_ds_search.h --- datovka-4.8.3/src/gui/dlg_ds_search.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_ds_search.h 2017-09-06 11:49:23.000000000 +0000 @@ -25,34 +25,84 @@ #define _DLG_DS_SEARCH_H_ #include -#include +#include +#include -#include "src/common.h" #include "src/models/combo_box_model.h" #include "src/models/data_box_contacts_model.h" +#include "src/models/sort_filter_proxy_model.h" #include "src/worker/task_search_owner.h" #include "src/worker/task_search_owner_fulltext.h" -#include "ui_dlg_ds_search.h" + +class DlgDsSearch; /* Forward declaration. */ /*! - * @brief Data box search dialogue. + * @brief Thread performing full-text data box searching. */ -class DlgDsSearch : public QDialog, public Ui::DsSearch { +class FulltextSearchThread : public QThread { Q_OBJECT + public: /*! * @brief Constructor. */ + explicit FulltextSearchThread(DlgDsSearch *dlg); + +signals: + /*! + * @brief Emitted when search finishes. + * + * @param[in] result Task result code. + * @param[in] longErrMsg Long error message. + */ + void searchFinished(int result, const QString &longErrMsg); + +protected: + /*! + * @brief Thread function. + */ + virtual + void run(void) Q_DECL_OVERRIDE; + +private: + DlgDsSearch *m_dlg; /*!< Pointer to data box search window. */ +}; + +namespace Ui { + class DlgDsSearch; +} + +/*! + * @brief Data box search dialogue. + */ +class DlgDsSearch : public QDialog { + Q_OBJECT + +private: + /*! + * @brief Constructor. + */ DlgDsSearch(const QString &userName, const QString &dbType, bool dbEffectiveOVM, bool dbOpenAddressing, QStringList *dbIdList = Q_NULLPTR, QWidget *parent = Q_NULLPTR); +public: /*! * @brief Destructor. */ virtual ~DlgDsSearch(void); + /*! + * @brief Show data box search dialogue. + * + * @return List of data-box identifiers. + */ + static + QStringList search(const QString &userName, const QString &dbType, + bool dbEffectiveOVM, bool dbOpenAddressing, + QWidget *parent = Q_NULLPTR); + private slots: /*! * @brief Activates confirmation button. @@ -74,6 +124,15 @@ void checkInputFields(void); /*! + * @brief Run on search thread exit. + * + * @param[in] result Full-text task result code. + * @param[in] longErrMsg Long error message. + */ + void collectFulltextThreadOutcome(int result, + const QString &longErrMsg); + + /*! * @brief Search for data boxes according given criteria. */ void searchDataBox(void); @@ -94,19 +153,56 @@ void setBreakDownloadLoop(void); /*! - * @brief Ping the ISDS server, test whether connection is active. - */ - void pingIsdsServer(void) const; - - /*! * @brief Displays elements relevant for normal or full-text search. * * @param[in] fulltextCheckState STate of full-text checkbox state. */ void makeSearchElelementsVisible(int fulltextState); + /*! + * @brief Apply filter text on the table. + */ + void filterContact(const QString &text); + private: /*! + * @brief Normal search result. + */ + class SearchResult { + public: + /*! + * @brief Constructor. + */ + SearchResult(enum TaskSearchOwner::Result r, + const QString &lErr) + : result(r), longErrMsg(lErr) + { + } + + enum TaskSearchOwner::Result result; + QString longErrMsg; + }; + + /*! + * @brief Full-text search result. + */ + class SearchResultFt { + public: + /*! + * @brief Constructor. + */ + SearchResultFt(enum TaskSearchOwnerFulltext::Result r, + const QString &lErr, bool lp) + : result(r), longErrMsg(lErr), lastPage(lp) + { + } + + enum TaskSearchOwnerFulltext::Result result; + QString longErrMsg; + bool lastPage; /*!< True if last page acquired. */ + }; + + /*! * @brief Initialise dialogue content. */ void initContent(void); @@ -124,12 +220,18 @@ /*! * @brief Normal search for data boxes according given criteria. */ - void searchDataBoxNormal(void); + SearchResult searchDataBoxNormal(void); /*! * @brief Full-text search for data boxes according given criteria. */ - void searchDataBoxFulltext(void); + SearchResultFt searchDataBoxFulltext(void); + + /*! + * @brief Full-text search for data boxes according given criteria + * run in background. + */ + void searchDataBoxFulltextThread(void); /*! * @brief Encapsulates query. @@ -139,21 +241,29 @@ * @param[in] ic Identifier number. * @param[in] name Name to search for. * @param[in] zipCode ZIP code. + * @return Search result. */ - void queryBoxNormal(const QString &boxId, + SearchResult queryBoxNormal(const QString &boxId, enum TaskSearchOwner::BoxType boxType, const QString &ic, const QString &name, const QString &zipCode); /*! + * @brief Display message about search result. + * + * @param[in] searchResult Search task result code. + */ + void displaySearchResult(const SearchResult &searchResult); + + /*! * @brief Encapsulates full-text query for a single page. * * @param[in] target Which field to search in. * @param[in] boxType Type of data box to search for. * @param[in] phrase Text phrase to search for. * @param[in] pageNum Page umber to ask for. - * @return False on error or when last page downloaded. + * @return Search result. */ - bool queryBoxFulltextPage( + SearchResultFt queryBoxFulltextPage( enum TaskSearchOwnerFulltext::FulltextTarget target, enum TaskSearchOwnerFulltext::BoxType boxType, const QString &phrase, qint64 pageNum); @@ -165,26 +275,53 @@ * @param[in] boxType Type of data box to search for. * @param[in] phrase Text phrase to search for. */ - void queryBoxFulltextAll( + SearchResultFt queryBoxFulltextAll( enum TaskSearchOwnerFulltext::FulltextTarget target, enum TaskSearchOwnerFulltext::BoxType boxType, const QString &phrase); + /*! + * @brief Display message about full-text search result. + * + * @param[in] result Full-text task result code. + * @param[in] longErrMsg Long error message. + */ + void displaySearchResultFt(int result, const QString &longErrMsg); + + /*! + * @brief Returns total found string. + * + * @param[in] total Total found number. + * @return String containing total found summary. + */ + static + QString totalFoundStr(int total); + + /* Allow access from search thread to dialogue controls. */ + friend class FulltextSearchThread; + + Ui::DlgDsSearch *m_ui; /*!< UI generated from UI file. */ + + FulltextSearchThread m_fulltextThread; /*!< Tread that's waiting for incoming full-text search result. */ + const QString m_userName; /*!< User name used for searching. */ const QString m_dbType; /*!< Data box type used for searching. */ - const bool m_dbEffectiveOVM; - const bool m_dbOpenAddressing; + const bool m_dbEffectiveOVM; /*!< True if box has OVM status. */ + const bool m_dbOpenAddressing; /*!< True if open addressing is enabled. */ + SortFilterProxyModel m_contactListProxyModel; /*!< + * Used for message + * sorting and filtering. + */ BoxContactsModel m_contactTableModel; /*!< Model of found data boxes. */ CBoxModel m_boxTypeCBoxModel; /*!< Data box type combo box model. */ CBoxModel m_fulltextCBoxModel; /*!< Full-text combo box model. */ QStringList *m_dbIdList; /*!< List of box identifiers to append to. */ - bool m_breakDownloadLoop; /*!< Setting to true interrupts download loop. */ + volatile bool m_breakDownloadLoop; /*!< Setting to true interrupts download loop. */ - QTimer *m_pingTimer; - bool m_showInfoLabel; + bool m_showInfoLabel; /*!< Controls the notification about limited search results. */ }; #endif /* DLG_DS_SEARCH_H */ diff -Nru datovka-4.8.3/src/gui/dlg_import_zfo.cpp datovka-4.9.3/src/gui/dlg_import_zfo.cpp --- datovka-4.8.3/src/gui/dlg_import_zfo.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_import_zfo.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -23,8 +23,8 @@ #include "src/gui/dlg_import_zfo.h" -ImportZFODialog::ImportZFODialog(enum ImportZFODialog::ZFOtype &zfoType, - enum ImportZFODialog::ZFOlocation &locationType, bool &checkZfoOnServer, +ImportZFODialog::ImportZFODialog(enum Imports::Type &zfoType, + enum ZFOlocation &locationType, bool &checkZfoOnServer, QWidget *parent) : QDialog(parent), m_zfoType(zfoType), @@ -63,11 +63,11 @@ void ImportZFODialog::setChosenValues(void) { if (this->messageZFO->isChecked()) { - m_zfoType = IMPORT_MESSAGE_ZFO; + m_zfoType = Imports::IMPORT_MESSAGE; } else if (this->deliveryZFO->isChecked()) { - m_zfoType = IMPORT_DELIVERY_ZFO; + m_zfoType = Imports::IMPORT_DELIVERY; } else { - m_zfoType = IMPORT_ALL_ZFO; + m_zfoType = Imports::IMPORT_ANY; } if (this->radioImportAll->isChecked()) { diff -Nru datovka-4.8.3/src/gui/dlg_import_zfo.h datovka-4.9.3/src/gui/dlg_import_zfo.h --- datovka-4.8.3/src/gui/dlg_import_zfo.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_import_zfo.h 2017-09-06 11:49:23.000000000 +0000 @@ -25,6 +25,8 @@ #define _DLG_IMPORT_ZFO_H_ #include + +#include "src/io/imports.h" #include "ui_dlg_import_zfo.h" /*! @@ -43,15 +45,6 @@ }; /*! - * ZFO type. - */ - enum ZFOtype { - IMPORT_ALL_ZFO, - IMPORT_MESSAGE_ZFO, - IMPORT_DELIVERY_ZFO - }; - - /*! * @brief Constructor. * * @param[out] zfoType - Specifies ZFO type. @@ -60,9 +53,9 @@ * will check on the ISDS server. * @param[in] parent - Parent object. */ - ImportZFODialog(enum ImportZFODialog::ZFOtype &zfoType, - enum ImportZFODialog::ZFOlocation &locationType, - bool &checkZfoOnServer, QWidget *parent = Q_NULLPTR); + ImportZFODialog(enum Imports::Type &zfoType, + enum ZFOlocation &locationType, bool &checkZfoOnServer, + QWidget *parent = Q_NULLPTR); private slots: /*! @@ -76,8 +69,8 @@ void setChosenValues(void); private: - enum ImportZFODialog::ZFOtype &m_zfoType; /*!< Specifies ZFO type. */ - enum ImportZFODialog::ZFOlocation &m_locationType; /*!< Specifies how/where ZFOs will load. */ + enum Imports::Type &m_zfoType; /*!< Specifies ZFO type. */ + enum ZFOlocation &m_locationType; /*!< Specifies how/where ZFOs will load. */ bool &m_checkZfoOnServer; /*!< ZFO will check on the ISDS server. */ }; diff -Nru datovka-4.8.3/src/gui/dlg_login_mojeid.cpp datovka-4.9.3/src/gui/dlg_login_mojeid.cpp --- datovka-4.8.3/src/gui/dlg_login_mojeid.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_login_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#include - -#include "dlg_login_mojeid.h" -#include "src/log/log.h" -#include "src/web/json.h" - -DlgLoginToMojeId::DlgLoginToMojeId(const QString &userName, - const QString &lastUrl, QWidget *parent) - : QDialog(parent), - m_loginmethod(0), - m_certPath(""), - m_userName(userName), - m_lastUrl(lastUrl), - m_token(QString()) -{ - setupUi(this); - initAccountDialog(); -} - - -/* ========================================================================= */ -/* - * Init dialog - */ -void DlgLoginToMojeId::initAccountDialog(void) -/* ========================================================================= */ -{ - this->loginmethodComboBox->addItem(tr("Password")); - this->loginmethodComboBox->addItem(tr("Certificate")); - this->loginmethodComboBox->addItem(tr("Password + Secure code")); - this->certificateLabel->setEnabled(false); - this->otpLineEdit->setEnabled(false); - this->accountButtonBox->button( - QDialogButtonBox::Ok)->setEnabled(false); - this->addCertificateButton->setEnabled(false); - connect(this->loginmethodComboBox, SIGNAL(currentIndexChanged (int)), - this, SLOT(setActiveButton(int))); - connect(this->addCertificateButton, SIGNAL(clicked()), this, - SLOT(addCertificateFromFile())); - connect(this->accountButtonBox, SIGNAL(accepted()), this, - SLOT(sendData(void))); - connect(this->usernameLineEdit, SIGNAL(textChanged(QString)), - this, SLOT(checkInputFields())); - connect(this->passwordLineEdit, SIGNAL(textChanged(QString)), - this, SLOT(checkInputFields())); - connect(this->otpLineEdit, SIGNAL(textChanged(QString)), - this, SLOT(checkInputFields())); - - if (!m_userName.isEmpty()) { - this->synchroCheckBox->setEnabled(false); - this->setWindowTitle(tr("Login to account: %1").arg(m_userName)); - } - - /* USERNAME+PWD is set as default login method in the Webdatovka */ - jsonlayer.loginMethodChanged(USER_NAME, m_lastUrl, m_token); -} - - -/* ========================================================================= */ -/* - * Open load dialog and set certificate file path - */ -void DlgLoginToMojeId::addCertificateFromFile(void) -/* ========================================================================= */ -{ - QString certFileName = QFileDialog::getOpenFileName(this, - tr("Open Certificate"), "", - tr("Certificate Files (*.p12 *.pem)")); - if (!certFileName.isEmpty()) { - this->addCertificateButton->setText(certFileName); - this->addCertificateButton->setIcon(QIcon(ICON_3PARTY_PATH + - QString("key_16.png"))); - m_certPath = certFileName; - checkInputFields(); - } -} - - -/* ========================================================================= */ -/* - * Check content of mandatory items in dialog and activate save button - */ -void DlgLoginToMojeId::checkInputFields(void) -/* ========================================================================= */ -{ - bool buttonEnabled; - if (m_loginmethod == CERTIFICATE) { - buttonEnabled = !m_certPath.isEmpty(); - } else if (m_loginmethod == USER_NAME) { - buttonEnabled = !this->usernameLineEdit->text().isEmpty() - && !this->passwordLineEdit->text().isEmpty(); - } else { - buttonEnabled = !this->usernameLineEdit->text().isEmpty() - && !this->passwordLineEdit->text().isEmpty() - && !this->otpLineEdit->text().isEmpty(); - } - - this->accountButtonBox->button(QDialogButtonBox::Ok)-> - setEnabled(buttonEnabled); -} - - -/* ========================================================================= */ -/* - * Set active/inactive buttons based on login method - */ -void DlgLoginToMojeId::setActiveButton(int itemindex) -/* ========================================================================= */ -{ - this->usernameLineEdit->setEnabled(true); - - if (itemindex == CERTIFICATE) { - this->certificateLabel->setEnabled(true); - this->addCertificateButton->setEnabled(true); - this->passwordLabel->setEnabled(false); - this->passwordLineEdit->setEnabled(false); - this->otpLineEdit->setEnabled(false); - this->otpLineEdit->clear(); - this->passwordLineEdit->clear(); - } else if (itemindex == USER_NAME) { - this->certificateLabel->setEnabled(false); - this->addCertificateButton->setEnabled(false); - this->passwordLabel->setEnabled((true)); - this->passwordLineEdit->setEnabled((true)); - this->otpLineEdit->setEnabled(false); - this->otpLineEdit->clear(); - } else { - this->certificateLabel->setEnabled(false); - this->addCertificateButton->setEnabled(false); - this->passwordLabel->setEnabled((true)); - this->passwordLineEdit->setEnabled((true)); - this->otpLineEdit->setEnabled(true); - } - - m_loginmethod = itemindex; - - jsonlayer.loginMethodChanged(m_loginmethod, m_lastUrl, m_token); - - checkInputFields(); -} - - -/* ========================================================================= */ -/* - * Login to mojeID. - */ -void DlgLoginToMojeId::sendData(void) -/* ========================================================================= */ -{ - debugSlotCall(); - - emit callMojeId(m_userName, m_lastUrl, - m_token, this->usernameLineEdit->text(), - this->passwordLineEdit->text(), this->otpLineEdit->text(), - this->synchroCheckBox->isChecked(), m_certPath); -} diff -Nru datovka-4.8.3/src/gui/dlg_login_mojeid.h datovka-4.9.3/src/gui/dlg_login_mojeid.h --- datovka-4.8.3/src/gui/dlg_login_mojeid.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_login_mojeid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - - -#ifndef _DLG_LOGIN_MOJEID_H_ -#define _DLG_LOGIN_MOJEID_H_ - -#include - -#include "src/common.h" -#include "ui_dlg_login_mojeid.h" - -class DlgLoginToMojeId : public QDialog, public Ui::LoginToMojeId { - Q_OBJECT - -public: - - DlgLoginToMojeId(const QString &userName, const QString &lastUrl, - QWidget *parent = 0); - -private slots: - void setActiveButton(int); - void addCertificateFromFile(void); - void sendData(void); - void checkInputFields(void); - -signals: - void callMojeId(QString, QString, QString, - QString, QString, QString, bool, QString); - -private: - void initAccountDialog(void); - - int m_loginmethod; - QString m_certPath; - QString m_userName; - QString m_lastUrl; - QString m_token; -}; - -#endif /* _DLG_LOGIN_MOJEID_H_ */ diff -Nru datovka-4.8.3/src/gui/dlg_msg_box_informative.cpp datovka-4.9.3/src/gui/dlg_msg_box_informative.cpp --- datovka-4.8.3/src/gui/dlg_msg_box_informative.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_msg_box_informative.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include "src/gui/dlg_msg_box_informative.h" + +int DlgMsgBox::message(QWidget *parent, enum QMessageBox::Icon icon, + const QString &title, const QString &text, const QString &infoText, + const QString &detailText, QMessageBox::StandardButtons buttons, + enum QMessageBox::StandardButton defaultButton) +{ + QMessageBox msgBox(parent); + msgBox.setIcon(icon); + msgBox.setWindowTitle(title); + msgBox.setText(text); + if (!infoText.isEmpty()) { + msgBox.setInformativeText(infoText); + } + if (!detailText.isEmpty()) { + msgBox.setDetailedText(detailText); + } + msgBox.setStandardButtons(buttons); + msgBox.setDefaultButton(defaultButton); + return msgBox.exec(); +} diff -Nru datovka-4.8.3/src/gui/dlg_msg_box_informative.h datovka-4.9.3/src/gui/dlg_msg_box_informative.h --- datovka-4.8.3/src/gui/dlg_msg_box_informative.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_msg_box_informative.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _DLG_MSG_BOX_INFORMATIVE_H_ +#define _DLG_MSG_BOX_INFORMATIVE_H_ + +#include + +/*! + * @brief Encapsulates QMessageBox with informative field. + */ +class DlgMsgBox { + +private: + /*! + * @brief Private constructor. + */ + DlgMsgBox(void); + +public: + /*! + * @brief Show message box with informative text. + * + * @param[in] parent Window parent. + * @param[in] icon Windows icon. + * @param[in] title Window title. + * @param[in] text Text to be displayed. + * @param[in] infoText Informative text. + * @param[in] detailText Detailed text. + * @param[in] buttons Displayed buttons. + * @param[in] defaultButton Default button. + * @return Standard button code. + */ + static + int message(QWidget *parent, enum QMessageBox::Icon icon, + const QString &title, const QString &text, + const QString &infoText, const QString &detailText, + QMessageBox::StandardButtons buttons = QMessageBox::Ok, + enum QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); +}; + +#endif /* _DLG_MSG_BOX_INFORMATIVE_H_ */ diff -Nru datovka-4.8.3/src/gui/dlg_msg_search.cpp datovka-4.9.3/src/gui/dlg_msg_search.cpp --- datovka-4.8.3/src/gui/dlg_msg_search.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_msg_search.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,13 +21,12 @@ * the two. */ - -#include "dlg_msg_search.h" #include "src/common.h" +#include "src/gui/dlg_msg_search.h" #include "src/io/message_db.h" #include "src/io/tag_db.h" #include "src/log/log.h" -#include "src/models/accounts_model.h" +#include "src/settings/accounts.h" #include "src/views/table_home_end_filter.h" #define COL_USER_NAME 0 @@ -72,8 +71,7 @@ Q_ASSERT(!m_userName.isEmpty()); /* set account name and user name to label */ - QString accountName = - AccountModel::globAccounts[m_userName].accountName() + " (" + + QString accountName = globAccounts[m_userName].accountName() + " (" + m_userName + ")"; this->currentAccountName->setText(accountName); @@ -525,7 +523,7 @@ Q_ASSERT(0 != messageDb); item->setToolTip(messageDb->descriptionHtml( - msgData.mId.dmId, 0, true, false, true)); + msgData.mId.dmId, true, false, true)); } this->resultsTableWidget->setItem(row, COL_MESSAGE_ID, item); this->resultsTableWidget->setItem(row, COL_DELIVERY_YEAR, diff -Nru datovka-4.8.3/src/gui/dlg_search_mojeid.cpp datovka-4.9.3/src/gui/dlg_search_mojeid.cpp --- datovka-4.8.3/src/gui/dlg_search_mojeid.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_search_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - - -#include -#include - -#include "src/gui/dlg_search_mojeid.h" -#include "src/views/table_home_end_filter.h" -#include "src/views/table_space_selection_filter.h" -#include "src/web/json.h" - -DlgDsSearchMojeId::DlgDsSearchMojeId(Action action, - QTableWidget *recipientTableWidget, const QString &dbType, - bool dbEffectiveOVM, QWidget *parent, const QString &userName) - : QDialog(parent), - m_action(action), - m_recipientTableWidget(recipientTableWidget), - m_dbType(dbType), - m_dbEffectiveOVM(dbEffectiveOVM), - m_userName(userName), - m_limit(0) -{ - setupUi(this); - initSearchWindow(); -} - - -/* ========================================================================= */ -/* - * Init ISDS search dialog - */ -void DlgDsSearchMojeId::initSearchWindow(void) -/* ========================================================================= */ -{ - this->resultsTableWidget->setColumnHidden(5, true); - - this->accountInfo->setText("" + m_userName + - "" + " - " + m_dbType); - - this->resultsTableWidget->setColumnWidth(0,20); - this->resultsTableWidget->setColumnWidth(1,60); - this->resultsTableWidget->setColumnWidth(2,120); - - connect(this->resultsTableWidget, - SIGNAL(itemSelectionChanged()), this, - SLOT(setFirtsColumnActive())); - - connect(this->keywordLineEdit, SIGNAL(textChanged(QString)), - this, SLOT(checkInputFields())); - connect(this->resultsTableWidget,SIGNAL(itemClicked(QTableWidgetItem*)), - this, SLOT(enableOkButton())); - connect(this->resultsTableWidget, - SIGNAL(itemChanged(QTableWidgetItem*)), this, - SLOT(enableOkButton())); - connect(this->buttonBox, SIGNAL(accepted()), this, - SLOT(insertDsItems())); - connect(this->searchPushButton, SIGNAL(clicked()), this, - SLOT(searchDataBox())); - connect(this->resultsTableWidget, SIGNAL(doubleClicked(QModelIndex)), - this, SLOT(contactItemDoubleClicked(QModelIndex))); - - this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - this->resultsTableWidget-> - setEditTriggers(QAbstractItemView::NoEditTriggers); - - this->resultsTableWidget->installEventFilter( - new TableHomeEndFilter(this)); - this->resultsTableWidget->installEventFilter( - new TableSpaceSelectionFilter(this)); - - checkInputFields(); -} - - -/* ========================================================================= */ -/* - * Set first column with checkbox active if item was changed - */ -void DlgDsSearchMojeId::setFirtsColumnActive(void) -/* ========================================================================= */ -{ - this->resultsTableWidget->selectColumn(0); - this->resultsTableWidget->selectRow( - this->resultsTableWidget->currentRow()); -} - - -/* ========================================================================= */ -/* - * Check input fields in the dialog - */ -void DlgDsSearchMojeId::checkInputFields(void) -/* ========================================================================= */ -{ - this->searchPushButton->setEnabled(false); - if (this->keywordLineEdit->text().length() > 0) { - this->searchPushButton->setEnabled(true); - } - this->searchPushButton->setText(tr("Search")); - m_limit = 0; -} - - -/* ========================================================================= */ -/* - * Call ISDS and find data boxes with given criteria - */ -void DlgDsSearchMojeId::searchDataBox(void) -/* ========================================================================= */ -{ - if (m_limit == 0) { - this->resultsTableWidget->setRowCount(0); - } - this->resultsTableWidget->setEnabled(false); - - QList rList; - bool hasMore = false; - QString errStr; - - int accountID = getWebDatovkaAccountId(m_userName); - - JsonLayer jsonLayer; - jsonLayer.searchRecipient(m_userName, accountID, - this->keywordLineEdit->text(), m_limit, rList, hasMore, errStr); - - if (rList.isEmpty()) { - return; - } - - this->resultsTableWidget->setEnabled(true); - foreach (const JsonLayer::Recipient &recipient, rList) { - int row = this->resultsTableWidget->rowCount(); - this->resultsTableWidget->insertRow(row); - QTableWidgetItem *item = new QTableWidgetItem; - item->setCheckState(Qt::Unchecked); - this->resultsTableWidget->setItem(row,0,item); - item = new QTableWidgetItem; - item->setText(recipient.recipientDbId); - this->resultsTableWidget->setItem(row,1,item); - item = new QTableWidgetItem; - item->setText(recipient.recipientName); - this->resultsTableWidget->setItem(row,2,item); - item = new QTableWidgetItem; - item->setText(recipient.recipientAddress); - this->resultsTableWidget->setItem(row,3,item); - } - - if (this->resultsTableWidget->rowCount() > 0) { - this->resultsTableWidget->selectColumn(0); - this->resultsTableWidget->selectRow(0); - } - - if (hasMore) { - this->searchPushButton->setText(tr("Search next")); - m_limit++; - } -} - - -/* ========================================================================= */ -/* - * Enable action button - */ -void DlgDsSearchMojeId::enableOkButton(void) -/* ========================================================================= */ -{ - this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - for (int i = 0; i < this->resultsTableWidget->rowCount(); i++) { - if (this->resultsTableWidget->item(i,0)->checkState()) { - this->buttonBox->button(QDialogButtonBox::Ok)-> - setEnabled(true); - } - } -} - - -/* ========================================================================= */ -/* - * Test if the selected item is not in recipient list - */ -bool DlgDsSearchMojeId::isInRecipientTable(const QString &idDs) const -/* ========================================================================= */ -{ - Q_ASSERT(0 != m_recipientTableWidget); - - for (int i = 0; i < this->m_recipientTableWidget->rowCount(); i++) { - if (this->m_recipientTableWidget->item(i,0)->text() == idDs) { - return true; - } - } - return false; -} - - -/* ========================================================================= */ -/* - * Insert selected contacts into recipient list of the sent message dialog. - */ -void DlgDsSearchMojeId::insertDsItems(void) -/* ========================================================================= */ -{ - if (ACT_ADDNEW == m_action) { - Q_ASSERT(0 != m_recipientTableWidget); - for (int i = 0; i < this->resultsTableWidget->rowCount(); i++) { - if (this->resultsTableWidget->item(i,0)->checkState()) { - insertContactToRecipentTable(i); - } - } - } -} - - -/* ========================================================================= */ -/* - * Doubleclick of selected contact. - */ -void DlgDsSearchMojeId::contactItemDoubleClicked(const QModelIndex &index) -/* ========================================================================= */ -{ - if (ACT_ADDNEW == m_action) { - - if (!index.isValid()) { - this->close(); - return; - } - - insertContactToRecipentTable(index.row()); - - this->close(); - } -} - - -/* ========================================================================= */ -/* - * Insert contact into recipient list of the sent message dialog. - */ -void DlgDsSearchMojeId::insertContactToRecipentTable(int selRow) -/* ========================================================================= */ -{ - if (!isInRecipientTable( - this->resultsTableWidget->item(selRow, 1)->text())) { - - int row = m_recipientTableWidget->rowCount(); - m_recipientTableWidget->insertRow(row); - QTableWidgetItem *item = new QTableWidgetItem; - item->setText(this->resultsTableWidget-> - item(selRow, 1)->text()); - this->m_recipientTableWidget->setItem(row,0,item); - item = new QTableWidgetItem; - item->setText(this->resultsTableWidget-> - item(selRow, 2)->text()); - this->m_recipientTableWidget->setItem(row,1,item); - item = new QTableWidgetItem; - item->setText(this->resultsTableWidget->item(selRow, 3)->text()); - this->m_recipientTableWidget->setItem(row, 2, item); - item = new QTableWidgetItem; - item->setText(""); - item->setTextAlignment(Qt::AlignCenter); - this->m_recipientTableWidget->setItem(row, 3, item); - } -} diff -Nru datovka-4.8.3/src/gui/dlg_search_mojeid.h datovka-4.9.3/src/gui/dlg_search_mojeid.h --- datovka-4.8.3/src/gui/dlg_search_mojeid.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_search_mojeid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - - -#ifndef _DLG_SEARCH_MOJEID_H_ -#define _DLG_SEARCH_MOJEID_H_ - - -#include -#include - -#include "src/common.h" -#include "ui_dlg_search_mojeid.h" - - -class DlgDsSearchMojeId : public QDialog, public Ui::DsSearchMojeId { - Q_OBJECT - -public: - enum Action { - ACT_BLANK, - ACT_ADDNEW - }; - - DlgDsSearchMojeId(Action action, QTableWidget *recipientTableWidget, - const QString &dbType, bool dbEffectiveOVM, - QWidget *parent = 0, const QString &userName = QString()); - -private slots: - void checkInputFields(void); - void insertDsItems(void); - void enableOkButton(void); - void searchDataBox(void); - void setFirtsColumnActive(void); - void contactItemDoubleClicked(const QModelIndex &index); - -private: - - bool isInRecipientTable(const QString &idDs) const; - void initSearchWindow(void); - void addContactsToTable(const QList< QVector > &contactList); - void insertContactToRecipentTable(int selRow); - - Action m_action; - QTableWidget *m_recipientTableWidget; - QString m_dbType; - bool m_dbEffectiveOVM; - const QString m_userName; - int m_limit; -}; - - -#endif /* _DLG_SEARCH_MOJEID_H_ */ diff -Nru datovka-4.8.3/src/gui/dlg_send_message.cpp datovka-4.9.3/src/gui/dlg_send_message.cpp --- datovka-4.8.3/src/gui/dlg_send_message.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_send_message.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -31,18 +31,18 @@ #include "src/gui/dlg_change_pwd.h" #include "src/gui/dlg_contacts.h" #include "src/gui/dlg_ds_search.h" -#include "src/gui/dlg_search_mojeid.h" +#include "src/gui/dlg_msg_box_informative.h" #include "src/gui/dlg_send_message.h" #include "src/gui/dlg_yes_no_checkbox.h" #include "src/model_interaction/attachment_interaction.h" -#include "src/models/accounts_model.h" #include "src/io/account_db.h" #include "src/io/dbs.h" #include "src/io/isds_sessions.h" -#include "src/io/wd_sessions.h" #include "src/io/message_db.h" +#include "src/isds/isds_conversion.h" #include "src/localisation/localisation.h" #include "src/log/log.h" +#include "src/settings/accounts.h" #include "src/settings/preferences.h" #include "src/views/attachment_table_view.h" #include "src/views/table_home_end_filter.h" @@ -53,26 +53,25 @@ #include "src/worker/task_send_message.h" #include "src/worker/task_search_owner.h" #include "src/worker/task_search_owner_fulltext.h" -#include "src/worker/task_send_message_mojeid.h" #include "src/worker/task_search_owner.h" #include "ui_dlg_send_message.h" /* - * Message types as defined in ISDS alnd used in libisds. - * For details see linisds.h . + * Message types as defined in ISDS and used in libisds. + * For details see libisds.h . */ #define DMTYPE_INIT "I" #define DMTYPE_COMM "K" #define DMTYPE_RESP "O" -const QString &dzPrefix(MessageDb *messageDb, qint64 dmId) +const QString &dzPrefix(const MessageDb *messageDb, qint64 dmId) { - const static QString nothing; - const static QString received(QLatin1String("D")); - const static QString sent(QLatin1String("O")); + const static QString unspecified(QLatin1String("DZ")); + const static QString received(QLatin1String("DDZ")); + const static QString sent(QLatin1String("ODZ")); - if (Q_NULLPTR == messageDb || dmId < 0) { - return nothing; + if (Q_UNLIKELY(Q_NULLPTR == messageDb || dmId < 0)) { + return unspecified; } switch (messageDb->msgMessageType(dmId)) { @@ -83,7 +82,7 @@ return sent; break; default: - return nothing; + return unspecified; break; } } @@ -102,7 +101,6 @@ m_dbEffectiveOVM(false), m_dbOpenAddressing(false), m_isLogged(false), - m_isWebDatovkaAccount(false), m_lastAttAddPath(), m_pdzCredit("0"), m_dmType(), @@ -163,22 +161,8 @@ void DlgSendMessage::addRecipientFromISDSSearch(void) { - QStringList dbIDs; - QDialog *dsSearch = Q_NULLPTR; - if (!m_isWebDatovkaAccount) { - dsSearch = new DlgDsSearch(m_userName, m_dbType, - m_dbEffectiveOVM, m_dbOpenAddressing, &dbIDs, this); - } else { -#if 0 /* TODO -- MojeID functionality disabled, deal with it later. */ - dsSearch = new DlgDsSearchMojeId(DlgDsSearchMojeId::ACT_ADDNEW, - this->recipientTableWidget, m_dbType, m_dbEffectiveOVM, - this, m_userName); -#else - return; -#endif - } - dsSearch->exec(); - dsSearch->deleteLater(); + QStringList dbIDs(DlgDsSearch::search(m_userName, m_dbType, + m_dbEffectiveOVM, m_dbOpenAddressing, this)); addRecipientBoxes(dbIDs); } @@ -188,20 +172,16 @@ QString dbID = QInputDialog::getText(this, tr("Databox ID"), tr("Enter Databox ID (7 characters):"), QLineEdit::Normal, - NULL, &ok, Qt::WindowStaysOnTopHint); + QString(), &ok, Qt::WindowStaysOnTopHint); if (!ok) { return; } if (dbID.isEmpty() || dbID.length() != 7) { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setWindowTitle(tr("Wrong data box ID")); - msgBox.setText(tr("Wrong data box ID '%1'!").arg(dbID)); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); + QMessageBox::critical(this, tr("Wrong data box ID"), + tr("Wrong data box ID '%1'!").arg(dbID), + QMessageBox::Ok, QMessageBox::Ok); return; } @@ -243,7 +223,7 @@ static void removeSelectedEntries(const QTableView *view, QAbstractItemModel *model) { - if ((view == Q_NULLPTR) || (model == Q_NULLPTR)) { + if (Q_UNLIKELY((view == Q_NULLPTR) || (model == Q_NULLPTR))) { Q_ASSERT(0); return; } @@ -372,43 +352,30 @@ m_userName = userName; } - if (isWebDatovkaAccount(m_userName)) { - m_isWebDatovkaAccount = true; - } - - if (!m_isWebDatovkaAccount) { - m_isLogged = true; - m_keepAliveTimer.stop(); - { - TaskKeepAlive *task = - new (std::nothrow) TaskKeepAlive(m_userName); - task->setAutoDelete(false); - globWorkPool.runSingle(task); - - m_isLogged = task->m_isAlive; - - delete task; - } - if (!m_isLogged) { - if (Q_NULLPTR != m_mw) { - m_isLogged = m_mw->connectToIsds(m_userName); - } + m_isLogged = true; + m_keepAliveTimer.stop(); + { + TaskKeepAlive *task = + new (std::nothrow) TaskKeepAlive(m_userName); + task->setAutoDelete(false); + globWorkPool.runSingle(task); + + m_isLogged = task->m_isAlive; + + delete task; + } + if (!m_isLogged) { + if (Q_NULLPTR != m_mw) { + m_isLogged = m_mw->connectToIsds(m_userName); } - m_keepAliveTimer.start(DLG_ISDS_KEEPALIVE_MS); + } + m_keepAliveTimer.start(DLG_ISDS_KEEPALIVE_MS); - /* Check for presence of struct isds_ctx . */ - if (NULL == globIsdsSessions.session(m_userName)) { - logErrorNL("%s", "Missing ISDS session."); - m_isLogged = false; - } - } else { - if (!wdSessions.isConnectedToWebdatovka(m_userName)) { - if (Q_NULLPTR != m_mw) { - m_mw->loginToMojeId(m_userName); - } - } - m_isLogged = true; + /* Check for presence of struct isds_ctx . */ + if (NULL == globIsdsSessions.session(m_userName)) { + logErrorNL("%s", "Missing ISDS session."); + m_isLogged = false; } foreach (const Task::AccountDescr &acnt, m_messageDbSetList) { @@ -418,7 +385,7 @@ } } - const AcntSettings &accountInfo(AccountModel::globAccounts[m_userName]); + const AcntSettings &accountInfo(globAccounts[m_userName]); const QString acntDbKey(AccountDb::keyFromLogin(m_userName)); m_dbId = globAccountDbPtr->dbId(acntDbKey); Q_ASSERT(!m_dbId.isEmpty()); @@ -436,10 +403,8 @@ m_lastAttAddPath = accountInfo.lastAttachAddPath(); } - if (!m_isWebDatovkaAccount) { - if (m_dbOpenAddressing) { - m_pdzCredit = getPDZCreditFromISDS(m_userName, m_dbId); - } + if (m_dbOpenAddressing) { + m_pdzCredit = getPDZCreditFromISDS(m_userName, m_dbId); } QString dbOpenAddressingText; @@ -455,9 +420,8 @@ } this->fromUser->setText("" + - AccountModel::globAccounts[m_userName].accountName() + - "" + " (" + m_userName + ") - " + m_dbType + - dbOpenAddressingText); + globAccounts[m_userName].accountName() + "" + + " (" + m_userName + ") - " + m_dbType + dbOpenAddressingText); } void DlgSendMessage::sendMessage(void) @@ -467,11 +431,8 @@ const QList recipEntries( m_recipientTableModel.partialBoxEntries(BoxContactsModel::ANY)); - if (!m_isWebDatovkaAccount) { - sendMessageISDS(recipEntries); - } else { - sendMessageWebDatovka(recipEntries); - } + + sendMessageISDS(recipEntries); } void DlgSendMessage::collectSendMessageStatus(const QString &userName, @@ -509,7 +470,7 @@ this->setEnabled(true); int successfullySentCnt = 0; - QString detailText; + QString infoText; foreach (const TaskSendMessage::ResultData &resultData, m_sentMsgResultList) { @@ -517,7 +478,7 @@ ++successfullySentCnt; if (resultData.isPDZ) { - detailText += tr( + infoText += tr( "Message was successfully sent to " "%1 (%2) as PDZ with number " "%3."). @@ -525,7 +486,7 @@ arg(resultData.dbIDRecipient). arg(resultData.dmId) + "
    "; } else { - detailText += tr( + infoText += tr( "Message was successfully sent to " "%1 (%2) as message number " "%3."). @@ -534,7 +495,7 @@ arg(resultData.dmId) + "
    "; } } else { - detailText += tr("Message was NOT sent to " + infoText += tr("Message was NOT sent to " "%1 (%2). Server says: %3"). arg(resultData.recipientName). arg(resultData.dbIDRecipient). @@ -544,29 +505,20 @@ m_sentMsgResultList.clear(); if (m_recipientTableModel.rowCount() == successfullySentCnt) { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Information); - msgBox.setWindowTitle(tr("Message sent")); - msgBox.setText("" + - tr("Message was successfully sent to all recipients.") + - ""); - msgBox.setInformativeText(detailText); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); + DlgMsgBox::message(this, QMessageBox::Information, + tr("Message sent"), + "" + tr("Message was successfully sent to all recipients.") + "", + infoText, QString(), QMessageBox::Ok, QMessageBox::Ok); this->accept(); /* Set return code to accepted. */ } else { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Warning); - msgBox.setWindowTitle(tr("Message sending error")); - msgBox.setText("" + - tr("Message was NOT sent to all recipients.") + ""); - detailText += "

    " + + infoText += "

    " + tr("Do you want to close the Send message form?") + ""; - msgBox.setInformativeText(detailText); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - if (msgBox.exec() == QMessageBox::Yes) { + int ret = DlgMsgBox::message(this, QMessageBox::Warning, + tr("Message sending error"), + "" + tr("Message was NOT sent to all recipients.") + "", + infoText, QString(), QMessageBox::Yes | QMessageBox::No, + QMessageBox::No); + if (ret == QMessageBox::Yes) { this->close(); /* Set return code to closed. */ } } @@ -574,56 +526,9 @@ emit usedAttachmentPath(m_userName, m_lastAttAddPath); } -void DlgSendMessage::collectSendMessageStatusWebDatovka(const QString &userName, - const QStringList &results, const QString &error) -{ - debugSlotCall(); - - Q_UNUSED(error); - - QString detailText; - - if (results.isEmpty()) { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Information); - msgBox.setWindowTitle(tr("Message sent")); - msgBox.setText("" + - tr("Message was successfully sent to all recipients.") + - ""); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); - this->accept(); /* Set return code to accepted. */ - emit usedAttachmentPath(userName, m_lastAttAddPath); - } else { - for (int i = 0; i < results.count(); ++i) { - QString msg = results.at(i); - detailText += msg.replace("§", ": "); - } - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Warning); - msgBox.setWindowTitle(tr("Message sending error")); - msgBox.setText("" + - tr("Message was NOT sent to all recipients.") + ""); - detailText += "

    " + - tr("Do you want to close the Send message form?") + ""; - msgBox.setInformativeText(detailText); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - if (msgBox.exec() == QMessageBox::Yes) { - this->close(); /* Set return code to closed. */ - emit usedAttachmentPath(userName, m_lastAttAddPath); - } - } -} - void DlgSendMessage::initContent(enum Action action, const QList &msgIds) { - if (isWebDatovkaAccount(m_userName)) { - m_isWebDatovkaAccount = true; - } - m_recipientTableModel.setHeader(); this->recipientTableView->setModel(&m_recipientTableModel); @@ -660,7 +565,7 @@ foreach (const Task::AccountDescr &acnt, m_messageDbSetList) { const QString accountName = - AccountModel::globAccounts[acnt.userName].accountName() + + globAccounts[acnt.userName].accountName() + " (" + acnt.userName + ")"; this->fromComboBox->addItem(accountName, QVariant(acnt.userName)); if (m_userName == acnt.userName) { @@ -744,23 +649,15 @@ QString, QString, bool, qint64)), this, SLOT(collectSendMessageStatus(QString, QString, int, QString, QString, QString, bool, qint64))); - connect(&globMsgProcEmitter, - SIGNAL(sendMessageMojeIdFinished(QString, QStringList, QString)), - this, - SLOT(collectSendMessageStatusWebDatovka(QString, QStringList, - QString))); m_keepAliveTimer.start(DLG_ISDS_KEEPALIVE_MS); - if (!m_isWebDatovkaAccount) { - connect(&m_keepAliveTimer, SIGNAL(timeout()), this, - SLOT(pingIsdsServer())); - } + connect(&m_keepAliveTimer, SIGNAL(timeout()), this, SLOT(pingIsdsServer())); this->attachmentSizeInfo->setText( tr("Total size of attachments is %1 B").arg(0)); - if (convertDbTypeToInt(m_dbType) > DBTYPE_OVM_REQ) { + if (IsdsConversion::boxTypeStrToInt(m_dbType) > DBTYPE_OVM_REQ) { this->dmAllowSubstDelivery->setEnabled(false); this->dmAllowSubstDelivery->hide(); } @@ -821,7 +718,7 @@ } m_attachmentModel.appendAttachmentEntry(msgBase64, - dzPrefix(messageDb, msgId.dmId) + QString("DZ_%1.zfo").arg(msgId.dmId)); + QString("%1_%2.zfo").arg(dzPrefix(messageDb, msgId.dmId)).arg(msgId.dmId)); } } @@ -1005,7 +902,7 @@ } } -int DlgSendMessage::notifyOfPDZ(int pdzCnt) const +int DlgSendMessage::notifyOfPDZ(int pdzCnt) { QString title; QString info; @@ -1029,13 +926,9 @@ info += "\n\n" + tr("Your remaining credit is ") + m_pdzCredit + " Kč"; - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Information); - msgBox.setText(title); - msgBox.setInformativeText(info); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::Yes); - return msgBox.exec(); + return DlgMsgBox::message(this, QMessageBox::Information, title, title, + info, QString(), QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); } bool DlgSendMessage::calculateAndShowTotalAttachSize(void) @@ -1123,17 +1016,12 @@ address = entry.address; boxType = entry.type; if (!entry.active) { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Warning); - msgBox.setWindowTitle(tr("Data box is not active")); - msgBox.setText(tr( - "Recipient with data box ID '%1' does not have active data box.") - .arg(boxId)); - msgBox.setInformativeText( - tr("The message cannot be delivered.")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); + DlgMsgBox::message(this, QMessageBox::Warning, + tr("Data box is not active"), + tr("Recipient with data box ID '%1' does not have active data box.") + .arg(boxId), + tr("The message cannot be delivered."), QString(), + QMessageBox::Ok, QMessageBox::Ok); return; } if (entry.publicSending) { @@ -1143,32 +1031,22 @@ } else if (entry.effectiveOVM) { pdz = false; } else { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setWindowTitle(tr("Cannot send to data box")); - msgBox.setText(tr( - "Cannot send message to recipient with data box ID '%1'.") - .arg(boxId)); - msgBox.setInformativeText(tr( - "You won't be able as user '%1' to send messages into data box '%2'.") - .arg(m_userName).arg(boxId)); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); + DlgMsgBox::message(this, QMessageBox::Critical, + tr("Cannot send to data box"), + tr("Cannot send message to recipient with data box ID '%1'.") + .arg(boxId), + tr("You won't be able as user '%1' to send messages into data box '%2'.") + .arg(m_userName).arg(boxId), + QString(), QMessageBox::Ok, QMessageBox::Ok); return; } } else if (foundBoxes.isEmpty()) { if (result == TaskSearchOwnerFulltext::SOF_SUCCESS) { /* No data box found. */ - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setWindowTitle(tr("Wrong Recipient")); - msgBox.setText(tr( - "Recipient with data box ID '%1' does not exist.") - .arg(boxId)); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); + QMessageBox::critical(this, tr("Wrong Recipient"), + tr("Recipient with data box ID '%1' does not exist.") + .arg(boxId), + QMessageBox::Ok, QMessageBox::Ok); return; } else { /* Search error. */ @@ -1200,7 +1078,6 @@ m_recipientTableModel.appendData(boxId, boxType, name, address, QString(), pdz); - } void DlgSendMessage::addRecipientBoxes(const QStringList &boxIds) @@ -1288,7 +1165,7 @@ envelope.dmPersonalDelivery = this->dmPersonalDelivery->isChecked(); /* Only OVM can change. */ - if (convertDbTypeToInt(m_dbType) > DBTYPE_OVM_REQ) { + if (IsdsConversion::boxTypeStrToInt(m_dbType) > DBTYPE_OVM_REQ) { envelope.dmAllowSubstDelivery = true; } else { envelope.dmAllowSubstDelivery = @@ -1366,7 +1243,7 @@ void DlgSendMessage::sendMessageISDS( const QList &recipEntries) { - QString detailText; + QString infoText; /* List of unique identifiers. */ QList taskIdentifiers; @@ -1399,11 +1276,11 @@ /* Attach envelope and attachment files to message structure. */ if (!buildDocuments(message.documents)) { - detailText = tr("An error occurred while loading attachments into message."); + infoText = tr("An error occurred while loading attachments into message."); goto finish; } if (!buildEnvelope(message.envelope)) { - detailText = tr("An error occurred during message envelope creation."); + infoText = tr("An error occurred during message envelope creation."); goto finish; } @@ -1443,98 +1320,9 @@ return; finish: - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setWindowTitle(tr("Send message error")); - msgBox.setText(tr("It has not been possible to send a message to the ISDS server.")); - detailText += "\n\n" + tr("The message will be discarded."); - msgBox.setInformativeText(detailText); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.exec(); + infoText += "\n\n" + tr("The message will be discarded."); + DlgMsgBox::message(this, QMessageBox::Critical, tr("Send message error"), + tr("It has not been possible to send a message to the ISDS server."), + infoText, QString(), QMessageBox::Ok); this->close(); } - -void DlgSendMessage::buildEnvelopeWebDatovka( - JsonLayer::Envelope &envelope) const -{ - /* Set mandatory fields of envelope. */ - envelope.dmAnnotation = this->subjectText->text(); - - /* Set optional fields. */ - envelope.dmSenderIdent = this->dmSenderIdent->text(); - envelope.dmRecipientIdent = this->dmRecipientIdent->text(); - envelope.dmSenderRefNumber = this->dmSenderRefNumber->text(); - envelope.dmRecipientRefNumber = this->dmRecipientRefNumber->text(); - envelope.dmLegalTitleLaw = this->dmLegalTitleLaw->text(); - envelope.dmLegalTitleYear = this->dmLegalTitleYear->text(); - envelope.dmLegalTitleSect = this->dmLegalTitleSect->text(); - envelope.dmLegalTitlePar = this->dmLegalTitlePar->text(); - envelope.dmLegalTitlePoint = this->dmLegalTitlePoint->text(); - envelope.dmPersonalDelivery = this->dmPersonalDelivery->isChecked(); - envelope.dmPublishOwnID = this->dmPublishOwnID->isChecked(); - envelope.dmOVM = m_dbEffectiveOVM; - - /* Only OVM can change. */ - if (convertDbTypeToInt(m_dbType) > DBTYPE_OVM_REQ) { - envelope.dmAllowSubstDelivery = true; - } else { - envelope.dmAllowSubstDelivery = - this->dmAllowSubstDelivery->isChecked(); - } -} - -void DlgSendMessage::buildFileListWebDatovka( - QList &fileList) const -{ - QModelIndex index; - - for (int row = 0; row < m_attachmentModel.rowCount(); ++row) { - - index = m_attachmentModel.index(row, DbFlsTblModel::FNAME_COL); - if (!index.isValid()) { - Q_ASSERT(0); - continue; - } - - JsonLayer::File file; - file.fName = index.data(Qt::DisplayRole).toString(); - - index = - m_attachmentModel.index(row, DbFlsTblModel::CONTENT_COL); - if (!index.isValid()) { - Q_ASSERT(0); - continue; - } - - file.fContent = index.data(Qt::DisplayRole).toByteArray(); - fileList.append(file); - } -} - -void DlgSendMessage::sendMessageWebDatovka( - const QList &recipEntries) -{ - /* Get account ID */ - int accountID = getWebDatovkaAccountId(m_userName); - - /* Create recipient list. */ - JsonLayer::Recipient recipient; - QList recipientList; - foreach (const BoxContactsModel::PartialEntry &e, recipEntries) { - recipient.recipientDbId = e.id; - recipient.toHands = this->dmToHands->text(); - recipient.recipientName = e.name; - recipient.recipientAddress = e.address; - recipientList.append(recipient); - } - - JsonLayer::Envelope envelope; - buildEnvelopeWebDatovka(envelope); - QList fileList; - buildFileListWebDatovka(fileList); - - TaskSendMessageMojeId *task = new (std::nothrow) TaskSendMessageMojeId( - m_userName, accountID, recipientList, envelope, fileList); - task->setAutoDelete(true); - globWorkPool.assignHi(task); -} diff -Nru datovka-4.8.3/src/gui/dlg_send_message.h datovka-4.9.3/src/gui/dlg_send_message.h --- datovka-4.8.3/src/gui/dlg_send_message.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_send_message.h 2017-09-06 11:49:23.000000000 +0000 @@ -38,7 +38,6 @@ #include "src/models/files_model.h" #include "src/worker/task.h" #include "src/worker/task_send_message.h" -#include "src/web/json.h" #include "ui_dlg_send_message.h" /*! @@ -46,12 +45,12 @@ * * @param[in] messageDb Message database. * @param[in] dmId Message identifier number. - * @return Prefix. + * @return Prefix strings 'DDZ', 'ODZ' or 'DZ'. * * @todo Move this function somewhere else * (and clean up the code of the following dialogue. */ -const QString &dzPrefix(MessageDb *messageDb, qint64 dmId); +const QString &dzPrefix(const MessageDb *messageDb, qint64 dmId); /*! * @brief Send message dialogue. @@ -199,16 +198,6 @@ const QString &dbIDRecipient, const QString &recipientName, bool isPDZ, qint64 dmId); - /*! - * @brief Gathers status after sending messages via WebDatovka. - * - * @param[in] userName User name identifying the sender account. - * @param[in] results List of result state descriptions. - * @param[in] error Error description. - */ - void collectSendMessageStatusWebDatovka(const QString &userName, - const QStringList &results, const QString &error); - private: /*! * @brief Initialises the dialogue content. @@ -246,7 +235,7 @@ * @return QMessageBox::StandardButton value describing the pressed * button. */ - int notifyOfPDZ(int pdzCount) const; + int notifyOfPDZ(int pdzCount); /*! * @brief Calculates and shows total attachment size. @@ -315,28 +304,6 @@ void sendMessageISDS( const QList &recipEntries); - /*! - * @brief Construct JSON envelope description. - * - * @param[out] envelope Envelope to be set. - */ - void buildEnvelopeWebDatovka(JsonLayer::Envelope &envelope) const; - - /*! - * @brief Construct list of JSON attachment descriptions. - * - * @param[out] fileList File list to append entries to. - */ - void buildFileListWebDatovka(QList &fileList) const; - - /*! - * @brief Send messages via WebDatovka interface. - * - * @param[in] recipEntries List of recipients. - */ - void sendMessageWebDatovka( - const QList &recipEntries); - QTimer m_keepAliveTimer; /*!< Keeps connection to ISDS alive. */ const QList m_messageDbSetList; /*!< Available accounts.*/ @@ -347,7 +314,6 @@ bool m_dbEffectiveOVM; /*! True if selected data box has effective OVM. */ bool m_dbOpenAddressing; /*! True if selected box has open addressing. */ bool m_isLogged; /*!< True if account has already logged in. */ - bool m_isWebDatovkaAccount; /*!< True if this is a WebDatovka account. */ QString m_lastAttAddPath; /*! Last attachment location. */ QString m_pdzCredit; /*! String containing credit value. */ diff -Nru datovka-4.8.3/src/gui/dlg_tag.cpp datovka-4.9.3/src/gui/dlg_tag.cpp --- datovka-4.8.3/src/gui/dlg_tag.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_tag.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,47 +22,69 @@ */ #include -#include +#include "src/gui/dlg_msg_box_informative.h" #include "src/gui/dlg_tag.h" -#include "src/web/json.h" +#include "src/io/tag_db.h" +#include "ui_dlg_tag.h" -DlgTag::DlgTag(const QString &userName, TagDb *tagDb, - bool isWebDatovkaAccount, QWidget *parent) +DlgTag::DlgTag(const TagItem &tag, QWidget *parent) : QDialog(parent), - m_userName(userName), - m_tagDbPtr(tagDb), - m_isWebDatovkaAccount(isWebDatovkaAccount), - m_tagItem() + m_ui(new (std::nothrow) Ui::DlgTag), + m_tagItem(tag) { - setupUi(this); + m_ui->setupUi(this); + + m_ui->currentColor->setEnabled(false); + m_ui->tagNamelineEdit->setText(m_tagItem.name); + tagNameChanged(m_tagItem.name); + setPreviewButtonColor(); - initDlg(); + connect(m_ui->tagNamelineEdit, SIGNAL(textChanged(QString)), + this, SLOT(tagNameChanged(QString))); + connect(m_ui->changeColorPushButton, SIGNAL(clicked()), + this, SLOT(chooseNewColor())); } -DlgTag::DlgTag(const QString &userName, TagDb *tagDb, - bool isWebDatovkaAccount, const TagItem &tag, QWidget *parent) - : QDialog(parent), - m_userName(userName), - m_tagDbPtr(tagDb), - m_isWebDatovkaAccount(isWebDatovkaAccount), - m_tagItem(tag) +DlgTag::~DlgTag(void) +{ + delete m_ui; +} + +bool DlgTag::createTag(TagDb *tagDb, QWidget *parent) { - setupUi(this); + if (Q_UNLIKELY(Q_NULLPTR == tagDb)) { + Q_ASSERT(0); + return false; + } - initDlg(); + DlgTag dlg(TagItem(), parent); + if (dlg.exec() == QDialog::Accepted) { + return saveTag(tagDb, dlg.m_tagItem, parent); + } + return false; } -void DlgTag::initDlg(void) +bool DlgTag::editTag(TagDb *tagDb, const TagItem &tag, QWidget *parent) { - this->currentColor->setEnabled(false); - this->tagNamelineEdit->setText(m_tagItem.name); - setPreviewButtonColor(); + if (Q_UNLIKELY(Q_NULLPTR == tagDb)) { + Q_ASSERT(0); + return false; + } + + DlgTag dlg(tag, parent); + if (dlg.exec() == QDialog::Accepted) { + return saveTag(tagDb, dlg.m_tagItem, parent); + } + return false; +} + +void DlgTag::tagNameChanged(const QString &tagName) +{ + m_tagItem.name = tagName; - connect(this->changeColorPushButton, SIGNAL(clicked()), this, - SLOT(chooseNewColor())); - connect(this->buttonBox, SIGNAL(accepted()), this, - SLOT(saveTag())); + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled( + !tagName.isEmpty()); } void DlgTag::chooseNewColor(void) @@ -79,86 +101,42 @@ } } -void DlgTag::saveTag(void) +void DlgTag::setPreviewButtonColor(void) { - m_tagItem.name = this->tagNamelineEdit->text(); + QPalette pal(m_ui->currentColor->palette()); + pal.setColor(QPalette::Button, QColor("#" + m_tagItem.colour)); + const QString style = "border-style: outset; background-color: "; + m_ui->currentColor->setStyleSheet(style + "#" + m_tagItem.colour); +} - if (m_tagItem.name.isEmpty()) { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setWindowTitle(tr("Tag error")); - msgBox.setText(tr("Tag name is empty.")); - msgBox.setInformativeText(tr("Tag wasn't created.")); - msgBox.exec(); - return; - } - - Q_ASSERT(TagItem::isValidColourStr(m_tagItem.colour)); - - JsonLayer jsLayer; - QString errStr; - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - - if (m_tagItem.id >= 0) { - - if (m_isWebDatovkaAccount) { - Q_ASSERT(!m_userName.isEmpty()); - if (!jsLayer.updateTag(m_userName, m_tagItem.id, - m_tagItem.name, m_tagItem.colour, errStr)) { - msgBox.setWindowTitle(tr("Tag update error")); - msgBox.setText(tr("Tag with name '%1'' wasn't " - "updated in the WebDatovka database.").arg( - m_tagItem.name)); - msgBox.setInformativeText(errStr); - msgBox.exec(); - return; - } - } - m_tagDbPtr->updateTag(m_tagItem.id, m_tagItem.name, - m_tagItem.colour); +bool DlgTag::saveTag(TagDb *tagDb, const TagItem &tagItem, QWidget *parent) +{ + if (Q_UNLIKELY(Q_NULLPTR == tagDb)) { + Q_ASSERT(0); + return false; + } + if (Q_UNLIKELY(tagItem.name.isEmpty())) { + DlgMsgBox::message(parent, QMessageBox::Critical, + tr("Tag error"), tr("Tag name is empty."), + tr("Tag wasn't created."), QString()); + return false; + } + + Q_ASSERT(TagItem::isValidColourStr(tagItem.colour)); + + if (tagItem.id >= 0) { + tagDb->updateTag(tagItem.id, tagItem.name, tagItem.colour); } else { - if (m_isWebDatovkaAccount) { - Q_ASSERT(!m_userName.isEmpty()); - int tagId = jsLayer.createTag(m_userName, - m_tagItem.name, m_tagItem.colour, errStr); - if (tagId <= 0) { - msgBox.setWindowTitle(tr("Tag insert error")); - msgBox.setText(tr("Tag with name '%1'' wasn't'" - " created in WebDatovka database.").arg( - m_tagItem.name)); - msgBox.setInformativeText(errStr); - msgBox.exec(); - return; - } - if (!m_tagDbPtr->insertUpdateWebDatovkaTag(tagId, - m_tagItem.name, m_tagItem.colour)) { - msgBox.setWindowTitle(tr("Tag error")); - msgBox.setText(tr("Tag with name '%1'' already " - "exists in database.").arg(m_tagItem.name)); - msgBox.setInformativeText( - tr("Tag wasn't created again.")); - msgBox.exec(); - } - } else { - if (!m_tagDbPtr->insertTag(m_tagItem.name, - m_tagItem.colour)) { - msgBox.setWindowTitle(tr("Tag error")); - msgBox.setText(tr("Tag with name '%1'' already " - "exists in database.").arg(m_tagItem.name)); - msgBox.setInformativeText( - tr("Tag wasn't created again.")); - msgBox.exec(); - } + if (!tagDb->insertTag(tagItem.name, tagItem.colour)) { + DlgMsgBox::message(parent, QMessageBox::Critical, + tr("Tag error"), + tr("Tag with name '%1'' already exists in database.") + .arg(tagItem.name), + tr("Tag wasn't created."), QString()); + return false; } } -} -void DlgTag::setPreviewButtonColor(void) -{ - QPalette pal = this->currentColor->palette(); - pal.setColor(QPalette::Button, QColor("#" + m_tagItem.colour)); - const QString style = "border-style: outset; background-color: "; - this->currentColor->setStyleSheet(style + "#" + m_tagItem.colour); + return true; } diff -Nru datovka-4.8.3/src/gui/dlg_tag.h datovka-4.9.3/src/gui/dlg_tag.h --- datovka-4.8.3/src/gui/dlg_tag.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_tag.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,43 +28,62 @@ #include #include "src/delegates/tag_item.h" -#include "ui_dlg_tag.h" -#include "src/io/tag_db.h" + +class TagDb; /* Forward declaration. */ + +namespace Ui { + class DlgTag; +} /*! * @brief Create new tag dialogue. */ -class DlgTag : public QDialog, public Ui::TagDialog { - Q_OBJECT +class DlgTag : public QDialog { + Q_OBJECT -public: +private: /*! * @brief Constructor. * - * @param[in] userName Account user name. - * @param[in] isWebDatovka is Webdatovka account. - * @param[in] parent Parent widget. + * @param[in] tag Tag to be modified. + * @param[in] parent Parent widget. */ - explicit DlgTag(const QString &userName, TagDb *tagDb, - bool isWebDatovkaAccount, QWidget *parent = Q_NULLPTR); + explicit DlgTag(const TagItem &tag, QWidget *parent = Q_NULLPTR); +public: /*! - * @brief Constructor. + * @brief Destructor. + */ + ~DlgTag(void); + + /*! + * @brief Create new tag. * - * @param[in] userName Account user name. - * @param[in] isWebDatovka is Webdatovka account. - * @param[in] tag Tag. - * @param[in] parent Parent widget. + * @param[in] tagDb Tag database. + * @param[in] parent Parent widget. */ - explicit DlgTag(const QString &userName, TagDb *tagDb, - bool isWebDatovkaAccount, const TagItem &tag, + static + bool createTag(TagDb *tagDb, QWidget *parent = Q_NULLPTR); + + /*! + * @brief Edit existing tag. + * + * @param[in] tagDb Tag database. + * @param[in] tag Tag to be modified. + * @param[in] parent Parent widget. + * @return True when tag has been changed. + */ + static + bool editTag(TagDb *tagDb, const TagItem &tag, QWidget *parent = Q_NULLPTR); private slots: /*! - * @brief Insert or update tag data into database. + * @brief Sets window elements according to tag name. + * + * @param[in] tagName Tag name. */ - void saveTag(void); + void tagNameChanged(const QString &tagName); /*! * @brief Choose or change tag colour. @@ -73,18 +92,24 @@ private: /*! - * @brief Initialises new tag dialogue. + * @brief Set actual tag colour on the preview button. */ - void initDlg(void); + void setPreviewButtonColor(void); /*! - * @brief Set actual tag colour on the preview button. + * @brief Insert or update tag data into database. + * + * @param[in] tagDb Tag database. + * @param[in] tagItem Tag to be saved. + * @param[in] parent Parent widget. + * @return True when tag has been saved. */ - void setPreviewButtonColor(void); + static + bool saveTag(TagDb *tagDb, const TagItem &tagItem, + QWidget *parent = Q_NULLPTR); + + Ui::DlgTag *m_ui; /*!< UI generated from UI file. */ - const QString m_userName; /*!< Account username. */ - TagDb *m_tagDbPtr; /*!< Tag db pointer. */ - const bool m_isWebDatovkaAccount; /*!< is WebDatovka account. */ TagItem m_tagItem; /*!< Created tag. */ }; diff -Nru datovka-4.8.3/src/gui/dlg_tags.cpp datovka-4.9.3/src/gui/dlg_tags.cpp --- datovka-4.8.3/src/gui/dlg_tags.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_tags.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -25,152 +25,173 @@ #include #include "src/common.h" -#include "src/delegates/tags_delegate.h" #include "src/gui/dlg_tag.h" #include "src/gui/dlg_tags.h" -#include "src/io/tag_db_container.h" -#include "src/models/tags_model.h" +#include "src/io/tag_db.h" +#include "ui_dlg_tags.h" #define WRONG_TAG_ID -1 /** TODO -- Remove. */ -DlgTags::DlgTags(const QString &userName, TagDb *tagDb, QWidget *parent) - : QDialog(parent), - m_userName(userName), - m_tagDbPtr(tagDb), - m_msgIdList(), - m_msgIdWebDatovkaList(), - m_tagsDelegate(Q_NULLPTR), - m_tagsModel(Q_NULLPTR), - m_retCode(NO_ACTION), - m_isWebDatovkaAccount(false) -{ - setupUi(this); - initDlg(); -} - DlgTags::DlgTags(const QString &userName, TagDb *tagDb, - const QList &msgIdList, - const QList &msgIdWebDatovkaList, QWidget *parent) + const QList &msgIdList, QWidget *parent) : QDialog(parent), + m_ui(new (std::nothrow) Ui::DlgTags), m_userName(userName), m_tagDbPtr(tagDb), m_msgIdList(msgIdList), - m_msgIdWebDatovkaList(msgIdWebDatovkaList), - m_tagsDelegate(Q_NULLPTR), - m_tagsModel(Q_NULLPTR), - m_retCode(NO_ACTION), - m_isWebDatovkaAccount(false) + m_availableTagsDelegate(this), + m_availableTagsModel(this), + m_assignedTagsDelegate(this), + m_assignedTagsModel(this), + m_retCode(NO_ACTION) { - setupUi(this); + m_ui->setupUi(this); initDlg(); - selectAllAssingedTagsFromMsgs(); + fillTagsToListViews(); + //selectAllAssingedTagsFromMsgs(); } DlgTags::~DlgTags(void) { - if (Q_NULLPTR != m_tagsDelegate) { - delete m_tagsDelegate; - } - if (Q_NULLPTR != m_tagsModel) { - delete m_tagsModel; + delete m_ui; +} + +enum DlgTags::ReturnCode DlgTags::editAvailable(const QString &userName, + TagDb *tagDb, QWidget *parent) +{ + if (Q_UNLIKELY(tagDb == Q_NULLPTR)) { + Q_ASSERT(0); + return NO_ACTION; } + + DlgTags dlg(userName, tagDb, QList(), parent); + dlg.exec(); + + return dlg.m_retCode; } -int DlgTags::exec(void) +enum DlgTags::ReturnCode DlgTags::editAssignment(const QString &userName, + TagDb *tagDb, const QList &msgIdList, QWidget *parent) { - QDialog::exec(); + if (Q_UNLIKELY((tagDb == Q_NULLPTR) || msgIdList.isEmpty())) { + Q_ASSERT(0); + return NO_ACTION; + } + + DlgTags dlg(userName, tagDb, msgIdList, parent); + dlg.exec(); - return m_retCode; + return dlg.m_retCode; } void DlgTags::addTag(void) { - QDialog *tagDlg = new DlgTag(m_userName, m_tagDbPtr, - m_isWebDatovkaAccount, this); - tagDlg->exec(); - tagDlg->deleteLater(); + DlgTag::createTag(m_tagDbPtr, this); + + fillTagsToListViews(); +} + +/*! + * @brief Get tag id from index. + * + * @param[in] idx Model index. + * @return Tag id if success else -1. + */ +static inline +int getTagIdFromIndex(const QModelIndex &idx) +{ + if (Q_UNLIKELY(!idx.isValid())) { + return WRONG_TAG_ID; + } + + if (Q_UNLIKELY(!idx.data().canConvert())) { + return WRONG_TAG_ID; + } + + TagItem tagItem(qvariant_cast(idx.data())); - fillTagsToListView(); + return tagItem.id; +} + +/*! + * @brief Get selected index. + * + * @param[in] view List view. + * @return Selected index. + */ +static inline +QModelIndex selectedIndex(const QListView *view) +{ + if (Q_UNLIKELY(view == Q_NULLPTR)) { + Q_ASSERT(0); + return QModelIndex(); + } + + return view->selectionModel()->currentIndex(); } void DlgTags::updateTag(void) { TagItem tagItem(m_tagDbPtr->getTagData( - getTagIdFromIndex(tagListView->selectionModel()->currentIndex()))); - - QDialog *tagDlg = new DlgTag(m_userName, m_tagDbPtr, - m_isWebDatovkaAccount, tagItem, this); - int retVal = tagDlg->exec(); - tagDlg->deleteLater(); + getTagIdFromIndex(selectedIndex(m_ui->availableTagsView)))); - if (retVal == QDialog::Accepted) { + if (DlgTag::editTag(m_tagDbPtr, tagItem, this)) { /* Existing tag has very likely just been changed. */ m_retCode = TAGS_CHANGED; } - fillTagsToListView(); + fillTagsToListViews(); } -void DlgTags::deleteTag(void) +/*! + * @brief Get selected indexes. + * + * @param[in] view List view. + * @return Selected indexes. + */ +static inline +QModelIndexList selectedIndexes(const QListView *view) { - QModelIndexList slctIdxs(tagListView->selectionModel()->selectedRows()); + if (Q_UNLIKELY(view == Q_NULLPTR)) { + Q_ASSERT(0); + return QModelIndexList(); + } + + return view->selectionModel()->selectedRows(); +} - if (slctIdxs.isEmpty()) { +void DlgTags::deleteTag(void) +{ + QModelIndexList slctIdxs(selectedIndexes(m_ui->availableTagsView)); + if (Q_UNLIKELY(slctIdxs.isEmpty())) { /* Nothing to do. */ return; } foreach (const QModelIndex &idx, slctIdxs) { - - if (m_isWebDatovkaAccount) { - if (!m_jsonsLayer.deleteTag(m_userName, - getTagIdFromIndex(idx), m_errStr)) { - continue; - } - } m_tagDbPtr->deleteTag(getTagIdFromIndex(idx)); } /* Existing tags have been removed. */ m_retCode = TAGS_CHANGED; - fillTagsToListView(); + fillTagsToListViews(); } void DlgTags::assignSelectedTagsToMsgs(void) { - QModelIndexList slctIdxs(tagListView->selectionModel()->selectedRows()); - - if (slctIdxs.isEmpty()) { + QModelIndexList slctIdxs(selectedIndexes(m_ui->availableTagsView)); + if (Q_UNLIKELY(slctIdxs.isEmpty())) { /* Nothing to do. */ return; } Q_ASSERT(!m_userName.isEmpty()); - if (m_isWebDatovkaAccount) { - if (m_msgIdList.count() != m_msgIdWebDatovkaList.count()) { - return; - } - for (int i = 0; i < m_msgIdList.count(); ++i) { - foreach (const QModelIndex &idx, slctIdxs) { - if (!m_jsonsLayer.assignTag(m_userName, - getTagIdFromIndex(idx), - m_msgIdWebDatovkaList.at(i), m_errStr)) { - continue; - } - m_tagDbPtr->assignTagToMsg(m_userName, - getTagIdFromIndex(idx), - m_msgIdList.at(i)); - } - - } - } else { - foreach (const qint64 &msgId, m_msgIdList) { - foreach (const QModelIndex &idx, slctIdxs) { - m_tagDbPtr->assignTagToMsg(m_userName, - getTagIdFromIndex(idx), msgId); - } + foreach (const qint64 &msgId, m_msgIdList) { + foreach (const QModelIndex &idx, slctIdxs) { + m_tagDbPtr->assignTagToMsg(m_userName, + getTagIdFromIndex(idx), msgId); } } @@ -178,41 +199,24 @@ if (m_retCode != TAGS_CHANGED) { m_retCode = ASSIGMENT_CHANGED; } + + fillTagsToListViews(); } void DlgTags::removeSelectedTagsFromMsgs(void) { - QModelIndexList slctIdxs(tagListView->selectionModel()->selectedRows()); - - if (slctIdxs.isEmpty()) { + QModelIndexList slctIdxs(selectedIndexes(m_ui->assignedTagsView)); + if (Q_UNLIKELY(slctIdxs.isEmpty())) { /* Nothing to do. */ return; } Q_ASSERT(!m_userName.isEmpty()); - if (m_isWebDatovkaAccount) { - if (m_msgIdList.count() != m_msgIdWebDatovkaList.count()) { - return; - } - for (int i = 0; i < m_msgIdList.count(); ++i) { - foreach (const QModelIndex &idx, slctIdxs) { - if (!m_jsonsLayer.removeTag(m_userName, - getTagIdFromIndex(idx), - m_msgIdWebDatovkaList.at(i), m_errStr)) { - continue; - } - m_tagDbPtr->removeTagFromMsg(m_userName, - getTagIdFromIndex(idx), m_msgIdList.at(i)); - } - - } - } else { - foreach (const qint64 &msgId, m_msgIdList) { - foreach (const QModelIndex &idx, slctIdxs) { - m_tagDbPtr->removeTagFromMsg(m_userName, - getTagIdFromIndex(idx), msgId); - } + foreach (const qint64 &msgId, m_msgIdList) { + foreach (const QModelIndex &idx, slctIdxs) { + m_tagDbPtr->removeTagFromMsg(m_userName, + getTagIdFromIndex(idx), msgId); } } @@ -220,141 +224,160 @@ if (m_retCode != TAGS_CHANGED) { m_retCode = ASSIGMENT_CHANGED; } + + fillTagsToListViews(); } void DlgTags::removeAllTagsFromMsgs(void) { Q_ASSERT(!m_userName.isEmpty()); - if (m_isWebDatovkaAccount) { - if (m_msgIdList.count() != m_msgIdWebDatovkaList.count()) { - return; - } - for (int i = 0; i < m_msgIdList.count(); ++i) { - if (!m_jsonsLayer.removeAllTags(m_userName, - m_msgIdWebDatovkaList.at(i), m_errStr)) { - continue; - } - m_tagDbPtr->removeAllTagsFromMsg(m_userName, - m_msgIdList.at(i)); - } - } else { - foreach (const qint64 &msgId, m_msgIdList) { - m_tagDbPtr->removeAllTagsFromMsg(m_userName, msgId); - } + foreach (const qint64 &msgId, m_msgIdList) { + m_tagDbPtr->removeAllTagsFromMsg(m_userName, msgId); } /* Tag assignment was changed. */ if (m_retCode != TAGS_CHANGED) { m_retCode = ASSIGMENT_CHANGED; } + + fillTagsToListViews(); } -void DlgTags::handleSelectionChanged(void) +void DlgTags::handleAvailableSelectionChange(void) { - QModelIndexList slctIdxs(tagListView->selectionModel()->selectedRows()); + QModelIndexList slctIdxs(selectedIndexes(m_ui->availableTagsView)); - if (slctIdxs.isEmpty()) { - this->pushButtonUpdate->setEnabled(false); - this->pushButtonDelete->setEnabled(false); - this->pushButtonRemove->setEnabled(false); - this->pushButtonAssign->setEnabled(false); - } else { - if (slctIdxs.count() > 1) { - this->pushButtonUpdate->setEnabled(false); - } else { - this->pushButtonUpdate->setEnabled(true); - } - this->pushButtonDelete->setEnabled(true); - this->pushButtonRemove->setEnabled(true); - this->pushButtonAssign->setEnabled(true); + m_ui->deleteTagButton->setEnabled(!slctIdxs.isEmpty()); + m_ui->updateTagButton->setEnabled(slctIdxs.count() == 1); + m_ui->assignButton->setEnabled(!slctIdxs.isEmpty()); + + if (!slctIdxs.isEmpty()) { + m_ui->assignedTagsView->clearSelection(); } } -void DlgTags::fillTagsToListView(void) +void DlgTags::handleAssignedSelectionChange(void) { - TagItemList tagList(m_tagDbPtr->getAllTags()); - tagList.sortNames(); + QModelIndexList slctIdxs(selectedIndexes(m_ui->assignedTagsView)); + + m_ui->removeButton->setEnabled(!slctIdxs.isEmpty()); - m_tagsModel->setTagList(tagList); + if (!slctIdxs.isEmpty()) { + m_ui->availableTagsView->clearSelection(); + } } -void DlgTags::initDlg(void) +void DlgTags::fillTagsToListViews(void) { - m_isWebDatovkaAccount = isWebDatovkaAccount(m_userName); + Q_ASSERT(!m_userName.isEmpty()); - m_tagsDelegate = new TagsDelegate(this); - m_tagsModel = new TagsModel(this); + /* This should also disable all related buttons. */ + m_ui->availableTagsView->clearSelection(); + m_ui->assignedTagsView->clearSelection(); + + /* Get all available tags. */ + QSet availableTags(m_tagDbPtr->getAllTags().toSet()); + + /* + * Get set of tags assigned to any supplied message and to all supplied + * messages. + */ + QSet assignedTagsUnion, assignedTagsIntersection; + bool firstMsg = true; + foreach (qint64 dmId, m_msgIdList) { + const QSet msgTagSet( + m_tagDbPtr->getMessageTags(m_userName, dmId).toSet()); + + assignedTagsUnion += msgTagSet; + if (firstMsg) { + assignedTagsIntersection = msgTagSet; + firstMsg = false; + } else { + assignedTagsIntersection.intersect(msgTagSet); + } + } - tagListView->setItemDelegate(m_tagsDelegate); - tagListView->setModel(m_tagsModel); + { + /* + * Don't disable model interaction for tags that are already + * assigned to all related messages. + */ - tagListView->setSelectionMode(QAbstractItemView::ExtendedSelection); - tagListView->setSelectionBehavior(QAbstractItemView::SelectRows); + TagItemList availableTagList(availableTags.toList()); + availableTagList.sortNames(); + m_availableTagsModel.setTagList(availableTagList); + } - this->pushButtonUpdate->setEnabled(false); - this->pushButtonDelete->setEnabled(false); - this->pushButtonRemove->setEnabled(false); - this->pushButtonAssign->setEnabled(false); + { + TagItemList assignedTagList(assignedTagsUnion.toList()); + assignedTagList.sortNames(); + m_assignedTagsModel.setTagList(assignedTagList); - this->tagAssignGroup->setEnabled(false); - this->tagAssignGroup->setVisible(false); + m_ui->removeAllButton->setEnabled(assignedTagList.count() > 0); + } +} - connect(this->pushButtonAdd, SIGNAL(clicked()), this, - SLOT(addTag())); - connect(this->pushButtonUpdate, SIGNAL(clicked()), this, - SLOT(updateTag())); - connect(this->pushButtonDelete, SIGNAL(clicked()), this, - SLOT(deleteTag())); - connect(tagListView->selectionModel(), +void DlgTags::initDlg(void) +{ + m_ui->availableTagsView->setItemDelegate(&m_availableTagsDelegate); + m_ui->availableTagsView->setModel(&m_availableTagsModel); + m_ui->availableTagsView->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_ui->availableTagsView->setSelectionBehavior(QAbstractItemView::SelectRows); + + m_ui->assignedTagsView->setItemDelegate(&m_assignedTagsDelegate); + m_ui->assignedTagsView->setModel(&m_assignedTagsModel); + m_ui->assignedTagsView->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_ui->assignedTagsView->setSelectionBehavior(QAbstractItemView::SelectRows); + + connect(m_ui->availableTagsView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, - SLOT(handleSelectionChanged())); + SLOT(handleAvailableSelectionChange())); + connect(m_ui->assignedTagsView->selectionModel(), + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, + SLOT(handleAssignedSelectionChange())); - /* any messages was selected */ - if (!m_msgIdList.isEmpty()) { + connect(m_ui->addTagButton, SIGNAL(clicked()), this, SLOT(addTag())); + connect(m_ui->deleteTagButton, SIGNAL(clicked()), this, + SLOT(deleteTag())); + connect(m_ui->updateTagButton, SIGNAL(clicked()), this, + SLOT(updateTag())); - connect(this->pushButtonAssign, SIGNAL(clicked()), this, + /* Message tag assignment is going to be edited. */ + if (!m_msgIdList.isEmpty()) { + connect(m_ui->assignButton, SIGNAL(clicked()), this, SLOT(assignSelectedTagsToMsgs())); - connect(this->pushButtonRemove, SIGNAL(clicked()), this, + connect(m_ui->removeButton, SIGNAL(clicked()), this, SLOT(removeSelectedTagsFromMsgs())); - connect(this->pushButtonRemoveAll, SIGNAL(clicked()), this, + connect(m_ui->removeAllButton, SIGNAL(clicked()), this, SLOT(removeAllTagsFromMsgs())); - - this->tagAssignGroup->setVisible(true); - this->tagAssignGroup->setEnabled(true); - } - - fillTagsToListView(); -} - -int DlgTags::getTagIdFromIndex(const QModelIndex &idx) -{ - if (!idx.isValid()) { - return WRONG_TAG_ID; } - if (!idx.data().canConvert()) { - return WRONG_TAG_ID; - } + m_ui->deleteTagButton->setEnabled(false); + m_ui->updateTagButton->setEnabled(false); - TagItem tagItem(qvariant_cast(idx.data())); + m_ui->assignButton->setEnabled(false); + m_ui->assignButton->setVisible(!m_msgIdList.isEmpty()); + m_ui->removeButton->setEnabled(false); + m_ui->removeButton->setVisible(!m_msgIdList.isEmpty()); - return tagItem.id; + m_ui->assignedGroup->setEnabled(!m_msgIdList.isEmpty()); + m_ui->assignedGroup->setVisible(!m_msgIdList.isEmpty()); } void DlgTags::selectAllAssingedTagsFromMsgs(void) { - int rows = tagListView->model()->rowCount(); + int rows = m_ui->availableTagsView->model()->rowCount(); for (int i = 0; i < rows; ++i) { - const QModelIndex idx = tagListView->model()->index(i, 0); + const QModelIndex idx = m_ui->availableTagsView->model()->index(i, 0); const qint64 id = getTagIdFromIndex(idx); foreach (const qint64 &msgId, m_msgIdList) { const TagItemList tags = m_tagDbPtr->getMessageTags(m_userName, msgId); foreach (const TagItem &tag, tags) { if (tag.id == id) { - tagListView->selectionModel()->select( + m_ui->availableTagsView->selectionModel()->select( idx, QItemSelectionModel::Select); } } diff -Nru datovka-4.8.3/src/gui/dlg_tags.h datovka-4.9.3/src/gui/dlg_tags.h --- datovka-4.8.3/src/gui/dlg_tags.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_tags.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,15 +27,20 @@ #include #include -#include "ui_dlg_tags.h" -#include "src/io/tag_db.h" -#include "src/web/json.h" +#include "src/delegates/tags_delegate.h" +#include "src/models/tags_model.h" + +class TagDb; /* Forward declaration. */ + +namespace Ui { + class DlgTags; +} /*! * @brief Tags management dialogue. */ -class DlgTags : public QDialog, public Ui::TagsDialog { - Q_OBJECT +class DlgTags : public QDialog { + Q_OBJECT public: /*! @@ -47,40 +52,49 @@ TAGS_CHANGED /*!< Actual tags have been deleted or changed. */ }; +private: /*! * @brief Constructor. * - * @param[in] userName Account user name. - * @param[in] parent Parent widget. - */ - explicit DlgTags(const QString &userName, TagDb *tagDb, - QWidget *parent = Q_NULLPTR); - - /*! - * @brief Constructor. - * - * @param[in] userName Account user name. - * @param[in] msgIdList List of message ids. - * @param[in] msgIdWebDatovkaList List of message ids. - * @param[in] parent Parent widget. + * @param[in] userName Account user name. + * @param[in] tagDb Pointer to tag database. + * @param[in] msgIdList List of message ids, empty list if no assignment + * should be edited. + * @param[in] parent Parent widget. */ explicit DlgTags(const QString &userName, TagDb *tagDb, - const QList &msgIdList, - const QList &msgIdWebDatovkaList, QWidget *parent = Q_NULLPTR); + const QList &msgIdList, QWidget *parent = Q_NULLPTR); +public: /*! * @brief Destructor. */ ~DlgTags(void); -public slots: /*! - * @brief Shows the dialogue as a modal dialogue. + * @brief Edit all tags. * - * @return Method returns ReturnCode. + * @param[in] userName Account user name. + * @param[in] tagDb Pointer to tag database. + * @param[in] parent Parent widget. + * @return Return code. */ - virtual - int exec(void) Q_DECL_OVERRIDE; + static + enum ReturnCode editAvailable(const QString &userName, TagDb *tagDb, + QWidget *parent = Q_NULLPTR); + + /*! + * @brief Edit assigned tags. + * + * @param[in] userName Account user name. + * @param[in] tagDb Pointer to tag database. + * @param[in] msgIdList List of message ids. + * @param[in] parent Parent widget. + * @return Return code. + */ + static + enum ReturnCode editAssignment(const QString &userName, TagDb *tagDb, + const QList &msgIdList, QWidget *parent = Q_NULLPTR); private slots: /*! @@ -116,47 +130,45 @@ void removeAllTagsFromMsgs(void); /*! - * @brief Activate/deactivate tag buttons on selection change. + * @brief Activate/deactivate buttons on available selection change. */ - void handleSelectionChanged(void); + void handleAvailableSelectionChange(void); -private: /*! - * @brief Fill all tags to table view from database. + * @brief Activate/deactivate buttons on assigned selection change. */ - void fillTagsToListView(void); + void handleAssignedSelectionChange(void); +private: /*! - * @brief Initialises the dialogue. + * @brief Fill all tag entries into list views from database. */ - void initDlg(void); + void fillTagsToListViews(void); /*! - * @brief Get tag id from index. - * - * @return Tag id if success else -1. + * @brief Initialises the dialogue. */ - int getTagIdFromIndex(const QModelIndex &idx); + void initDlg(void); /*! - * @brief Choose (select) all tags in the listview + * @brief Choose (select) all tags in the list view * which are assigned in selected messages. */ void selectAllAssingedTagsFromMsgs(void); + Ui::DlgTags *m_ui; /*!< UI generated from UI file. */ + const QString m_userName; /*!< Account username. */ TagDb *m_tagDbPtr; /*!< Tag db pointer. */ const QList m_msgIdList; /*!< List of message identifiers. */ - QList m_msgIdWebDatovkaList; /*!< List of message identifiers of WebDatovka. */ - class TagsDelegate *m_tagsDelegate; /*!< Responsible for painting. */ - class TagsModel *m_tagsModel; /*!< Tags model. */ + TagsDelegate m_availableTagsDelegate; /*!< Responsible for painting. */ + TagsModel m_availableTagsModel; /*!< Available tags model. */ - enum ReturnCode m_retCode; /*!< Dialogue return code. */ - bool m_isWebDatovkaAccount; /*!< is WebDatovka account. */ + TagsDelegate m_assignedTagsDelegate; /*!< Responsible for painting. */ + TagsModel m_assignedTagsModel; /*!< Assigned tags model. */ - QString m_errStr; - JsonLayer m_jsonsLayer; + enum ReturnCode m_retCode; /*!< Dialogue return code. */ }; #endif /* _DLG_TAGS_H_ */ diff -Nru datovka-4.8.3/src/gui/dlg_view_zfo.cpp datovka-4.9.3/src/gui/dlg_view_zfo.cpp --- datovka-4.8.3/src/gui/dlg_view_zfo.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_view_zfo.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,6 +36,7 @@ #include "src/io/dbs.h" #include "src/io/filesystem.h" #include "src/io/isds_sessions.h" +#include "src/isds/isds_conversion.h" #include "src/log/log.h" #include "src/model_interaction/attachment_interaction.h" #include "src/settings/preferences.h" @@ -175,11 +176,11 @@ goto fail; } - m_zfoType = ImportZFODialog::IMPORT_MESSAGE_ZFO; + m_zfoType = Imports::IMPORT_MESSAGE; Q_ASSERT(NULL == m_message); m_message = loadZfoData(dummy_session, zfoData, m_zfoType); if (NULL == m_message) { - m_zfoType = ImportZFODialog::IMPORT_DELIVERY_ZFO; + m_zfoType = Imports::IMPORT_DELIVERY; m_message = loadZfoData(dummy_session, zfoData, m_zfoType); if (NULL == m_message) { logError("%s\n", "Cannot parse message data."); @@ -202,11 +203,11 @@ goto fail; } - m_zfoType = ImportZFODialog::IMPORT_MESSAGE_ZFO; + m_zfoType = Imports::IMPORT_MESSAGE; Q_ASSERT(NULL == m_message); m_message = loadZfoFile(dummy_session, zfoFileName, m_zfoType); if (NULL == m_message) { - m_zfoType = ImportZFODialog::IMPORT_DELIVERY_ZFO; + m_zfoType = Imports::IMPORT_DELIVERY; m_message = loadZfoFile(dummy_session, zfoFileName, m_zfoType); if (NULL == m_message) { logError("Cannot parse file '%s'.\n", @@ -225,7 +226,7 @@ { /* TODO -- Adjust splitter sizes. */ - if (ImportZFODialog::IMPORT_DELIVERY_ZFO == m_zfoType) { + if (Imports::IMPORT_DELIVERY == m_zfoType) { this->attachmentTable->hide(); envelopeTextEdit->setHtml( deliveryDescriptionHtml( @@ -323,16 +324,16 @@ envelopeHeaderDescriptionHtml(html, envelope); - html += strongAccountInfoLine(tr("Events"),""); + html += strongAccountInfoLine(tr("Events"), QString()); html += indentDivStart; const struct isds_list *event = envelope->events; while (NULL != event) { isds_event *item = (isds_event *) event->data; html += strongAccountInfoLine( - dateTimeStrFromDbFormat(timevalToDbFormat(item->time), + dateTimeStrFromDbFormat(timevalToDbFormat(item->time), dateTimeDisplayFormat), - item->description); + QString(item->description)); event = event->next; } html += divEnd; @@ -354,24 +355,24 @@ html += "

    " + tr("Identification") + "

    "; - html += strongAccountInfoLine(tr("ID"), envelope->dmID); - html += strongAccountInfoLine(tr("Subject"), envelope->dmAnnotation); - html += strongAccountInfoLine(tr("Message type"), envelope->dmType); + html += strongAccountInfoLine(tr("ID"), QString(envelope->dmID)); + html += strongAccountInfoLine(tr("Subject"), QString(envelope->dmAnnotation)); + html += strongAccountInfoLine(tr("Message type"), QString(envelope->dmType)); html += "
    "; /* Information about message author. */ - html += strongAccountInfoLine(tr("Sender"), envelope->dmSender); - html += strongAccountInfoLine(tr("Sender Databox ID"), envelope->dbIDSender); + html += strongAccountInfoLine(tr("Sender"), QString(envelope->dmSender)); + html += strongAccountInfoLine(tr("Sender Databox ID"), QString(envelope->dbIDSender)); html += strongAccountInfoLine(tr("Sender Address"), - envelope->dmSenderAddress); + QString(envelope->dmSenderAddress)); html += "
    "; - html += strongAccountInfoLine(tr("Recipient"), envelope->dmRecipient); - html += strongAccountInfoLine(tr("Recipient Databox ID"), envelope->dbIDRecipient); + html += strongAccountInfoLine(tr("Recipient"), QString(envelope->dmRecipient)); + html += strongAccountInfoLine(tr("Recipient Databox ID"), QString(envelope->dbIDRecipient)); html += strongAccountInfoLine(tr("Recipient Address"), - envelope->dmRecipientAddress); + QString(envelope->dmRecipientAddress)); html += "

    " + tr("Status") + "

    "; @@ -389,9 +390,10 @@ QString statusString; if (NULL != envelope->dmMessageStatus) { statusString = - QString::number(convertHexToDecIndex(*(envelope->dmMessageStatus))) + + QString::number(IsdsConversion::msgStatusIsdsToDbRepr(*(envelope->dmMessageStatus))) + " -- " + - msgStatusToText(convertHexToDecIndex(*(envelope->dmMessageStatus))); + IsdsConversion::msgStatusDbToText( + IsdsConversion::msgStatusIsdsToDbRepr(*(envelope->dmMessageStatus))); } html += strongAccountInfoLine(tr("Status"), statusString); diff -Nru datovka-4.8.3/src/gui/dlg_view_zfo.h datovka-4.9.3/src/gui/dlg_view_zfo.h --- datovka-4.8.3/src/gui/dlg_view_zfo.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/dlg_view_zfo.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +24,6 @@ #ifndef _DLG_VIEW_ZFO_H_ #define _DLG_VIEW_ZFO_H_ - #include #include "src/models/files_model.h" @@ -43,7 +42,8 @@ * @param[in] zfoFileName Path to the ZFO file. * @param[in] parent Pointer to parent object. */ - explicit DlgViewZfo(const QString &zfoFileName, QWidget *parent = 0); + explicit DlgViewZfo(const QString &zfoFileName, + QWidget *parent = Q_NULLPTR); /*! * @brief Constructor. @@ -51,7 +51,8 @@ * @param[in] zfoData Raw ZFO data. * @param[in] parent Pointer to parent object. */ - explicit DlgViewZfo(const QByteArray &zfoData, QWidget *parent = 0); + explicit DlgViewZfo(const QByteArray &zfoData, + QWidget *parent = Q_NULLPTR); /*! * @brief Destructor. diff -Nru datovka-4.8.3/src/gui/ui/datovka.ui datovka-4.9.3/src/gui/ui/datovka.ui --- datovka-4.8.3/src/gui/ui/datovka.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/datovka.ui 2017-09-06 11:49:23.000000000 +0000 @@ -359,13 +359,15 @@ - + + + @@ -415,6 +417,8 @@ + + @@ -1209,16 +1213,37 @@ QAction::NoRole - + - :/mojeid.png:/mojeid.png + :/icons/16x16/datovka.png:/icons/16x16/datovka.png - Add mojeID account + Records management settings - - Add new mojeID account + + QAction::NoRole + + + + + + :/icons/16x16/datovka.png:/icons/16x16/datovka.png + + + Send to records management + + + QAction::NoRole + + + + + + :/icons/16x16/datovka.png:/icons/16x16/datovka.png + + + Update records management information QAction::NoRole @@ -1227,6 +1252,11 @@ + LoweredTreeView + QTreeView +
    lowered_tree_view.h
    +
    + AttachmentTableView QTableView
    attachment_table_view.h
    @@ -1236,11 +1266,6 @@ QTableView
    lowered_table_view.h
    - - LoweredTreeView - QTreeView -
    lowered_tree_view.h
    -
    diff -Nru datovka-4.8.3/src/gui/ui/dlg_about.ui datovka-4.9.3/src/gui/ui/dlg_about.ui --- datovka-4.8.3/src/gui/ui/dlg_about.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_about.ui 2017-09-06 11:49:23.000000000 +0000 @@ -1,7 +1,7 @@ - AboutDialog - + DlgAbout + 0 diff -Nru datovka-4.8.3/src/gui/ui/dlg_account_from_db.ui datovka-4.9.3/src/gui/ui/dlg_account_from_db.ui --- datovka-4.8.3/src/gui/ui/dlg_account_from_db.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_account_from_db.ui 2017-09-06 11:49:23.000000000 +0000 @@ -1,7 +1,7 @@ - CreateAccountFromDb - + DlgCreateAccountFromDb + 0 @@ -11,7 +11,7 @@ - Create account form database file + Create account from database file @@ -30,7 +30,7 @@ - Database file(s) from directory + Database files from directory true @@ -40,7 +40,7 @@ - Selected database file(s) + Selected database files @@ -64,7 +64,7 @@ buttonBox accepted() - CreateAccountFromDb + DlgCreateAccountFromDb accept() @@ -80,7 +80,7 @@ buttonBox rejected() - CreateAccountFromDb + DlgCreateAccountFromDb reject() diff -Nru datovka-4.8.3/src/gui/ui/dlg_change_directory.ui datovka-4.9.3/src/gui/ui/dlg_change_directory.ui --- datovka-4.8.3/src/gui/ui/dlg_change_directory.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_change_directory.ui 2017-09-06 11:49:23.000000000 +0000 @@ -1,7 +1,7 @@ - ChangeDirectory - + DlgChangeDirectory + 0 @@ -11,7 +11,7 @@ - Change data directory for current account + Change data directory for current account @@ -100,7 +100,7 @@ - Cannot used the original directory as destination! + You cannot use the original directory as destination! Qt::AlignCenter @@ -181,7 +181,7 @@ buttonBox accepted() - ChangeDirectory + DlgChangeDirectory accept() @@ -197,7 +197,7 @@ buttonBox rejected() - ChangeDirectory + DlgChangeDirectory reject() diff -Nru datovka-4.8.3/src/gui/ui/dlg_contacts.ui datovka-4.9.3/src/gui/ui/dlg_contacts.ui --- datovka-4.8.3/src/gui/ui/dlg_contacts.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_contacts.ui 2017-09-06 11:49:23.000000000 +0000 @@ -28,26 +28,19 @@ - + Filter: - + Qt::ClickFocus - - - - Clear - - - diff -Nru datovka-4.8.3/src/gui/ui/dlg_ds_search.ui datovka-4.9.3/src/gui/ui/dlg_ds_search.ui --- datovka-4.8.3/src/gui/ui/dlg_ds_search.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_ds_search.ui 2017-09-06 11:49:23.000000000 +0000 @@ -1,7 +1,7 @@ - DsSearch - + DlgDsSearch + 0 @@ -229,6 +229,16 @@ + + + + Filter: + + + + + + @@ -279,7 +289,7 @@ buttonBox accepted() - DsSearch + DlgDsSearch accept() @@ -295,7 +305,7 @@ buttonBox rejected() - DsSearch + DlgDsSearch reject() diff -Nru datovka-4.8.3/src/gui/ui/dlg_login_mojeid.ui datovka-4.9.3/src/gui/ui/dlg_login_mojeid.ui --- datovka-4.8.3/src/gui/ui/dlg_login_mojeid.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_login_mojeid.ui 1970-01-01 00:00:00.000000000 +0000 @@ -1,261 +0,0 @@ - - - LoginToMojeId - - - - 0 - 0 - 413 - 322 - - - - - 0 - 0 - - - - - 16777215 - 322 - - - - Add a new mojeID account(s) - - - - :/icons/3party/plus_16.png:/icons/3party/plus_16.png - - - - - - - - - - - :/mojeid.png - - - - - - - Please select login method and enter credentials for mojeID. - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - Qt::Horizontal - - - - - - - Login method: - - - - - - - Select authorization method for login into your databox - - - - - - - Username: - - - - - - - Enter your username - - - - - - - Password: - - - - - - - Enter your password - - - QLineEdit::Password - - - - - - - Qt::Horizontal - - - - - - - Certificate file: - - - - - - - - - Select a certificate - - - Add - - - - :/icons/3party/plus_16.png:/icons/3party/plus_16.png - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Horizontal - - - - - - - - - - Security code (OTP): - - - - - - - - - Qt::Horizontal - - - - - - - Account will be included into synchronisation -process of all accounts on the background - - - Synchronise account(s) when "Synchronise all" is activated - - - true - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - accountButtonBox - accepted() - LoginToMojeId - accept() - - - 248 - 254 - - - 157 - 274 - - - - - accountButtonBox - rejected() - LoginToMojeId - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff -Nru datovka-4.8.3/src/gui/ui/dlg_proxysets.ui datovka-4.9.3/src/gui/ui/dlg_proxysets.ui --- datovka-4.8.3/src/gui/ui/dlg_proxysets.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_proxysets.ui 2017-09-06 11:49:23.000000000 +0000 @@ -42,7 +42,7 @@ 1 - The HTTPS protocol is used when accessing the Databox server while HTTP is used to download the certificate revocation list and information about new Datovka versions. + The HTTPS protocol is used when accessing the Databox server while HTTP is used to download the certificate revocation list and information about new Datovka versions. Qt::AlignCenter diff -Nru datovka-4.8.3/src/gui/ui/dlg_search_mojeid.ui datovka-4.9.3/src/gui/ui/dlg_search_mojeid.ui --- datovka-4.8.3/src/gui/ui/dlg_search_mojeid.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_search_mojeid.ui 1970-01-01 00:00:00.000000000 +0000 @@ -1,200 +0,0 @@ - - - DsSearchMojeId - - - - 0 - 0 - 514 - 365 - - - - Search recipient - - - - :/icons/3party/plus_16.png:/icons/3party/plus_16.png - - - - - - - - Current account: - - - - - - - n/a - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Horizontal - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - - - Keyword: - - - - - - - - - - - - false - - - Search - - - - :/icons/3party/search_16.png:/icons/3party/search_16.png - - - - - - - Qt::Horizontal - - - - - - - false - - - QAbstractItemView::SelectRows - - - false - - - true - - - false - - - true - - - false - - - 18 - - - false - - - 18 - - - - - - - - - ID - - - - - Name - - - - - Address - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - DsSearchMojeId - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - DsSearchMojeId - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff -Nru datovka-4.8.3/src/gui/ui/dlg_send_message.ui datovka-4.9.3/src/gui/ui/dlg_send_message.ui --- datovka-4.8.3/src/gui/ui/dlg_send_message.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_send_message.ui 2017-09-06 11:49:23.000000000 +0000 @@ -90,7 +90,7 @@ - Sender: + Sender: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter diff -Nru datovka-4.8.3/src/gui/ui/dlg_tags.ui datovka-4.9.3/src/gui/ui/dlg_tags.ui --- datovka-4.8.3/src/gui/ui/dlg_tags.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_tags.ui 2017-09-06 11:49:23.000000000 +0000 @@ -1,13 +1,13 @@ - TagsDialog - + DlgTags + 0 0 - 400 - 325 + 740 + 320 @@ -17,81 +17,109 @@ - - - QAbstractItemView::SingleSelection + + + Available Tags - - QAbstractItemView::SelectRows - - - - - - - - - Tag operations - - - Qt::AlignCenter - - + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + + - + Add - - - - - - Update + + + :/icons/3party/plus_16.png:/icons/3party/plus_16.png - + Delete - - - - - - - - - Tag assignment - - - Qt::AlignCenter - - - - - - Assign + + + :/icons/3party/delete_16.png:/icons/3party/delete_16.png - + - Remove + Update + + + + :/icons/3party/pencil_16.png:/icons/3party/pencil_16.png - - - Remove all + + + Qt::Horizontal - + + + 40 + 20 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Assign + + + + :/icons/3party/right_16.png:/icons/3party/right_16.png + + + + + + + Remove + + + + :/icons/3party/left_16.png:/icons/3party/left_16.png + @@ -109,6 +137,46 @@ + + + + Assigned Tags + + + + + + + + + + + Remove all + + + + :/icons/3party/left_16.png:/icons/3party/left_16.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + @@ -123,12 +191,14 @@ - + + + buttonBox accepted() - TagsDialog + DlgTags accept() @@ -144,7 +214,7 @@ buttonBox rejected() - TagsDialog + DlgTags reject() diff -Nru datovka-4.8.3/src/gui/ui/dlg_tag.ui datovka-4.9.3/src/gui/ui/dlg_tag.ui --- datovka-4.8.3/src/gui/ui/dlg_tag.ui 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/gui/ui/dlg_tag.ui 2017-09-06 11:49:23.000000000 +0000 @@ -1,7 +1,7 @@ - TagDialog - + DlgTag + 0 @@ -89,7 +89,7 @@ buttonBox accepted() - TagDialog + DlgTag accept() @@ -105,7 +105,7 @@ buttonBox rejected() - TagDialog + DlgTag reject() diff -Nru datovka-4.8.3/src/initialisation.cpp datovka-4.9.3/src/initialisation.cpp --- datovka-4.8.3/src/initialisation.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/initialisation.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef WIN32 +#include +#endif /* !WIN32 */ +#include +#include +#include + +#include "src/cli/cli_parser.h" +#include "src/crypto/crypto.h" +#include "src/crypto/crypto_funcs.h" +#include "src/initialisation.h" +#include "src/io/account_db.h" +#include "src/io/file_downloader.h" +#include "src/io/filesystem.h" +#include "src/io/message_db_set_container.h" +#include "src/io/records_management_db.h" +#include "src/io/tag_db.h" +#include "src/localisation/localisation.h" + +void setDefaultLocale(void) +{ +#ifndef WIN32 + QString lang(QProcessEnvironment::systemEnvironment().value("LANG")); + if (lang.isEmpty() || ("c" == lang.toLower())) { +#define LANG_DEF "en_GB.UTF-8" + logWarning("The LANG environment variable is missing or unset. " + "Setting to '%s'.\n", LANG_DEF); + if (NULL == setlocale(LC_ALL, LANG_DEF)) { + logError("Setting locale to '%s' failed.\n", LANG_DEF); + } +#undef LANG_DEF + } +#endif /* !WIN32 */ +} + +int preferencesSetUp(const QCommandLineParser &parser, + GlobPreferences &prefs, LogDevice &log) +{ + int logFileId = -1; + + if (parser.isSet(CONF_SUBDIR_OPT)) { + prefs.confSubdir = parser.value(CONF_SUBDIR_OPT); + } + if (parser.isSet(LOAD_CONF_OPT)) { + prefs.loadFromConf = parser.value(LOAD_CONF_OPT); + } + if (parser.isSet(SAVE_CONF_OPT)) { + prefs.saveToConf = parser.value(SAVE_CONF_OPT); + } + if (parser.isSet(LOG_FILE)) { + QString logFileName = parser.value(LOG_FILE); + logFileId = log.openFile(logFileName.toUtf8().constData(), + LogDevice::LM_APPEND); + if (-1 == logFileId) { + logError("Cannot open log file '%s'.\n", + logFileName.toUtf8().constData()); + return -1; + } + /* Log warnings. */ + log.setLogLevels(logFileId, LOGSRC_ANY, + LOG_UPTO(LOG_WARNING)); + } +#ifdef DEBUG + if (parser.isSet(DEBUG_OPT) || parser.isSet(DEBUG_VERBOSITY_OPT)) { + log.setLogLevels(LogDevice::LF_STDERR, LOGSRC_ANY, + LOG_UPTO(LOG_DEBUG)); + if (-1 != logFileId) { + log.setLogLevels(logFileId, LOGSRC_ANY, + LOG_UPTO(LOG_DEBUG)); + } + } + if (parser.isSet(DEBUG_VERBOSITY_OPT)) { + bool ok; + int value = parser.value(DEBUG_VERBOSITY_OPT).toInt(&ok, 10); + if (!ok) { + logError("%s\n", "Invalid debug-verbosity parameter."); + exit(EXIT_FAILURE); + } + logInfo("Setting debugging verbosity to value '%d'.\n", value); + log.setDebugVerbosity(value); + } +#endif /* DEBUG */ + if (parser.isSet(LOG_VERBOSITY_OPT)) { + bool ok; + int value = parser.value(LOG_VERBOSITY_OPT).toInt(&ok, 10); + if (!ok) { + logError("%s\n", "Invalid log-verbosity parameter."); + exit(EXIT_FAILURE); + } + logInfo("Setting logging verbosity to value '%d'.\n", value); + log.setLogVerbosity(value); + } + + return 0; +} + +void downloadCRL(void) +{ + /* Start downloading the CRL files. */ + QList urlList; + FileDownloader fDown(true); + const struct crl_location *crl = crl_locations; + const char **url; + while ((NULL != crl) && (NULL != crl->file_name)) { + urlList.clear(); + + url = crl->urls; + while ((NULL != url) && (NULL != *url)) { + urlList.append(QUrl(*url)); + ++url; + } + + QByteArray data = fDown.download(urlList, 2000); + if (!data.isEmpty()) { + if (0 != crypto_add_crl(data.data(), + data.size())) { + logWarning( + "Couldn't load downloaded CRL file '%s'.\n", + crl->file_name); + } else { + logInfo("Loaded CRL file '%s'.\n", + crl->file_name); + } + } else { + logWarning("Couldn't download CRL file '%s'.\n", + crl->file_name); + } + + ++crl; + } +} + +void loadLocalisation(const GlobPreferences &prefs) +{ + static QTranslator qtTranslator, appTranslator; + + QSettings settings(prefs.loadConfPath(), QSettings::IniFormat); + settings.setIniCodec("UTF-8"); + + const QString language( + settings.value("preferences/language").toString()); + + /* Check for application localisation location. */ + QString localisationDir; + QString localisationFile; + + localisationDir = appLocalisationDir(); + + logInfo("Loading application localisation from path '%s'.\n", + localisationDir.toUtf8().constData()); + + localisationFile = "datovka_" + Localisation::shortLangName(language); + + Localisation::setProgramLocale(language); + + if (!appTranslator.load(localisationFile, localisationDir)) { + logWarning("Could not load localisation file '%s' " + "from directory '%s'.\n", + localisationFile.toUtf8().constData(), + localisationDir.toUtf8().constData()); + } + + QCoreApplication::installTranslator(&appTranslator); + + localisationDir = qtLocalisationDir(); + + logInfo("Loading Qt localisation from path '%s'.\n", + localisationDir.toUtf8().constData()); + + { + const QString langName(Localisation::shortLangName(language)); + if (langName != Localisation::langEn) { + localisationFile = + "qtbase_" + Localisation::shortLangName(language); + } else { + localisationFile = QString(); + } + } + + if (!localisationFile.isEmpty() && + !qtTranslator.load(localisationFile, localisationDir)) { + logWarning("Could not load localisation file '%s' " + "from directory '%s'.\n", + localisationFile.toUtf8().constData(), + localisationDir.toUtf8().constData()); + } + + QCoreApplication::installTranslator(&qtTranslator); +} + +int allocateGlobalObjects(const GlobPreferences &prefs) +{ + /* + * These objects cannot be globally accessible static objects. + * The unpredictable order of constructing and destructing these + * objects causes segmentation faults upon their destruction. + * + * TODO -- Solve the problem of this globally accessible structures. + */ + + globAccountDbPtr = new (std::nothrow) AccountDb("accountDb"); + if (Q_NULLPTR == globAccountDbPtr) { + logErrorNL("%s", "Cannot allocate account db."); + goto fail; + } + /* Open accounts database. */ + if (!globAccountDbPtr->openDb(prefs.accountDbPath())) { + logErrorNL("Error opening account db '%s'.", + prefs.accountDbPath().toUtf8().constData()); + goto fail; + } + + /* Create message DB container. */ + globMessageDbsPtr = new (std::nothrow) DbContainer("GLOBALDBS"); + if (Q_NULLPTR == globMessageDbsPtr) { + logErrorNL("%s", "Cannot allocate message db container."); + goto fail; + } + + globTagDbPtr = new (std::nothrow) TagDb("tagDb"); + if (Q_NULLPTR == globTagDbPtr) { + logErrorNL("%s", "Cannot allocate tag db."); + goto fail; + } + /* Open tags database. */ + if (!globTagDbPtr->openDb(prefs.tagDbPath())) { + logErrorNL("Error opening tag db '%s'.", + prefs.tagDbPath().toUtf8().constData()); + goto fail; + } + + globRecordsManagementDbPtr = + new (std::nothrow) RecordsManagementDb("recordsManagementDb"); + if (Q_NULLPTR == globRecordsManagementDbPtr) { + logErrorNL("%s", "Cannot allocate records management db."); + goto fail; + } + /* Open records management database. */ + if (!globRecordsManagementDbPtr->openDb(prefs.recordsManagementDbPath())) { + logErrorNL("Error opening records management db '%s'.", + prefs.recordsManagementDbPath().toUtf8().constData()); + goto fail; + } + + return 0; + +fail: + deallocateGlobalObjects(); + return -1; +} + +void deallocateGlobalObjects(void) +{ + if (Q_NULLPTR != globRecordsManagementDbPtr) { + delete globRecordsManagementDbPtr; + globRecordsManagementDbPtr = Q_NULLPTR; + } + + if (Q_NULLPTR != globTagDbPtr) { + delete globTagDbPtr; + globTagDbPtr = Q_NULLPTR; + } + + if (Q_NULLPTR != globMessageDbsPtr) { + delete globMessageDbsPtr; + globMessageDbsPtr = Q_NULLPTR; + } + if (Q_NULLPTR != globAccountDbPtr) { + delete globAccountDbPtr; + globAccountDbPtr = Q_NULLPTR; + } +} diff -Nru datovka-4.8.3/src/initialisation.h datovka-4.9.3/src/initialisation.h --- datovka-4.8.3/src/initialisation.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/initialisation.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _INITIALISATION_H_ +#define _INITIALISATION_H_ + +#include + +#include "src/log/log.h" +#include "src/settings/preferences.h" + +/*! + * @brief Set default locale. + */ +void setDefaultLocale(void); + +/*! + * @brief Sets preferences and log device according to command line parameters. + * + * @param[in] parser Command line parser. + * @param[in,out] prefs Preferences structure to be set. + * @param[in,out] log Log device to be set. + * @return 0 on success, -1 on failure. + */ +int preferencesSetUp(const QCommandLineParser &parser, + GlobPreferences &prefs, LogDevice &log); + +/*! + * @brief Downloads CRL files and installs them into OpenSSL context. + */ +void downloadCRL(void); + +/*! + * @brief Loads application localisation. + * + * @param[in] prefs Preferences structure. + */ +void loadLocalisation(const GlobPreferences &prefs); + +/*! + * @brief Allocates global database objects and containers. + * + * @param[in] prefs Preferences structure. + * @return 0 on success, -1 on failure. + */ +int allocateGlobalObjects(const GlobPreferences &prefs); + +/*! + * @brief Deallocates global database objects and containers. + */ +void deallocateGlobalObjects(void); + +#endif /* _INITIALISATION_H_ */ diff -Nru datovka-4.8.3/src/io/db_tables.cpp datovka-4.9.3/src/io/db_tables.cpp --- datovka-4.8.3/src/io/db_tables.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/db_tables.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -29,6 +29,30 @@ #include "src/io/db_tables.h" +void localiseTableDescriptions(void) +{ + accntinfTbl.reloadLocalisedDescription(); + userinfTbl.reloadLocalisedDescription(); + pwdexpdtTbl.reloadLocalisedDescription(); + + msgsTbl.reloadLocalisedDescription(); + flsTbl.reloadLocalisedDescription(); + hshsTbl.reloadLocalisedDescription(); + evntsTbl.reloadLocalisedDescription(); + prcstTbl.reloadLocalisedDescription(); + rwmsgdtTbl.reloadLocalisedDescription(); + rwdlvrinfdtTbl.reloadLocalisedDescription(); + smsgdtTbl.reloadLocalisedDescription(); + crtdtTbl.reloadLocalisedDescription(); + msgcrtdtTbl.reloadLocalisedDescription(); + + tagTbl.reloadLocalisedDescription(); + msgtagsTbl.reloadLocalisedDescription(); + + srvcInfTbl.reloadLocalisedDescription(); + strdFlsMsgsTbl.reloadLocalisedDescription(); +} + namespace AccntinfTbl { const QString tabName("account_info"); @@ -680,3 +704,69 @@ SQLiteTbl msgtagsTbl(MsgTagsTbl::tabName, MsgTagsTbl::knownAttrs, MsgTagsTbl::attrProps, MsgTagsTbl::colConstraints, MsgTagsTbl::tblConstraint); + +namespace SrvcInfTbl { + const QString tabName("service_info"); + + const QVector< QPair > knownAttrs = { + {"url", DB_TEXT}, /* NOT NULL */ + {"name", DB_TEXT}, + {"token_name", DB_TEXT}, + {"logo_svg", DB_TEXT} + /* + * PRIMARY KEY (url) + */ + }; + + const QMap colConstraints = { + {"url", "NOT NULL"} + }; + + const QString tblConstraint( + ",\n" + " PRIMARY KEY (url)" + ); + + const QMap attrProps = { + {"url", {DB_TEXT, ""}}, + {"name", {DB_TEXT, ""}}, + {"token_name", {DB_TEXT, ""}}, + {"logo_svg", {DB_TEXT, ""}} + }; +} /* namespace SrvcInfTbl */ +SQLiteTbl srvcInfTbl(SrvcInfTbl::tabName, SrvcInfTbl::knownAttrs, + SrvcInfTbl::attrProps, SrvcInfTbl::colConstraints, + SrvcInfTbl::tblConstraint); + +namespace StrdFlsMsgsTbls { + const QString tabName("stored_files_messages"); + + const QVector< QPair > knownAttrs = { + {"dm_id", DB_INTEGER}, /* NOT NULL */ + {"separator", DB_TEXT}, /* NOT NULL */ + {"joined_locations", DB_TEXT} /* NOT NULL */ + /* + * PRIMARY KEY (dm_id) + */ + }; + + const QMap colConstraints = { + {"dm_id", "NOT NULL"}, + {"separator", "NOT NULL"}, + {"joined_locations", "NOT NULL"} + }; + + const QString tblConstraint( + ",\n" + " PRIMARY KEY (dm_id)" + ); + + const QMap attrProps = { + {"dm_id", {DB_INTEGER, ""}}, + {"separator", {DB_TEXT, ""}}, + {"joined_locations", {DB_TEXT, ""}} + }; +} /* namespace StrdFlsMsgsTbls */ +SQLiteTbl strdFlsMsgsTbl(StrdFlsMsgsTbls::tabName, StrdFlsMsgsTbls::knownAttrs, + StrdFlsMsgsTbls::attrProps, StrdFlsMsgsTbls::colConstraints, + StrdFlsMsgsTbls::tblConstraint); diff -Nru datovka-4.8.3/src/io/db_tables.h datovka-4.9.3/src/io/db_tables.h --- datovka-4.8.3/src/io/db_tables.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/db_tables.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,11 @@ #include "src/io/sqlite/table.h" +/*! + * @brief Localised table descriptions. + */ +void localiseTableDescriptions(void); + /* * Account database. */ @@ -53,4 +58,10 @@ extern SQLiteTbl tagTbl; /*!< Table 'tag'. */ extern SQLiteTbl msgtagsTbl; /*!< Table 'message_tags'. */ +/* + * Records management database. + */ +extern SQLiteTbl srvcInfTbl; /*!< Table 'service_info'. */ +extern SQLiteTbl strdFlsMsgsTbl; /*!< Table 'stored_files_messages'. */ + #endif /* _DB_TABLES_H_ */ diff -Nru datovka-4.8.3/src/io/exports.cpp datovka-4.9.3/src/io/exports.cpp --- datovka-4.8.3/src/io/exports.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/exports.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -304,7 +304,7 @@ // save file to disk if (printPDF(fileName, - messageDb->descriptionHtml(msgId.dmId, 0) + + messageDb->descriptionHtml(msgId.dmId) + messageDb->fileListHtmlToPdf(msgId.dmId)) && attachWriteSuccess) { errStr = QObject::tr("Export of message envelope \"%1\" to " "PDF and attachments were successful.").arg(msgID); diff -Nru datovka-4.8.3/src/io/filesystem.cpp datovka-4.9.3/src/io/filesystem.cpp --- datovka-4.8.3/src/io/filesystem.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/filesystem.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -421,6 +421,74 @@ } /*! + * @brief Return text file name. + * + * @param[in] textFile Text file identifier. + * @return Pointer to C string or NULL on error. + */ +static inline +const char *textFileName(enum TextFile textFile) +{ +#define CREDITS_FILE "AUTHORS" +#define LICENCE_FILE "COPYING" + const char *fileName = NULL; + + switch (textFile) { + case TEXT_FILE_CREDITS: + fileName = CREDITS_FILE; + break; + case TEXT_FILE_LICENCE: + fileName = LICENCE_FILE; + break; + default: + break; + } + + return fileName; +#undef CREDITS_FILE +#undef LICENCE_FILE +} + +/*! + * @brief Expands to defined text files installation location. + */ +#define instLocationUnix() \ + QString(TEXT_FILES_INST_DIR) + +/*! + * @brief Adjust text file location for OS X/macOS package. + * + * @param[in] filePath Location as defined by executable. + * @return Adjusted path. + */ +static inline +QString adjustForMacPackage(const QString &filePath) +{ + QDir directory(filePath); + if (QLatin1String("MacOS") == directory.dirName()) { + directory.cdUp(); + } + return directory.absolutePath() + QDir::separator() + + QLatin1String("Resources"); +} + +QString expectedTextFilePath(enum TextFile textFile) +{ + QString filePath; + +#if defined TEXT_FILES_INST_DIR + filePath = instLocationUnix(); +#elif defined Q_OS_OSX + filePath = QCoreApplication::applicationDirPath(); + filePath = adjustForMacPackage(filePath); +#else /* !TEXT_FILES_INST_DIR && !Q_OS_OSX */ + filePath = QCoreApplication::applicationDirPath(); +#endif /* TEXT_FILES_INST_DIR || Q_OS_OSX */ + + return filePath + QDir::separator() + textFileName(textFile); +} + +/*! * @brief Searches for the location of the supplied text file. * * @param[in] fName File name. @@ -436,7 +504,7 @@ * Search in installation location if supplied. */ - filePath = QString(TEXT_FILES_INST_DIR) + QDir::separator() + fName; + filePath = instLocationUnix() + QDir::separator() + fName; if (QFile::exists(filePath)) { return filePath; @@ -448,14 +516,7 @@ /* Search in application location. */ filePath = QCoreApplication::applicationDirPath(); #ifdef Q_OS_OSX - { - QDir directory(filePath); - if ("MacOS" == directory.dirName()) { - directory.cdUp(); - } - filePath = directory.absolutePath() + QDir::separator() + - "Resources"; - } + filePath = adjustForMacPackage(filePath); #endif /* Q_OS_OSX */ filePath += QDir::separator() + fName; @@ -470,24 +531,8 @@ QString suppliedTextFileContent(enum TextFile textFile) { -#define CREDITS_FILE "AUTHORS" -#define LICENCE_FILE "COPYING" - - const char *fileName = NULL; - QString content; - - switch (textFile) { - case TEXT_FILE_CREDITS: - fileName = CREDITS_FILE; - break; - case TEXT_FILE_LICENCE: - fileName = LICENCE_FILE; - break; - default: - fileName = NULL; - } - - if (NULL == fileName) { + const char *fileName = textFileName(textFile); + if (Q_UNLIKELY(NULL == fileName)) { Q_ASSERT(0); return QString(); } @@ -497,6 +542,8 @@ return QString(); } + QString content; + QFile file(fileLocation); QTextStream textStream(&file); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -506,8 +553,6 @@ file.close(); return content; -#undef CREDITS_FILE -#undef LICENCE_FILE } #undef LOCALE_SRC_PATH diff -Nru datovka-4.8.3/src/io/filesystem.h datovka-4.9.3/src/io/filesystem.h --- datovka-4.8.3/src/io/filesystem.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/filesystem.h 2017-09-06 11:49:23.000000000 +0000 @@ -166,7 +166,16 @@ }; /*! + * @brief Return default installation location of text file. + * + * @param[in] textFile Text file identifier. + */ +QString expectedTextFilePath(enum TextFile textFile); + +/*! * @brief Returns the content of the supplied text file. + * + * @param[in] textFile Text file identifier. */ QString suppliedTextFileContent(enum TextFile textFile); diff -Nru datovka-4.8.3/src/io/imports.cpp datovka-4.9.3/src/io/imports.cpp --- datovka-4.8.3/src/io/imports.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/imports.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -43,9 +43,8 @@ } void Imports::importZfoIntoDatabase(const QStringList &fileList, - const QList &databaseList, - enum ImportZFODialog::ZFOtype zfoType, bool authenticate, - QSet &zfoFilesToImport, + const QList &databaseList, enum Type zfoType, + bool authenticate, QSet &zfoFilesToImport, QList< QPair > &zfoFilesInvalid, int &numFilesToImport, QString &errTxt) { @@ -60,20 +59,18 @@ switch (TaskImportZfo::determineFileType(file)) { case TaskImportZfo::ZT_UKNOWN: impZFOInfo.first = file; - impZFOInfo.second = QObject::tr("Wrong ZFO format. This " - "file does not contain correct data for import."); + impZFOInfo.second = QObject::tr("Wrong ZFO format. " + "This file does not contain correct data for import."); zfoFilesInvalid.append(impZFOInfo); break; case TaskImportZfo::ZT_MESSAGE: - if ((ImportZFODialog::IMPORT_ALL_ZFO == zfoType) || - (ImportZFODialog::IMPORT_MESSAGE_ZFO == zfoType)) { + if ((IMPORT_ANY == zfoType) || (IMPORT_MESSAGE == zfoType)) { messageZfoFiles.insert(file); zfoFilesToImport.insert(file); } break; case TaskImportZfo::ZT_DELIVERY_INFO: - if ((ImportZFODialog::IMPORT_ALL_ZFO == zfoType) || - (ImportZFODialog::IMPORT_DELIVERY_ZFO == zfoType)) { + if ((IMPORT_ANY == zfoType) || (IMPORT_DELIVERY == zfoType)) { deliveryZfoFiles.insert(file); zfoFilesToImport.insert(file); } @@ -84,8 +81,8 @@ } if (messageZfoFiles.isEmpty() && deliveryZfoFiles.isEmpty()) { - errTxt = QObject::tr("The selection does not contain any " - "valid ZFO file."); + errTxt = QObject::tr( + "The selection does not contain any valid ZFO file."); return; } diff -Nru datovka-4.8.3/src/io/imports.h datovka-4.9.3/src/io/imports.h --- datovka-4.8.3/src/io/imports.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/imports.h 2017-09-06 11:49:23.000000000 +0000 @@ -24,7 +24,6 @@ #ifndef _IMPORTS_H_ #define _IMPORTS_H_ -#include "src/gui/dlg_import_zfo.h" #include "src/worker/task.h" /*! @@ -34,6 +33,15 @@ public: /*! + * @brief ZFO type. + */ + enum Type { + IMPORT_ANY, /*!< All types. */ + IMPORT_MESSAGE, /*!< Data message. */ + IMPORT_DELIVERY /*!< Delivery info. */ + }; + + /*! * @brief Import messages from external databases to local database. * * @param[in] dbSet Account target database set. @@ -61,7 +69,7 @@ static void importZfoIntoDatabase(const QStringList &fileList, const QList &databaseList, - enum ImportZFODialog::ZFOtype zfoType, bool authenticate, + enum Type zfoType, bool authenticate, QSet &zfoFilesToImport, QList< QPair > &zfoFilesInvalid, int &numFilesToImport, QString &errTxt); diff -Nru datovka-4.8.3/src/io/isds_sessions.cpp datovka-4.9.3/src/io/isds_sessions.cpp --- datovka-4.8.3/src/io/isds_sessions.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/isds_sessions.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,24 +21,21 @@ * the two. */ - #include /* malloc(3) */ #include /* memset(3) */ #include #include #include -#include "isds_sessions.h" #include "src/common.h" -#include "src/gui/dlg_import_zfo.h" +#include "src/io/imports.h" +#include "src/io/isds_sessions.h" #include "src/log/log.h" #include "src/models/accounts_model.h" #include "src/settings/preferences.h" - IsdsSessions globIsdsSessions; - /* ========================================================================= */ /*! * @brief Logging facility name. @@ -954,7 +951,7 @@ goto fail; } - if (zfoType == ImportZFODialog::IMPORT_MESSAGE_ZFO) { + if (zfoType == Imports::IMPORT_MESSAGE) { status = isds_load_message(isdsSession, raw_type, rawMsgData.data(), rawMsgData.size(), &message, BUFFER_COPY); diff -Nru datovka-4.8.3/src/io/isds_sessions.h datovka-4.9.3/src/io/isds_sessions.h --- datovka-4.8.3/src/io/isds_sessions.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/isds_sessions.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,6 @@ * the two. */ - #ifndef _ISDS_SESSIONS_H_ #define _ISDS_SESSIONS_H_ @@ -44,7 +43,6 @@ class IsdsSessions; extern IsdsSessions globIsdsSessions; - /*! * @brief Holds the ISDS context structures. */ @@ -90,21 +88,18 @@ QMap m_sessions; }; - /*! * @brief Log in using user name and password. */ isds_error isdsLoginUserName(struct isds_ctx *isdsSession, const QString &userName, const QString &pwd, bool testingSession); - /*! * @brief Log in using system certificate. */ isds_error isdsLoginSystemCert(struct isds_ctx *isdsSession, const QString &certPath, const QString &passphrase, bool testingSession); - /*! * @brief Log in using user certificate without password. * NOTE: It need ID of Databox instead username @@ -113,7 +108,6 @@ const QString &idBox, const QString &certPath, const QString &passphrase, bool testingSession); - /*! * @brief Log in using user certificate with password. */ @@ -121,7 +115,6 @@ const QString &userName, const QString &pwd, const QString &certPath, const QString &passphrase, bool testingSession); - /*! * @brief Log in using username, pwd and OTP. */ @@ -160,7 +153,6 @@ struct isds_BirthInfo * isds_BirthInfo_createConsume(struct tm *biDate, const QString &biCity, const QString &biCountry, const QString &biState); - /*! * @brief Create new isds_DbOwnerInfo structure according to the supplied * values. @@ -178,7 +170,6 @@ const QString &identifier, const QString ®istryCode, long int dbState, bool dbEffectiveOVM, bool dbOpenAddressing); - /*! * @brief Create DbUserInfo structure. * @@ -198,8 +189,7 @@ * * @param[in,out] isdsSession Pointer to session context. * @param[in] rawMsgData Raw message data. - * @param[in] zfoType Message or delivery info - * (enum ImportZFODialog::ZFOtype). + * @param[in] zfoType Message or delivery info (enum Imports::Type). * @return Pointer to newly allocated message, NULL on error. Use * isds_message_free() to delete. */ diff -Nru datovka-4.8.3/src/io/message_db.cpp datovka-4.9.3/src/io/message_db.cpp --- datovka-4.8.3/src/io/message_db.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/message_db.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -22,7 +22,6 @@ */ #include -#include #include #include #include @@ -47,10 +46,11 @@ #include #include -#include "message_db.h" #include "src/crypto/crypto_funcs.h" #include "src/io/db_tables.h" #include "src/io/dbs.h" +#include "src/io/message_db.h" +#include "src/isds/isds_conversion.h" #include "src/log/log.h" #include "src/settings/preferences.h" @@ -70,34 +70,48 @@ const QVector MessageDb::msgStatus = {"dmDeliveryTime", "dmAcceptanceTime", "dmMessageStatus"}; +const QVector MessageDb::rcvdItemIds = {"dmID", "dmAnnotation", + "dmSender", "dmDeliveryTime", "dmAcceptanceTime", "read_locally", + "is_downloaded", "process_status"}; + +const QVector MessageDb::sntItemIds = {"dmID", "dmAnnotation", + "dmRecipient", "dmDeliveryTime", "dmAcceptanceTime", "dmMessageStatus", + "is_downloaded"}; + const QVector MessageDb::fileItemIds = {"id", "message_id", "dmEncodedContent", "_dmFileDescr", "_dmMimeType", "LENGTH(dmEncodedContent)"}; MessageDb::MessageDb(const QString &connectionName) - : SQLiteDb(connectionName), - m_sqlMsgsModel(), - m_sqlFilesModel() + : SQLiteDb(connectionName) { } -/* ========================================================================= */ -/* - * Return all received messages model. - */ -QAbstractTableModel *MessageDb::msgsRcvdModel(const QStringList &appendedCols) -/* ========================================================================= */ +void MessageDb::appendRcvdEntryList(QList &entryList, + QSqlQuery &query) +{ + query.first(); + while (query.isActive() && query.isValid()) { + entryList.append(MessageDb::RcvdEntry( + query.value(0).toLongLong(), query.value(1).toString(), + query.value(2).toString(), query.value(3).toString(), + query.value(4).toString(), query.value(5).toBool(), + query.value(6).toBool(), query.value(7).toInt())); + + query.next(); + } +} + +QList MessageDb::msgsRcvdEntries(void) const { + QList entryList; QSqlQuery query(m_db); QString queryStr = "SELECT "; - for (int i = 0; i < (DbMsgsTblModel::rcvdItemIds().size() - 2); ++i) { - queryStr += DbMsgsTblModel::rcvdItemIds()[i] + ", "; + for (int i = 0; i < (rcvdItemIds.size() - 2); ++i) { + queryStr += rcvdItemIds[i] + ", "; } queryStr += "(ifnull(r.message_id, 0) != 0) AS is_downloaded" ", " "ifnull(p.state, 0) AS process_status"; - for (int i = 0; i < appendedCols.size(); ++i) { - queryStr += ", null"; - } queryStr += " FROM messages AS m " "LEFT JOIN supplementary_message_data AS s " "ON (m.dmID = s.message_id) " @@ -119,62 +133,42 @@ goto fail; } - m_sqlMsgsModel.setQuery(query, DbMsgsTblModel::WORKING_RCVD); - if (!m_sqlMsgsModel.setRcvdHeader(appendedCols)) { - Q_ASSERT(0); - goto fail; - } - return &m_sqlMsgsModel; + appendRcvdEntryList(entryList, query); + + return entryList; fail: - return 0; + return QList(); } - -/* ========================================================================= */ -/* - * Return received messages within past 90 days. - */ -QAbstractTableModel *MessageDb::msgsRcvdWithin90DaysModel( - const QStringList &appendedCols) -/* ========================================================================= */ +QList MessageDb::msgsRcvdEntriesWithin90Days(void) const { + QList entryList; QSqlQuery query(m_db); - if (!msgsRcvdWithin90DaysQuery(query, appendedCols)) { + if (!msgsRcvdWithin90DaysQuery(query)) { goto fail; } - m_sqlMsgsModel.setQuery(query, DbMsgsTblModel::WORKING_RCVD); - if (!m_sqlMsgsModel.setRcvdHeader(appendedCols)) { - Q_ASSERT(0); - goto fail; - } - return &m_sqlMsgsModel; + appendRcvdEntryList(entryList, query); + + return entryList; fail: - return 0; + return QList(); } - -/* ========================================================================= */ -/* - * Return received messages within given year. - */ -QAbstractTableModel *MessageDb::msgsRcvdInYearModel(const QString &year, - const QStringList &appendedCols) -/* ========================================================================= */ +QList MessageDb::msgsRcvdEntriesInYear( + const QString &year) const { + QList entryList; QSqlQuery query(m_db); QString queryStr = "SELECT "; - for (int i = 0; i < (DbMsgsTblModel::rcvdItemIds().size() - 2); ++i) { - queryStr += DbMsgsTblModel::rcvdItemIds()[i] + ", "; + for (int i = 0; i < (rcvdItemIds.size() - 2); ++i) { + queryStr += rcvdItemIds[i] + ", "; } queryStr += "(ifnull(r.message_id, 0) != 0) AS is_downloaded" ", " "ifnull(p.state, 0) AS process_status"; - for (int i = 0; i < appendedCols.size(); ++i) { - queryStr += ", null"; - } queryStr += " FROM messages AS m " "LEFT JOIN supplementary_message_data AS s " "ON (m.dmID = s.message_id) " @@ -199,18 +193,14 @@ goto fail; } - m_sqlMsgsModel.setQuery(query, DbMsgsTblModel::WORKING_RCVD); - if (!m_sqlMsgsModel.setRcvdHeader(appendedCols)) { - Q_ASSERT(0); - goto fail; - } - return &m_sqlMsgsModel; + appendRcvdEntryList(entryList, query); + + return entryList; fail: - return 0; + return QList(); } - /* ========================================================================= */ /* * Return list of years (strings) in database. @@ -397,23 +387,28 @@ return -1; } +void MessageDb::appendSntEntryList(QList &entryList, QSqlQuery &query) +{ + query.first(); + while (query.isActive() && query.isValid()) { + entryList.append(SntEntry(query.value(0).toLongLong(), + query.value(1).toString(), query.value(2).toString(), + query.value(3).toString(), query.value(4).toString(), + query.value(5).toInt(), query.value(6).toBool())); -/* ========================================================================= */ -/* - * Return all sent messages model. - */ -QAbstractTableModel * MessageDb::msgsSntModel(const QStringList &appendedCols) -/* ========================================================================= */ + query.next(); + } +} + +QList MessageDb::msgsSntEntries(void) const { + QList entryList; QSqlQuery query(m_db); QString queryStr = "SELECT "; - for (int i = 0; i < (DbMsgsTblModel::sntItemIds().size() - 1); ++i) { - queryStr += DbMsgsTblModel::sntItemIds()[i] + ", "; + for (int i = 0; i < (sntItemIds.size() - 1); ++i) { + queryStr += sntItemIds[i] + ", "; } queryStr += "(ifnull(r.message_id, 0) != 0) AS is_downloaded"; - for (int i = 0; i < appendedCols.size(); ++i) { - queryStr += ", null"; - } queryStr += " FROM messages AS m " "LEFT JOIN supplementary_message_data AS s " "ON (m.dmID = s.message_id) " @@ -433,61 +428,41 @@ goto fail; } - m_sqlMsgsModel.setQuery(query, DbMsgsTblModel::WORKING_SNT); - if (!m_sqlMsgsModel.setSntHeader(appendedCols)) { - Q_ASSERT(0); - goto fail; - } - return &m_sqlMsgsModel; + appendSntEntryList(entryList, query); + + return entryList; fail: - return 0; + return QList(); } - -/* ========================================================================= */ -/* - * Return sent messages within past 90 days. - */ -QAbstractTableModel * MessageDb::msgsSntWithin90DaysModel( - const QStringList &appendedCols) -/* ========================================================================= */ +QList MessageDb::msgsSntEntriesWithin90Days(void) const { + QList entryList; QSqlQuery query(m_db); - if (!msgsSntWithin90DaysQuery(query, appendedCols)) { + if (!msgsSntWithin90DaysQuery(query)) { goto fail; } - m_sqlMsgsModel.setQuery(query, DbMsgsTblModel::WORKING_SNT); - if (!m_sqlMsgsModel.setSntHeader(appendedCols)) { - Q_ASSERT(0); - goto fail; - } - return &m_sqlMsgsModel; + appendSntEntryList(entryList, query); + + return entryList; fail: - return 0; + return QList(); } - -/* ========================================================================= */ -/* - * Return sent messages within given year. - */ -QAbstractTableModel * MessageDb::msgsSntInYearModel(const QString &year, - const QStringList &appendedCols) -/* ========================================================================= */ +QList MessageDb::msgsSntEntriesInYear( + const QString &year) const { + QList entryList; QSqlQuery query(m_db); QString queryStr = "SELECT "; - for (int i = 0; i < (DbMsgsTblModel::sntItemIds().size() - 1); ++i) { - queryStr += DbMsgsTblModel::sntItemIds()[i] + ", "; + for (int i = 0; i < (sntItemIds.size() - 1); ++i) { + queryStr += sntItemIds[i] + ", "; } queryStr += "(ifnull(r.message_id, 0) != 0) AS is_downloaded"; - for (int i = 0; i < appendedCols.size(); ++i) { - queryStr += ", null"; - } queryStr += " FROM messages AS m " "LEFT JOIN supplementary_message_data AS s " "ON (m.dmID = s.message_id) " @@ -510,18 +485,14 @@ goto fail; } - m_sqlMsgsModel.setQuery(query, DbMsgsTblModel::WORKING_SNT); - if (!m_sqlMsgsModel.setSntHeader(appendedCols)) { - Q_ASSERT(0); - goto fail; - } - return &m_sqlMsgsModel; + appendSntEntryList(entryList, query); + + return entryList; fail: - return 0; + return QList(); } - /* ========================================================================= */ /* * Get message information for reply/template send message dialog. @@ -911,7 +882,6 @@ /* ========================================================================= */ { QMap mapOfBoxes; - QMap::iterator it; QList contactList; QSqlQuery query(m_db); @@ -973,14 +943,8 @@ return contactList; } - -/* ========================================================================= */ -/* - * Return HTML formatted message description. - */ -QString MessageDb::descriptionHtml(qint64 dmId, QAbstractButton *verSigButton, - bool showId, bool verSignature, bool warnOld) const -/* ========================================================================= */ +QString MessageDb::descriptionHtml(qint64 dmId, bool showId, bool verSignature, + bool warnOld) const { QString html; QSqlQuery query(m_db); @@ -1009,9 +973,9 @@ html += strongAccountInfoLine(QObject::tr("Subject"), query.value(0).toString()); if (!query.value(1).toString().isEmpty() && - (!dmTypeToText(query.value(1).toString()).isEmpty())) { + (!IsdsConversion::dmTypeToText(query.value(1).toString()).isEmpty())) { html += strongAccountInfoLine(QObject::tr("Message type"), - dmTypeToText(query.value(1).toString())); + IsdsConversion::dmTypeToText(query.value(1).toString())); } html += "
    "; @@ -1024,7 +988,7 @@ query.value(6).toString()); QString dmSenderType = - convertSenderDbTypesToString(query.value(8).toInt()); + IsdsConversion::senderBoxTypeToText(query.value(8).toInt()); if (dmSenderType != "") { html += strongAccountInfoLine( QObject::tr("Databox type"), dmSenderType); @@ -1046,8 +1010,8 @@ html += strongAccountInfoLine( QObject::tr("Message author"), authorInfo + - authorTypeToText(value.toObject().value( - "userType").toString())); + IsdsConversion::senderTypeStrToText( + value.toObject().value("userType").toString())); } } @@ -1153,7 +1117,7 @@ html += strongAccountInfoLine( msgsTbl.attrProps[msgStatus[2]].desc, QString::number(query.value(2).toInt()) + " -- " + - msgStatusToText(query.value(2).toInt())); + IsdsConversion::msgStatusDbToText(query.value(2).toInt())); } else { logErrorNL( "Cannot execute SQL query and/or read SQL data: %s.", @@ -1176,7 +1140,7 @@ query.first(); if (query.isValid()) { html += strongAccountInfoLine(QObject::tr("Events"), - ""); + QString()); } while (query.isValid()) { html += indentDivStart + @@ -1243,11 +1207,6 @@ /* TODO */ } - /* Disable verify signature button. It is re-enabled when needed. */ - if (0 != verSigButton) { - verSigButton->setEnabled(false); - } - if (verSignature) { html += "

    " + QObject::tr("Signature") + "

    "; @@ -1257,10 +1216,6 @@ html += strongAccountInfoLine( QObject::tr("Message signature"), QObject::tr("Not present")); - /* Enable verification button. */ - if (0 != verSigButton) { - verSigButton->setEnabled(true); - } html += "
    " + QObject::tr("Download the complete message in order to verify its signature.") + "
    "; @@ -1808,14 +1763,9 @@ return QList(); } - -/* ========================================================================= */ -/* - * Return files related to given message. - */ -QAbstractTableModel * MessageDb::flsModel(qint64 msgId) -/* ========================================================================= */ +QList MessageDb::attachEntries(qint64 msgId) const { + QList entryList; int i; QSqlQuery query(m_db); QString queryStr = "SELECT "; @@ -1839,16 +1789,22 @@ /* First three columns ought to be hidden. */ - m_sqlFilesModel.setQuery(query); - m_sqlFilesModel.setHeader(); + query.first(); + while (query.isActive() && query.isValid()) { + entryList.append(AttachmentEntry(query.value(0).toLongLong(), + query.value(1).toLongLong(), query.value(2).toByteArray(), + query.value(3).toString(), query.value(4).toString(), + query.value(5).toInt())); + + query.next(); + } - return &m_sqlFilesModel; + return entryList; fail: - return 0; + return QList(); } - /* ========================================================================= */ /* * Check if any message (dmID) exists in the table @@ -3189,20 +3145,14 @@ return QByteArray(); } - -/* ========================================================================= */ -/* - * Return all message ID from database without attachment. - */ -QStringList MessageDb::getAllMessageIDsWithoutAttach(void) const -/* ========================================================================= */ +QList MessageDb::getAllMessageIDsWithoutAttach(void) const { QSqlQuery query(m_db); QString queryStr = "SELECT dmID FROM messages AS m " "LEFT JOIN raw_message_data AS r ON (m.dmID = r.message_id) " "WHERE r.message_id IS null"; - QStringList msgIsList; + QList msgIdList; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", @@ -3213,26 +3163,23 @@ if (query.exec() && query.isActive()) { query.first(); while (query.isValid()) { - msgIsList.append(query.value(0).toString()); + msgIdList.append(query.value(0).toLongLong()); query.next(); } } - return msgIsList; + return msgIdList; fail: - return QStringList(); + return QList(); } - -/* ========================================================================= */ -/* - * Return all message ID from database. - */ -QList MessageDb::getAllMessageIDsFromDB(void) const -/* ========================================================================= */ +QList MessageDb::getAllMessageIDs(enum MessageType messageType) const { QSqlQuery query(m_db); - QString queryStr = "SELECT dmID, dmDeliveryTime FROM messages"; - QList msgIdList; + QList msgIdList; + QString queryStr = "SELECT dmID FROM messages AS m " + "LEFT JOIN supplementary_message_data AS s " + "ON (m.dmID = s.message_id) " + "WHERE s.message_type = :message_type"; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", @@ -3240,33 +3187,30 @@ goto fail; } + query.bindValue(":message_type", messageType); + if (query.exec() && query.isActive()) { query.first(); while (query.isValid()) { - msgIdList.append(MessageDb::MsgId( - query.value(0).toLongLong(), - dateTimeFromDbFormat( - query.value(1).toString()))); + msgIdList.append(query.value(0).toLongLong()); query.next(); } } return msgIdList; fail: - return QList(); + return QList(); } - /* ========================================================================= */ /* - * Get all unique years from messages db. + * Return all message ID from database. */ -QStringList MessageDb::getAllUniqueYearsFormMsgs(void) const +QList MessageDb::getAllMessageIDsFromDB(void) const /* ========================================================================= */ { QSqlQuery query(m_db); - QString queryStr = "SELECT DISTINCT strftime('%Y', dmDeliveryTime) " - "FROM messages"; - QStringList yearIsList; + QString queryStr = "SELECT dmID, dmDeliveryTime FROM messages"; + QList msgIdList; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", @@ -3277,28 +3221,23 @@ if (query.exec() && query.isActive()) { query.first(); while (query.isValid()) { - if (!query.value(0).toString().isEmpty()) { - yearIsList.append(query.value(0).toString()); - } + msgIdList.append(MessageDb::MsgId( + query.value(0).toLongLong(), + dateTimeFromDbFormat( + query.value(1).toString()))); query.next(); } } - return yearIsList; + return msgIdList; fail: - return QStringList(); + return QList(); } - -/* ========================================================================= */ -/* - * Get list of all messages ID correspond with year. - */ -QStringList MessageDb::getAllMsgsIDEqualWithYear(const QString &year) const -/* ========================================================================= */ +QList MessageDb::getAllMsgsIDEqualWithYear(const QString &year) const { QSqlQuery query(m_db); - QStringList msgList; - QString queryStr; + QList msgList; + QString queryStr; if (year == "inv") { queryStr = "SELECT dmID FROM messages WHERE " @@ -3318,17 +3257,16 @@ query.first(); while (query.isValid()) { if (!query.value(0).toString().isEmpty()) { - msgList.append(query.value(0).toString()); + msgList.append(query.value(0).toLongLong()); } query.next(); } } return msgList; fail: - return QStringList(); + return QList(); } - /* ========================================================================= */ /* * Copy all messages correspond with year and their records @@ -3343,7 +3281,7 @@ bool transaction = false; QString queryStr; - QStringList idList = getAllMsgsIDEqualWithYear(year); + QList idList(getAllMsgsIDEqualWithYear(year)); attached = attachDb2(query, newDbFileName); if (!attached) { @@ -3375,15 +3313,16 @@ } // copy other message data from other tables into new db. - for (int i = 0; i < idList.count(); ++i) { + foreach (qint64 dmId, idList) { queryStr = "INSERT INTO " DB2 ".files SELECT * FROM files WHERE " - "message_id = '"+ idList.at(i) + "'"; + "message_id = :message_id"; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", query.lastError().text().toUtf8().constData()); goto fail; } + query.bindValue(":message_id", dmId); if (!query.exec()) { logErrorNL("Cannot execute SQL query: %s.", query.lastError().text().toUtf8().constData()); @@ -3391,12 +3330,13 @@ } queryStr = "INSERT INTO " DB2 ".hashes SELECT * FROM hashes WHERE " - "message_id = '"+ idList.at(i) + "'"; + "message_id = :message_id"; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", query.lastError().text().toUtf8().constData()); goto fail; } + query.bindValue(":message_id", dmId); if (!query.exec()) { logErrorNL("Cannot execute SQL query: %s.", query.lastError().text().toUtf8().constData()); @@ -3404,12 +3344,13 @@ } queryStr = "INSERT INTO " DB2 ".events SELECT * FROM events WHERE " - "message_id = '"+ idList.at(i) + "'"; + "message_id = :message_id"; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", query.lastError().text().toUtf8().constData()); goto fail; } + query.bindValue(":message_id", dmId); if (!query.exec()) { logErrorNL("Cannot execute SQL query: %s.", query.lastError().text().toUtf8().constData()); @@ -3417,13 +3358,13 @@ } queryStr = "INSERT INTO " DB2 ".raw_message_data SELECT * " - "FROM raw_message_data WHERE message_id = " - "'"+ idList.at(i) + "'"; + "FROM raw_message_data WHERE message_id = :message_id"; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", query.lastError().text().toUtf8().constData()); goto fail; } + query.bindValue(":message_id", dmId); if (!query.exec()) { logErrorNL("Cannot execute SQL query: %s.", query.lastError().text().toUtf8().constData()); @@ -3431,13 +3372,13 @@ } queryStr = "INSERT INTO " DB2 ".raw_delivery_info_data SELECT * " - "FROM raw_delivery_info_data WHERE message_id = " - "'"+ idList.at(i) + "'"; + "FROM raw_delivery_info_data WHERE message_id = :message_id"; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", query.lastError().text().toUtf8().constData()); goto fail; } + query.bindValue(":message_id", dmId); if (!query.exec()) { logErrorNL("Cannot execute SQL query: %s.", query.lastError().text().toUtf8().constData()); @@ -3446,12 +3387,13 @@ queryStr = "INSERT INTO " DB2 ".supplementary_message_data " "SELECT * FROM supplementary_message_data WHERE " - "message_id = '"+ idList.at(i) + "'"; + "message_id = :message_id"; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", query.lastError().text().toUtf8().constData()); goto fail; } + query.bindValue(":message_id", dmId); if (!query.exec()) { logErrorNL("Cannot execute SQL query: %s.", query.lastError().text().toUtf8().constData()); @@ -3459,12 +3401,13 @@ } queryStr = "INSERT INTO " DB2 ".process_state SELECT * FROM " - "process_state WHERE message_id = '"+ idList.at(i) + "'"; + "process_state WHERE message_id = :message_id"; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", query.lastError().text().toUtf8().constData()); goto fail; } + query.bindValue(":message_id", dmId); if (!query.exec()) { logErrorNL("Cannot execute SQL query: %s.", query.lastError().text().toUtf8().constData()); @@ -3486,12 +3429,13 @@ queryStr = "INSERT INTO " DB2 ".message_certificate_data SELECT * " "FROM message_certificate_data WHERE " - "message_id = '"+ idList.at(i) + "'"; + "message_id = :message_id"; if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", query.lastError().text().toUtf8().constData()); goto fail; } + query.bindValue(":message_id", dmId); if (!query.exec()) { logErrorNL("Cannot execute SQL query: %s.", query.lastError().text().toUtf8().constData()); @@ -3514,34 +3458,6 @@ return false; } - -/* ========================================================================= */ -/* - * Get id of message in webdatovka db form ISDS msgId. - */ -int MessageDb::getWebDatokaId(qint64 msgId) -/* ========================================================================= */ -{ - QSqlQuery query(m_db); - QString queryStr = "SELECT _origin FROM messages WHERE dmID = :dmId"; - if (!query.prepare(queryStr)) { - logErrorNL("Cannot prepare SQL query: %s.", - query.lastError().text().toUtf8().constData()); - return -1; - } - query.bindValue(":dmId", msgId); - if (query.exec() && query.isActive() && - query.first() && query.isValid()) { - return query.value(0).toInt(); - } else { - logErrorNL( - "Cannot execute SQL query and/or read SQL data: %s.", - query.lastError().text().toUtf8().constData()); - return -1; - } -} - - /* ========================================================================= */ /* * Insert raw (DER) delivery info into raw_delivery_info_data table. @@ -4540,18 +4456,14 @@ return reopen_ret; } -bool MessageDb::msgsRcvdWithin90DaysQuery(QSqlQuery &query, - const QStringList &appendedCols) +bool MessageDb::msgsRcvdWithin90DaysQuery(QSqlQuery &query) { QString queryStr = "SELECT "; - for (int i = 0; i < (DbMsgsTblModel::rcvdItemIds().size() - 2); ++i) { - queryStr += DbMsgsTblModel::rcvdItemIds()[i] + ", "; + for (int i = 0; i < (rcvdItemIds.size() - 2); ++i) { + queryStr += rcvdItemIds[i] + ", "; } queryStr += "(ifnull(r.message_id, 0) != 0) AS is_downloaded" ", " "ifnull(p.state, 0) AS process_status"; - for (int i = 0; i < appendedCols.size(); ++i) { - queryStr += ", null"; - } queryStr += " FROM messages AS m " "LEFT JOIN supplementary_message_data AS s " "ON (m.dmID = s.message_id) " @@ -4581,17 +4493,13 @@ return false; } -bool MessageDb::msgsSntWithin90DaysQuery(QSqlQuery &query, - const QStringList &appendedCols) +bool MessageDb::msgsSntWithin90DaysQuery(QSqlQuery &query) { QString queryStr = "SELECT "; - for (int i = 0; i < (DbMsgsTblModel::sntItemIds().size() - 1); ++i) { - queryStr += DbMsgsTblModel::sntItemIds()[i] + ", "; + for (int i = 0; i < (sntItemIds.size() - 1); ++i) { + queryStr += sntItemIds[i] + ", "; } queryStr += "(ifnull(r.message_id, 0) != 0) AS is_downloaded"; - for (int i = 0; i < appendedCols.size(); ++i) { - queryStr += ", null"; - } queryStr += " FROM messages AS m " "LEFT JOIN supplementary_message_data AS s " "ON (m.dmID = s.message_id) " diff -Nru datovka-4.8.3/src/io/message_db.h datovka-4.9.3/src/io/message_db.h --- datovka-4.8.3/src/io/message_db.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/message_db.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,13 +21,9 @@ * the two. */ - #ifndef _MESSAGE_DB_H_ #define _MESSAGE_DB_H_ - -#include -#include #include #include #include @@ -37,9 +33,8 @@ #include #include +#include "src/common.h" #include "src/io/sqlite/db.h" -#include "src/models/files_model.h" -#include "src/models/messages_model.h" #define INVALID_YEAR "inv" #define DB2 "db2" @@ -50,7 +45,6 @@ DESCENDING }; - /*! * @brief Encapsulates message database. */ @@ -181,6 +175,50 @@ }; /*! + * @brief Received entries. + */ + class RcvdEntry { + public: + qint64 dmId; /*!< Message identifier. */ + QString dmAnnotation; /*!< Message annotation. */ + QString dmSender; /*!< Message sender. */ + QString dmDeliveryTime; /*!< Delivery time as stored in the database. */ + QString dmAcceptanceTime; /*!< Acceptance time as stored in the database. */ + bool readLocally; /*!< True if locally read. */ + bool isDownloaded; /*!< True if complete message has been downloaded. */ + int processStatus; /*!< Brief processing status. */ + + RcvdEntry(qint64 i, const QString &a, const QString &s, + const QString &dt, const QString &at, bool rl, bool id, + int ps) + : dmId(i), dmAnnotation(a), dmSender(s), dmDeliveryTime(dt), + dmAcceptanceTime(at), readLocally(rl), isDownloaded(id), + processStatus(ps) + { } + }; + + /*! + * @brief Sent entries. + */ + class SntEntry { + public: + qint64 dmId; /*!< Message identifier. */ + QString dmAnnotation; /*!< Message annotation. */ + QString dmRecipient; /*!< Message recipient. */ + QString dmDeliveryTime; /*!< Delivery time as stored in the database. */ + QString dmAcceptanceTime; /*!< Acceptance time as stored in the database. */ + int dmMessageStatus; /*!< Brief message status. */ + bool isDownloaded; /*!< True if complete message has been downloaded. */ + + SntEntry(qint64 i, const QString &a, const QString &r, + const QString &dt, const QString &at, int ms, bool id) + : dmId(i), dmAnnotation(a), dmRecipient(r), + dmDeliveryTime(dt), dmAcceptanceTime(at), + dmMessageStatus(ms), isDownloaded(id) + { } + }; + + /*! * @brief File entry data. */ class FileData { @@ -205,6 +243,35 @@ } }; + /*! + * @brief Attachment data used to fill attachment model. + */ + class AttachmentEntry { + public: + qint64 id; /*!< Entry identifier. */ + qint64 messageId; /*!< Identifier of the message which the attachment belong to. */ + QByteArray dmEncodedContent; /*!< Base64-encoded file content. */ + QString dmFileDescr; /*!< Attachment file name. */ + QString dmMimeType; /*!< String holding the mime type. */ + int size; /*!< Attachment file size (base64-decoded). */ + + AttachmentEntry(void) + : id(0), messageId(0), dmEncodedContent(), dmFileDescr(), + dmMimeType(), size(0) + { } + AttachmentEntry(qint64 i, qint64 mi, const QByteArray &dec, + const QString &dfd, const QString &dmt, int s) + : id(i), messageId(mi), dmEncodedContent(dec), + dmFileDescr(dfd), dmMimeType(dmt), size(s) + { } + + bool isValid(void) const + { + return (!dmFileDescr.isEmpty()) && + (!dmEncodedContent.isEmpty()); + } + }; + class PartialEnvelopeData { public: QString dbIDSender; @@ -330,18 +397,15 @@ /*! * @brief Return HTML formatted message description. * - * @param[in] dmId Message identifier. - * @param[in,out] verSigButton Button to activate/deactivate - * according to message content. - * @param[in] showId Whether to also show the message id. - * @param[in] verSignature Whether to show verification details. + * @param[in] dmId Message identifier. + * @param[in] showId Whether to also show the message id. + * @param[in] verSignature Whether to show verification details. * @param[in] warnOld * @return HTML formatted string containing message information. * Empty string is returned on error. */ - QString descriptionHtml(qint64 dmId, QAbstractButton *verSigButton, - bool showId = true, bool verSignature = true, - bool warnOld = true) const; + QString descriptionHtml(qint64 dmId, bool showId = true, + bool verSignature = true, bool warnOld = true) const; /*! * @brief Return message envelope HTML to be used to generate a PDF. @@ -382,14 +446,12 @@ QList getFilesFromMessage(qint64 msgId) const; /*! - * @brief Return files related to given message. + * @brief Return list of attachment entries related to given message. * * @param[in] msgId Message identifier. - * @return Pointer to model, 0 on failure. - * - * @note The model must not be freed. + * @return List of attachment entries. */ - QAbstractTableModel * flsModel(qint64 msgId); + QList attachEntries(qint64 msgId) const; /*! * @brief Check if any message with given id exists in database. @@ -552,11 +614,19 @@ int messageType); /*! - * @brief Return all message ID from database without attachment. + * @brief Return all IDs of messages without attachment. * - * @return message id list. + * @return Message identifier list. + */ + QList getAllMessageIDsWithoutAttach(void) const; + + /*! + * @brief Return all message IDs from database. + * + * @param[in] messageType Specifies sent or received messages. + * @return Message identifier list. */ - QStringList getAllMessageIDsWithoutAttach(void) const; + QList getAllMessageIDs(enum MessageType messageType) const; /*! * @brief Check whether whole message is stored in database. @@ -714,47 +784,37 @@ bool copyRelevantMsgsToNewDb(const QString &newDbFileName, const QString &year); +protected: /* These function are used from within a database container. */ /*! - * @brief Get id of message in webdatovka db form ISDS msgId. + * @brief Appends to received entry list data received from SQL query. * - * @param[in] msgId Message identifier. - * @return Internal id of message in webdatovka db. + * @param[in,out] entryList List to add entries to. + * @param[in] query Query to read data from. */ - int getWebDatokaId(qint64 msgId); + static + void appendRcvdEntryList(QList &entryList, QSqlQuery &query); -protected: /* These function are used from within a database container. */ /*! - * @brief Return all received messages model. + * @brief Return entries for all received messages. * - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. - * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsRcvdModel(const QStringList &appendedCols); + QList msgsRcvdEntries(void) const; /*! - * @brief Return received messages within past 90 days. - * - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. + * @brief Return entries for received messages within past 90 days. * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsRcvdWithin90DaysModel( - const QStringList &appendedCols); + QList msgsRcvdEntriesWithin90Days(void) const; /*! - * @brief Return received messages within given year. + * @brief Return entries for received messages within given year. * * @param[in] year Year number. - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. - * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsRcvdInYearModel(const QString &year, - const QStringList &appendedCols); + QList msgsRcvdEntriesInYear(const QString &year) const; /*! * @brief Return list of years (strings) in database. @@ -796,37 +856,35 @@ const QString &year) const; /*! - * @brief Return all sent messages model. - * - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. + * @brief Appends to sent entry list data received from SQL query. * - * @note The model must not be freed. + * @param[in,out] entryList List to add entries to. + * @param[in] query Query to read data from. */ - QAbstractTableModel *msgsSntModel(const QStringList &appendedCols); + static + void appendSntEntryList(QList &entryList, QSqlQuery &query); /*! - * @brief Return sent messages within past 90 days. + * @brief Return entries for all sent messages. * - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. + * @return List of entries, empty list on failure. + */ + QList msgsSntEntries(void) const; + + /*! + * @brief Return entries for all sent messages within past 90 days. * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsSntWithin90DaysModel( - const QStringList &appendedCols); + QList msgsSntEntriesWithin90Days(void) const; /*! - * @brief Return sent messages within given year. + * @brief Return entries for sent messages within given year. * * @param[in] year Year number. - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. - * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsSntInYearModel(const QString &year, - const QStringList &appendedCols); + QList msgsSntEntriesInYear(const QString &year) const; /*! * @brief Set message read locally for all received messages. @@ -907,24 +965,11 @@ QList getAllMessageIDsFromDB(void) const; /*! - * @brief Get all unique years from messages db. - * - * @return Return unique year list. - */ - QStringList getAllUniqueYearsFormMsgs(void) const; - - /*! - * @brief Get list of all messages ID correspond with year. + * @brief Get list of all message IDs corresponding with year. * * @return Return message ID list. */ - QStringList getAllMsgsIDEqualWithYear(const QString &year) const; - - static - const QVector receivedItemIds; - static - const QVector sentItemIds; - + QList getAllMsgsIDEqualWithYear(const QString &year) const; /*! * @brief Return list of message ids corresponding to given date @@ -1010,26 +1055,30 @@ /*! * @brief Query received messages within past 90 days. * - * @param[in,out] query Query already assigned to a database. - * @param[in] appendedCols List of names for added empty columns. + * @param[in,out] query Query already assigned to a database. * @return True on success. */ - bool msgsRcvdWithin90DaysQuery(QSqlQuery &query, - const QStringList &appendedCols); + static + bool msgsRcvdWithin90DaysQuery(QSqlQuery &query); /*! * @brief Query received messages within past 90 days. * - * @param[in,out] query Query already assigned to a database. - * @param[in] appendedCols List of names for added empty columns. + * @param[in,out] query Query already assigned to a database. * @return True on success. */ - bool msgsSntWithin90DaysQuery(QSqlQuery &query, - const QStringList &appendedCols); - - DbMsgsTblModel m_sqlMsgsModel; /*!< Model of displayed messages. */ + static + bool msgsSntWithin90DaysQuery(QSqlQuery &query); public: + /* + * TODO -- Use static methods returning reference to static constant + * vector. + */ + static + const QVector rcvdItemIds; + static + const QVector sntItemIds; static const QVector fileItemIds; @@ -1041,8 +1090,6 @@ static const QVector msgStatus; - DbFlsTblModel m_sqlFilesModel; /*!< Model of displayed files. */ - /*! * @brief Adds _dmType column. * @@ -1116,5 +1163,4 @@ friend class MessageDbSingle; }; - #endif /* _MESSAGE_DB_H_ */ diff -Nru datovka-4.8.3/src/io/message_db_set.cpp datovka-4.9.3/src/io/message_db_set.cpp --- datovka-4.8.3/src/io/message_db_set.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/message_db_set.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +30,7 @@ #include #include -#include "message_db_set.h" +#include "src/io/message_db_set.h" #include "src/log/log.h" MessageDbSet::MessageDbSet(const QString &locDir, const QString &primaryKey, diff -Nru datovka-4.8.3/src/io/message_db_set_delegated.cpp datovka-4.9.3/src/io/message_db_set_delegated.cpp --- datovka-4.8.3/src/io/message_db_set_delegated.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/message_db_set_delegated.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,9 +26,14 @@ #include #include -#include "message_db_set.h" +#include "src/io/message_db_set.h" #include "src/log/log.h" +/* + * If defined then no attaching of databases will be performed. + */ +#define DISABLE_DB_ATTACHING 1 + bool MessageDbSet::vacuum(void) { for (QMap::const_iterator i = this->begin(); @@ -79,61 +84,53 @@ return keys; } -QAbstractTableModel *MessageDbSet::_sf_msgsRcvdModel( - const QStringList &appendedCols) +QList MessageDbSet::_sf_msgsRcvdEntries(void) const { if (this->size() == 0) { - return &DbMsgsTblModel::dummyModel( - DbMsgsTblModel::DUMMY_RCVD); + return QList(); } Q_ASSERT(this->size() == 1); - return this->first()->msgsRcvdModel(appendedCols); + return this->first()->msgsRcvdEntries(); } -QAbstractTableModel *MessageDbSet::_yrly_msgsRcvdModel( - const QStringList &appendedCols) +QList MessageDbSet::_yrly_msgsRcvdEntries(void) const { /* TODO -- Implementation missing and will probably be missing. */ - Q_UNUSED(appendedCols); Q_ASSERT(0); - return NULL; + return QList(); } -QAbstractTableModel *MessageDbSet::msgsRcvdModel( - const QStringList &appendedCols) +QList MessageDbSet::msgsRcvdEntries(void) const { switch (m_organisation) { case DO_SINGLE_FILE: - return _sf_msgsRcvdModel(appendedCols); + return _sf_msgsRcvdEntries(); break; case DO_YEARLY: - return _yrly_msgsRcvdModel(appendedCols); + return _yrly_msgsRcvdEntries(); break; default: Q_ASSERT(0); break; } - return NULL; + return QList(); } -QAbstractTableModel *MessageDbSet::_sf_msgsRcvdWithin90DaysModel( - const QStringList &appendedCols) +QList MessageDbSet::_sf_msgsRcvdEntriesWithin90Days(void) const { if (this->size() == 0) { - return &DbMsgsTblModel::dummyModel( - DbMsgsTblModel::DUMMY_RCVD); + return QList(); } Q_ASSERT(this->size() == 1); - return this->first()->msgsRcvdWithin90DaysModel(appendedCols); + return this->first()->msgsRcvdEntriesWithin90Days(); } -QAbstractTableModel *MessageDbSet::_yrly_2dbs_attach_msgsRcvdWithin90DaysModel( - MessageDb &db, const QString &attachFileName, - const QStringList &appendedCols) +QList MessageDbSet::_yrly_2dbs_attach_msgsRcvdEntriesWithin90Days( + MessageDb &db, const QString &attachFileName) { + QList entryList; QSqlQuery query(db.m_db); - QAbstractTableModel *ret = 0; bool attached = false; QString queryStr; @@ -143,14 +140,11 @@ } queryStr = "SELECT "; - for (int i = 0; i < (DbMsgsTblModel::rcvdItemIds().size() - 2); ++i) { - queryStr += DbMsgsTblModel::rcvdItemIds()[i] + ", "; + for (int i = 0; i < (MessageDb::rcvdItemIds.size() - 2); ++i) { + queryStr += MessageDb::rcvdItemIds[i] + ", "; } queryStr += "(ifnull(r.message_id, 0) != 0) AS is_downloaded" ", "; queryStr += "ifnull(p.state, 0) AS process_status"; - for (int i = 0; i < appendedCols.size(); ++i) { - queryStr += ", null"; - } queryStr += " FROM messages AS m " "LEFT JOIN supplementary_message_data AS s " "ON (m.dmID = s.message_id) " @@ -164,14 +158,11 @@ "(m.dmDeliveryTime >= date('now','-90 day'))" " UNION " "SELECT "; - for (int i = 0; i < (DbMsgsTblModel::rcvdItemIds().size() - 2); ++i) { - queryStr += DbMsgsTblModel::rcvdItemIds()[i] + ", "; + for (int i = 0; i < (MessageDb::rcvdItemIds.size() - 2); ++i) { + queryStr += MessageDb::rcvdItemIds[i] + ", "; } queryStr += "(ifnull(r.message_id, 0) != 0) AS is_downloaded" ", "; queryStr += "ifnull(p.state, 0) AS process_status"; - for (int i = 0; i < appendedCols.size(); ++i) { - queryStr += ", null"; - } queryStr += " FROM " DB2 ".messages AS m " "LEFT JOIN " DB2 ".supplementary_message_data AS s " "ON (m.dmID = s.message_id) " @@ -195,13 +186,7 @@ goto fail; } - db.m_sqlMsgsModel.setQuery(query, DbMsgsTblModel::WORKING_RCVD); - if (!db.m_sqlMsgsModel.setRcvdHeader(appendedCols)) { - Q_ASSERT(0); - goto fail; - } - - ret = &db.m_sqlMsgsModel; + MessageDb::appendRcvdEntryList(entryList, query); fail: /* Query must be finished before detaching. */ @@ -209,144 +194,129 @@ if (attached) { MessageDb::detachDb2(query); } - return ret; + return entryList; } -QAbstractTableModel *MessageDbSet::_yrly_2dbs_msgsRcvdWithin90DaysModel( - MessageDb &db0, MessageDb &db1, const QStringList &appendedCols) +QList MessageDbSet::_yrly_2dbs_msgsRcvdEntriesWithin90Days( + MessageDb &db0, MessageDb &db1) { - QAbstractTableModel *ret = 0; + QList entryList; { QSqlQuery query(db0.m_db); - if (!db0.msgsRcvdWithin90DaysQuery(query, appendedCols)) { + if (!db0.msgsRcvdWithin90DaysQuery(query)) { goto fail; } - db0.m_sqlMsgsModel.setQuery(query, - DbMsgsTblModel::WORKING_RCVD); - if (!db0.m_sqlMsgsModel.setRcvdHeader(appendedCols)) { - Q_ASSERT(0); - goto fail; - } + MessageDb::appendRcvdEntryList(entryList, query); } { QSqlQuery query(db1.m_db); - if (!db1.msgsRcvdWithin90DaysQuery(query, appendedCols)) { + if (!db1.msgsRcvdWithin90DaysQuery(query)) { goto fail; } - db0.m_sqlMsgsModel.appendQueryData(query, - DbMsgsTblModel::WORKING_RCVD); + MessageDb::appendRcvdEntryList(entryList, query); } - ret = &db0.m_sqlMsgsModel; - fail: - return ret; + return entryList; } -QAbstractTableModel *MessageDbSet::_yrly_msgsRcvdWithin90DaysModel( - const QStringList &appendedCols) +QList MessageDbSet::_yrly_msgsRcvdEntriesWithin90Days(void) const { + QList entryList; QStringList secKeys = _yrly_secKeysIn90Days(); if (secKeys.size() == 0) { - return &DbMsgsTblModel::dummyModel( - DbMsgsTblModel::DUMMY_RCVD); + return QList(); } else if (secKeys.size() == 1) { /* Query only one database. */ - MessageDb *db = this->value(secKeys[0], NULL); - if (NULL == db) { + MessageDb *db = this->value(secKeys[0], Q_NULLPTR); + if (Q_NULLPTR == db) { Q_ASSERT(0); - return NULL; + return QList(); } - return db->msgsRcvdWithin90DaysModel(appendedCols); + return db->msgsRcvdEntriesWithin90Days(); } else { Q_ASSERT(secKeys.size() == 2); /* The models need to be attached. */ - MessageDb *db0 = this->value(secKeys[0], NULL); - MessageDb *db1 = this->value(secKeys[1], NULL); - if ((NULL == db0) || (NULL == db1)) { + MessageDb *db0 = this->value(secKeys[0], Q_NULLPTR); + MessageDb *db1 = this->value(secKeys[1], Q_NULLPTR); + if ((Q_NULLPTR == db0) || (Q_NULLPTR == db1)) { Q_ASSERT(0); - return NULL; + return QList(); } -#if 0 - return _yrly_2dbs_attach_msgsRcvdWithin90DaysModel(*db0, - db1->fileName(), appendedCols); -#else - return _yrly_2dbs_msgsRcvdWithin90DaysModel(*db0, *db1, - appendedCols); -#endif +#if defined DISABLE_DB_ATTACHING + return _yrly_2dbs_msgsRcvdEntriesWithin90Days(*db0, *db1); +#else /* !DISABLE_DB_ATTACHING */ + return _yrly_2dbs_attach_msgsRcvdEntriesWithin90Days(*db0, + db1->fileName()); +#endif /* DISABLE_DB_ATTACHING */ } - - Q_ASSERT(0); - return NULL; } -QAbstractTableModel *MessageDbSet::msgsRcvdWithin90DaysModel( - const QStringList &appendedCols) +QList MessageDbSet::msgsRcvdEntriesWithin90Days(void) const { switch (m_organisation) { case DO_SINGLE_FILE: - return _sf_msgsRcvdWithin90DaysModel(appendedCols); + return _sf_msgsRcvdEntriesWithin90Days(); break; case DO_YEARLY: - return _yrly_msgsRcvdWithin90DaysModel(appendedCols); + return _yrly_msgsRcvdEntriesWithin90Days(); break; default: Q_ASSERT(0); break; } - return NULL; + return QList(); } -QAbstractTableModel *MessageDbSet::_sf_msgsRcvdInYearModel(const QString &year, - const QStringList &appendedCols) +QList MessageDbSet::_sf_msgsRcvdEntriesInYear( + const QString &year) const { if (this->size() == 0) { - return &DbMsgsTblModel::dummyModel( - DbMsgsTblModel::DUMMY_RCVD); + return QList(); } Q_ASSERT(this->size() == 1); - return this->first()->msgsRcvdInYearModel(year, appendedCols); + return this->first()->msgsRcvdEntriesInYear(year); } -QAbstractTableModel *MessageDbSet::_yrly_msgsRcvdInYearModel( - const QString &year, const QStringList &appendedCols) +QList MessageDbSet::_yrly_msgsRcvdEntriesInYear( + const QString &year) const { QString secondaryKey = _yrly_YearToSecondaryKey(year); - MessageDb *db = this->value(secondaryKey, NULL); - if (NULL == db) { - return 0; + MessageDb *db = this->value(secondaryKey, Q_NULLPTR); + if (Q_NULLPTR == db) { + return QList(); } - return db->msgsRcvdInYearModel(year, appendedCols); + return db->msgsRcvdEntriesInYear(year); } -QAbstractTableModel *MessageDbSet::msgsRcvdInYearModel(const QString &year, - const QStringList &appendedCols) +QList MessageDbSet::msgsRcvdEntriesInYear( + const QString &year) const { switch (m_organisation) { case DO_SINGLE_FILE: - return _sf_msgsRcvdInYearModel(year, appendedCols); + return _sf_msgsRcvdEntriesInYear(year); break; case DO_YEARLY: - return _yrly_msgsRcvdInYearModel(year, appendedCols); + return _yrly_msgsRcvdEntriesInYear(year); break; default: Q_ASSERT(0); break; } - return NULL; + return QList(); } QStringList MessageDbSet::_sf_msgsYears(enum MessageDb::MessageType type, @@ -613,58 +583,53 @@ return -1; } -QAbstractTableModel *MessageDbSet::_sf_msgsSntModel( - const QStringList &appendedCols) +QList MessageDbSet::_sf_msgsSntEntries(void) const { if (this->size() == 0) { - return &DbMsgsTblModel::dummyModel(DbMsgsTblModel::DUMMY_SNT); + return QList(); } Q_ASSERT(this->size() == 1); - return this->first()->msgsSntModel(appendedCols); + return this->first()->msgsSntEntries(); } -QAbstractTableModel *MessageDbSet::_yrly_msgsSntModel( - const QStringList &appendedCols) +QList MessageDbSet::_yrly_msgsSntEntries(void) const { /* TODO -- Implementation missing and will probably be missing. */ - Q_UNUSED(appendedCols); Q_ASSERT(0); - return NULL; + return QList(); } -QAbstractTableModel *MessageDbSet::msgsSntModel(const QStringList &appendedCols) +QList MessageDbSet::msgsSntEntries(void) const { switch (m_organisation) { case DO_SINGLE_FILE: - return _sf_msgsSntModel(appendedCols); + return _sf_msgsSntEntries(); break; case DO_YEARLY: - return _yrly_msgsSntModel(appendedCols); + return _yrly_msgsSntEntries(); break; default: Q_ASSERT(0); break; } - return NULL; + return QList(); } -QAbstractTableModel *MessageDbSet::_sf_msgsSntWithin90DaysModel( - const QStringList &appendedCols) +QList MessageDbSet::_sf_msgsSntEntriesWithin90Days(void) const { if (this->size() == 0) { - return &DbMsgsTblModel::dummyModel(DbMsgsTblModel::DUMMY_SNT); + return QList(); } Q_ASSERT(this->size() == 1); - return this->first()->msgsSntWithin90DaysModel(appendedCols); + return this->first()->msgsSntEntriesWithin90Days(); } -QAbstractTableModel *MessageDbSet::_yrly_2dbs_attach_msgsSntWithin90DaysModel( - MessageDb &db, const QString &attachFileName, - const QStringList &appendedCols) +QList MessageDbSet::_yrly_2dbs_attach_msgsSntEntriesWithin90Days( + MessageDb &db, const QString &attachFileName) { + QList entryList; QSqlQuery query(db.m_db); - QAbstractTableModel *ret = 0; bool attached = false; QString queryStr; @@ -674,13 +639,10 @@ } queryStr = "SELECT "; - for (int i = 0; i < (DbMsgsTblModel::sntItemIds().size() - 1); ++i) { - queryStr += DbMsgsTblModel::sntItemIds()[i] + ", "; + for (int i = 0; i < (MessageDb::sntItemIds.size() - 1); ++i) { + queryStr += MessageDb::sntItemIds[i] + ", "; } queryStr += "(ifnull(r.message_id, 0) != 0) AS is_downloaded"; - for (int i = 0; i < appendedCols.size(); ++i) { - queryStr += ", null"; - } queryStr += " FROM messages AS m " "LEFT JOIN supplementary_message_data AS s " "ON (m.dmID = s.message_id) " @@ -693,13 +655,10 @@ " (m.dmDeliveryTime IS NULL))" " UNION " "SELECT "; - for (int i = 0; i < (DbMsgsTblModel::sntItemIds().size() - 1); ++i) { - queryStr += DbMsgsTblModel::sntItemIds()[i] + ", "; + for (int i = 0; i < (MessageDb::sntItemIds.size() - 1); ++i) { + queryStr += MessageDb::sntItemIds[i] + ", "; } queryStr += "(ifnull(r.message_id, 0) != 0) AS is_downloaded"; - for (int i = 0; i < appendedCols.size(); ++i) { - queryStr += ", null"; - } queryStr += " FROM " DB2 ".messages AS m " "LEFT JOIN " DB2 ".supplementary_message_data AS s " "ON (m.dmID = s.message_id) " @@ -722,13 +681,7 @@ goto fail; } - db.m_sqlMsgsModel.setQuery(query, DbMsgsTblModel::WORKING_SNT); - if (!db.m_sqlMsgsModel.setSntHeader(appendedCols)) { - Q_ASSERT(0); - goto fail; - } - - ret = &db.m_sqlMsgsModel; + MessageDb::appendSntEntryList(entryList, query); fail: /* Query must be finished before detaching. */ @@ -736,141 +689,128 @@ if (attached) { MessageDb::detachDb2(query); } - return ret; + return entryList; } -QAbstractTableModel *MessageDbSet::_yrly_2dbs_msgsSntWithin90DaysModel( - MessageDb &db0, MessageDb &db1, const QStringList &appendedCols) +QList MessageDbSet::_yrly_2dbs_msgsSntEntriesWithin90Days( + MessageDb &db0, MessageDb &db1) { - QAbstractTableModel *ret = 0; + QList entryList; { QSqlQuery query(db0.m_db); - if (!db0.msgsSntWithin90DaysQuery(query, appendedCols)) { + if (!db0.msgsSntWithin90DaysQuery(query)) { goto fail; } - db0.m_sqlMsgsModel.setQuery(query, DbMsgsTblModel::WORKING_SNT); - if (!db0.m_sqlMsgsModel.setSntHeader(appendedCols)) { - Q_ASSERT(0); - goto fail; - } + MessageDb::appendSntEntryList(entryList, query); } { QSqlQuery query(db1.m_db); - if (!db1.msgsSntWithin90DaysQuery(query, appendedCols)) { + if (!db1.msgsSntWithin90DaysQuery(query)) { goto fail; } - db0.m_sqlMsgsModel.appendQueryData(query, - DbMsgsTblModel::WORKING_SNT); + MessageDb::appendSntEntryList(entryList, query); } - ret = &db0.m_sqlMsgsModel; - fail: - return ret; + return entryList; } -QAbstractTableModel *MessageDbSet::_yrly_msgsSntWithin90DaysModel( - const QStringList &appendedCols) +QList MessageDbSet::_yrly_msgsSntEntriesWithin90Days(void) const { QStringList secKeys = _yrly_secKeysIn90Days(); if (secKeys.size() == 0) { - return &DbMsgsTblModel::dummyModel(DbMsgsTblModel::DUMMY_SNT); + return QList(); } else if (secKeys.size() == 1) { /* Query only one database. */ - MessageDb *db = this->value(secKeys[0], NULL); - if (NULL == db) { + MessageDb *db = this->value(secKeys[0], Q_NULLPTR); + if (Q_NULLPTR == db) { Q_ASSERT(0); - return NULL; + return QList(); } - return db->msgsSntWithin90DaysModel(appendedCols); + return db->msgsSntEntriesWithin90Days(); } else { Q_ASSERT(secKeys.size() == 2); /* The models need to be attached. */ - MessageDb *db0 = this->value(secKeys[0], NULL); - MessageDb *db1 = this->value(secKeys[1], NULL); - if ((NULL == db0) || (NULL == db1)) { + MessageDb *db0 = this->value(secKeys[0], Q_NULLPTR); + MessageDb *db1 = this->value(secKeys[1], Q_NULLPTR); + if ((Q_NULLPTR == db0) || (Q_NULLPTR == db1)) { Q_ASSERT(0); - return NULL; + return QList(); } -#if 0 - return _yrly_2dbs_attach_msgsSntWithin90DaysModel(*db0, - db1->fileName(), appendedCols); -#else - return _yrly_2dbs_msgsSntWithin90DaysModel(*db0, *db1, - appendedCols); -#endif +#if defined DISABLE_DB_ATTACHING + return _yrly_2dbs_msgsSntEntriesWithin90Days(*db0, *db1); +#else /* !DISABLE_DB_ATTACHING */ + return _yrly_2dbs_attach_msgsSntEntriesWithin90Days(*db0, + db1->fileName()); +#endif /* DISABLE_DB_ATTACHING */ } - - Q_ASSERT(0); - return NULL; } -QAbstractTableModel *MessageDbSet::msgsSntWithin90DaysModel( - const QStringList &appendedCols) +QList MessageDbSet::msgsSntEntriesWithin90Days(void) const { switch (m_organisation) { case DO_SINGLE_FILE: - return _sf_msgsSntWithin90DaysModel(appendedCols); + return _sf_msgsSntEntriesWithin90Days(); break; case DO_YEARLY: - return _yrly_msgsSntWithin90DaysModel(appendedCols); + return _yrly_msgsSntEntriesWithin90Days(); break; default: Q_ASSERT(0); break; } - return NULL; + return QList(); } -QAbstractTableModel *MessageDbSet::_sf_msgsSntInYearModel(const QString &year, - const QStringList &appendedCols) +QList MessageDbSet::_sf_msgsSntEntriesInYear( + const QString &year) const { if (this->size() == 0) { - return &DbMsgsTblModel::dummyModel(DbMsgsTblModel::DUMMY_SNT); + return QList(); } Q_ASSERT(this->size() == 1); - return this->first()->msgsSntInYearModel(year, appendedCols); + return this->first()->msgsSntEntriesInYear(year); } -QAbstractTableModel *MessageDbSet::_yrly_msgsSntInYearModel(const QString &year, - const QStringList &appendedCols) +QList MessageDbSet::_yrly_msgsSntEntriesInYear( + const QString &year) const { QString secondaryKey = _yrly_YearToSecondaryKey(year); - MessageDb *db = this->value(secondaryKey, NULL); - if (NULL == db) { - return 0; + MessageDb *db = this->value(secondaryKey, Q_NULLPTR); + if (Q_NULLPTR == db) { + return QList(); } - return db->msgsSntInYearModel(year, appendedCols); + return db->msgsSntEntriesInYear(year); } -QAbstractTableModel *MessageDbSet::msgsSntInYearModel(const QString &year, - const QStringList &appendedCols) +QList MessageDbSet::msgsSntEntriesInYear( + const QString &year) const { switch (m_organisation) { case DO_SINGLE_FILE: - return _sf_msgsSntInYearModel(year, appendedCols); + return _sf_msgsSntEntriesInYear(year); break; case DO_YEARLY: - return _yrly_msgsSntInYearModel(year, appendedCols); + return _yrly_msgsSntEntriesInYear(year); break; default: Q_ASSERT(0); break; } - return NULL; + return QList(); } bool MessageDbSet::_sf_smsgdtSetAllReceivedLocallyRead(bool read) @@ -1338,25 +1278,25 @@ return QList(); } -QStringList MessageDbSet::_sf_getAllMessageIDsWithoutAttach(void) const +QList MessageDbSet::_sf_getAllMessageIDsWithoutAttach(void) const { if (this->size() == 0) { - return QStringList(); + return QList(); } Q_ASSERT(this->size() == 1); return this->first()->getAllMessageIDsWithoutAttach(); } -QStringList MessageDbSet::_yrly_getAllMessageIDsWithoutAttach(void) const +QList MessageDbSet::_yrly_getAllMessageIDsWithoutAttach(void) const { - QStringList msgIds; + QList msgIds; for (QMap::const_iterator i = this->begin(); i != this->end(); ++i) { MessageDb *db = i.value(); - if (NULL == db) { + if (Q_NULLPTR == db) { Q_ASSERT(0); - return QStringList(); + return QList(); } msgIds.append(db->getAllMessageIDsWithoutAttach()); @@ -1365,7 +1305,7 @@ return msgIds; } -QStringList MessageDbSet::getAllMessageIDsWithoutAttach(void) const +QList MessageDbSet::getAllMessageIDsWithoutAttach(void) const { switch (m_organisation) { case DO_SINGLE_FILE: @@ -1379,9 +1319,55 @@ break; } - return QStringList(); + return QList(); +} + +QList MessageDbSet::_sf_getAllMessageIDs( + enum MessageDb::MessageType messageType) const +{ + if (this->size() == 0) { + return QList(); + } + Q_ASSERT(this->size() == 1); + return this->first()->getAllMessageIDs(messageType); +} + +QList MessageDbSet::_yrly_getAllMessageIDs( + enum MessageDb::MessageType messageType) const +{ + QList msgIds; + + for (QMap::const_iterator i = this->begin(); + i != this->end(); ++i) { + MessageDb *db = i.value(); + if (Q_NULLPTR == db) { + Q_ASSERT(0); + return QList(); + } + + msgIds.append(db->getAllMessageIDs(messageType)); + } + + return msgIds; } +QList MessageDbSet::getAllMessageIDs( + enum MessageDb::MessageType messageType) const +{ + switch (m_organisation) { + case DO_SINGLE_FILE: + return _sf_getAllMessageIDs(messageType); + break; + case DO_YEARLY: + return _yrly_getAllMessageIDs(messageType); + break; + default: + Q_ASSERT(0); + break; + } + + return QList(); +} QList MessageDbSet::_sf_msgsDateInterval( const QDate &fromDate, const QDate &toDate, diff -Nru datovka-4.8.3/src/io/message_db_set.h datovka-4.9.3/src/io/message_db_set.h --- datovka-4.8.3/src/io/message_db_set.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/message_db_set.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +24,6 @@ #ifndef _MESSAGE_DB_SET_H_ #define _MESSAGE_DB_SET_H_ -#include #include #include #include @@ -358,37 +357,27 @@ bool vacuum(void); /*! - * @brief Return all received messages model. + * @brief Return entries for all received messages. * - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. - * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsRcvdModel(const QStringList &appendedCols); + QList msgsRcvdEntries(void) const; /*! - * @brief Return received messages within past 90 days. - * - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. + * @brief Return entries for received messages within past 90 days. * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsRcvdWithin90DaysModel( - const QStringList &appendedCols); + QList msgsRcvdEntriesWithin90Days(void) const; /*! - * @brief Return received messages within given year. + * @brief Return entries for received messages within given year. * * @param[in] year Year number. - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. - * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsRcvdInYearModel(const QString &year, - const QStringList &appendedCols); + QList msgsRcvdEntriesInYear( + const QString &year) const; /*! * @brief Return list of years (strings) in database. @@ -430,37 +419,27 @@ const QString &year) const; /*! - * @brief Return all sent messages model. + * @brief Return entries for all sent messages. * - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. - * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsSntModel(const QStringList &appendedCols); + QList msgsSntEntries(void) const; /*! - * @brief Return sent messages within past 90 days. - * - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. + * @brief Return entries for all sent messages within past 90 days. * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsSntWithin90DaysModel( - const QStringList &appendedCols); + QList msgsSntEntriesWithin90Days(void) const; /*! - * @brief Return sent messages within given year. + * @brief Return entries for sent messages within given year. * * @param[in] year Year number. - * @param[in] appendedCols List of names for added empty columns. - * @return Pointer to model, 0 on failure. - * - * @note The model must not be freed. + * @return List of entries, empty list on failure. */ - QAbstractTableModel *msgsSntInYearModel(const QString &year, - const QStringList &appendedCols); + QList msgsSntEntriesInYear( + const QString &year) const; /*! * @brief Set message read locally for all received messages. @@ -544,11 +523,19 @@ QList getAllMessageIDsFromDB(void) const; /*! - * @brief Return all message ID from database without attachment. + * @brief Return all IDs of messages without attachment. * - * @return message id list. + * @return Message identifier list. */ - QStringList getAllMessageIDsWithoutAttach(void) const; + QList getAllMessageIDsWithoutAttach(void) const; + + /*! + * @brief Return all message IDs from database. + * + * @param[in] messageType Specifies sent or received messages. + * @return Message identifier list. + */ + QList getAllMessageIDs(enum MessageDb::MessageType messageType) const; /*! * @brief Return list of message ids corresponding to given date @@ -594,18 +581,18 @@ */ QStringList _yrly_secKeysIn90Days(void) const; - inline QAbstractTableModel *_sf_msgsRcvdModel(const QStringList &appendedCols); - inline QAbstractTableModel *_yrly_msgsRcvdModel(const QStringList &appendedCols); + inline QList _sf_msgsRcvdEntries(void) const; + inline QList _yrly_msgsRcvdEntries(void) const; - inline QAbstractTableModel *_sf_msgsRcvdWithin90DaysModel(const QStringList &appendedCols); + inline QList _sf_msgsRcvdEntriesWithin90Days(void) const; static - inline QAbstractTableModel *_yrly_2dbs_attach_msgsRcvdWithin90DaysModel(MessageDb &db, const QString &attachFileName, const QStringList &appendedCols); + inline QList _yrly_2dbs_attach_msgsRcvdEntriesWithin90Days(MessageDb &db, const QString &attachFileName); static - inline QAbstractTableModel *_yrly_2dbs_msgsRcvdWithin90DaysModel(MessageDb &db0, MessageDb &db1, const QStringList &appendedCols); - inline QAbstractTableModel *_yrly_msgsRcvdWithin90DaysModel(const QStringList &appendedCols); + inline QList _yrly_2dbs_msgsRcvdEntriesWithin90Days(MessageDb &db0, MessageDb &db1); + inline QList _yrly_msgsRcvdEntriesWithin90Days(void) const; - inline QAbstractTableModel *_sf_msgsRcvdInYearModel(const QString &year, const QStringList &appendedCols); - inline QAbstractTableModel *_yrly_msgsRcvdInYearModel(const QString &year, const QStringList &appendedCols); + inline QList _sf_msgsRcvdEntriesInYear(const QString &year) const; + inline QList _yrly_msgsRcvdEntriesInYear(const QString &year) const; inline QStringList _sf_msgsYears(enum MessageDb::MessageType type, enum Sorting sorting) const; inline QStringList _yrly_msgsYears(enum MessageDb::MessageType type, enum Sorting sorting) const; @@ -619,18 +606,18 @@ inline int _sf_msgsUnreadInYear(enum MessageDb::MessageType type, const QString &year) const; inline int _yrly_msgsUnreadInYear(enum MessageDb::MessageType type, const QString &year) const; - inline QAbstractTableModel *_sf_msgsSntModel(const QStringList &appendedCols); - inline QAbstractTableModel *_yrly_msgsSntModel(const QStringList &appendedCols); + inline QList _sf_msgsSntEntries(void) const; + inline QList _yrly_msgsSntEntries(void) const; - inline QAbstractTableModel *_sf_msgsSntWithin90DaysModel(const QStringList &appendedCols); + inline QList _sf_msgsSntEntriesWithin90Days(void) const; static - inline QAbstractTableModel *_yrly_2dbs_attach_msgsSntWithin90DaysModel(MessageDb &db, const QString &attachFileName, const QStringList &appendedCols); + inline QList _yrly_2dbs_attach_msgsSntEntriesWithin90Days(MessageDb &db, const QString &attachFileName); static - inline QAbstractTableModel *_yrly_2dbs_msgsSntWithin90DaysModel(MessageDb &db0, MessageDb &db1, const QStringList &appendedCols); - inline QAbstractTableModel *_yrly_msgsSntWithin90DaysModel(const QStringList &appendedCols); + inline QList _yrly_2dbs_msgsSntEntriesWithin90Days(MessageDb &db0, MessageDb &db1); + inline QList _yrly_msgsSntEntriesWithin90Days(void) const; - inline QAbstractTableModel *_sf_msgsSntInYearModel(const QString &year, const QStringList &appendedCols); - inline QAbstractTableModel *_yrly_msgsSntInYearModel(const QString &year, const QStringList &appendedCols); + inline QList _sf_msgsSntEntriesInYear(const QString &year) const; + inline QList _yrly_msgsSntEntriesInYear(const QString &year) const; inline bool _sf_smsgdtSetAllReceivedLocallyRead(bool read); inline bool _yrly_smsgdtSetAllReceivedLocallyRead(bool read); @@ -659,8 +646,11 @@ inline QList _sf_getAllMessageIDsFromDB(void) const; inline QList _yrly_getAllMessageIDsFromDB(void) const; - inline QStringList _sf_getAllMessageIDsWithoutAttach(void) const; - inline QStringList _yrly_getAllMessageIDsWithoutAttach(void) const; + inline QList _sf_getAllMessageIDsWithoutAttach(void) const; + inline QList _yrly_getAllMessageIDsWithoutAttach(void) const; + + inline QList _sf_getAllMessageIDs(enum MessageDb::MessageType messageType) const; + inline QList _yrly_getAllMessageIDs(enum MessageDb::MessageType messageType) const; inline QList _sf_msgsDateInterval(const QDate &fromDate, const QDate &toDate, enum MessageDirection msgDirect) const; inline QList _yrly_msgsDateInterval(const QDate &fromDate, const QDate &toDate, enum MessageDirection msgDirect) const; diff -Nru datovka-4.8.3/src/io/records_management_db.cpp datovka-4.9.3/src/io/records_management_db.cpp --- datovka-4.8.3/src/io/records_management_db.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/io/records_management_db.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include +#include + +#include "src/io/db_tables.h" +#include "src/io/records_management_db.h" +#include "src/log/log.h" + +RecordsManagementDb::RecordsManagementDb(const QString &connectionName) + : SQLiteDb(connectionName) +{ +} + +bool RecordsManagementDb::openDb(const QString &fileName) +{ + return SQLiteDb::openDb(fileName, false, listOfTables()); +} + +/*! + * @brief Delete all entries from table. + * + * @param[in,out] db SQL database. + * @param[in] tblName Name of table whose content should be erased. + * @return True on success. + */ +static +bool deleteTableContent(QSqlDatabase &db, const QString &tblName) +{ + if (tblName.isEmpty()) { + return false; + } + + QSqlQuery query(db); + + QString queryStr = "DELETE FROM " + tblName; + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + if (!query.exec()) { + logErrorNL("Cannot execute SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + + return true; +} + +bool RecordsManagementDb::deleteAllEntries(void) +{ + deleteTableContent(m_db, QStringLiteral("service_info")); + deleteTableContent(m_db, QStringLiteral("stored_files_messages")); + + return true; +} + +/*! + * @brief Insert a new service info record into service info table. + * + * @param[in,out] db SQL database. + * @param[in] entry Service info entry. + * @return True on success. + */ +static +bool insertServiceInfo(QSqlDatabase &db, + const RecordsManagementDb::ServiceInfoEntry &entry) +{ + if (!entry.isValid()) { + Q_ASSERT(0); + return false; + } + + QSqlQuery query(db); + + QString queryStr = "INSERT INTO service_info " + "(url, name, token_name, logo_svg) VALUES " + "(:url, :name, :tokenName, :logoSvg)"; + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + + query.bindValue(":url", entry.url); + query.bindValue(":name", entry.name); + query.bindValue(":tokenName", entry.tokenName); + query.bindValue(":logoSvg", entry.logoSvg.toBase64()); + + if (!query.exec()) { + logErrorNL("Cannot execute SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + + return true; +} + +bool RecordsManagementDb::updateServiceInfo(const ServiceInfoEntry &entry) +{ + if (!entry.isValid()) { + return false; + } + + if (!beginTransaction()) { + return false; + } + + if (!deleteTableContent(m_db, QStringLiteral("service_info"))) { + goto rollback; + } + + if (!insertServiceInfo(m_db, entry)) { + goto rollback; + } + + return commitTransaction(); + +rollback: + rollbackTransaction(); + return false; +} + +RecordsManagementDb::ServiceInfoEntry RecordsManagementDb::serviceInfo(void) const +{ + QSqlQuery query(m_db); + + QString queryStr = "SELECT url, name, token_name, logo_svg " + "FROM service_info"; + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return ServiceInfoEntry(); + } + + if (query.exec() && query.isActive()) { + query.first(); + if (query.isValid()) { + ServiceInfoEntry entry; + + entry.url = query.value(0).toString(); + entry.name = query.value(1).toString(); + entry.tokenName = query.value(2).toString(); + entry.logoSvg = QByteArray::fromBase64( + query.value(3).toByteArray()); + + Q_ASSERT(entry.isValid()); + return entry; + } else { + return ServiceInfoEntry(); + } + } else { + logErrorNL( + "Cannot execute SQL query and/or read SQL data: %s.", + query.lastError().text().toUtf8().constData()); + return ServiceInfoEntry(); + } +} + +bool RecordsManagementDb::deleteAllStoredMsg(void) +{ + return deleteTableContent(m_db, + QStringLiteral("stored_files_messages")); +} + +bool RecordsManagementDb::deleteStoredMsg(qint64 dmId) +{ + QSqlQuery query(m_db); + + QString queryStr = "DELETE FROM stored_files_messages " + "WHERE dm_id = :dm_id"; + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + query.bindValue(":dm_id", dmId); + if (!query.exec()) { + logErrorNL("Cannot execute SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + + return true; +} + +bool RecordsManagementDb::updateStoredMsg(qint64 dmId, + const QStringList &locations) +{ +#define LIST_SEPARATOR QLatin1String("^") + + QSqlQuery query(m_db); + + QString queryStr = "INSERT OR REPLACE INTO stored_files_messages " + "(dm_id, separator, joined_locations) VALUES " + "(:dm_id, :separator, :joined_locations)"; + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + + query.bindValue(":dm_id", dmId); + query.bindValue(":separator", LIST_SEPARATOR); + query.bindValue(":joined_locations", locations.join(LIST_SEPARATOR)); + + if (!query.exec()) { + logErrorNL("Cannot exec SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + + return true; + +#undef LIST_SEPARATOR +} + +QList RecordsManagementDb::getAllDmIds(void) const +{ + QSqlQuery query(m_db); + + QList dmIdList; + + QString queryStr = "SELECT dm_id FROM stored_files_messages"; + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return dmIdList; + } + if (query.exec() && query.isActive()) { + query.first(); + while (query.isValid()) { + dmIdList.append(query.value(0).toLongLong()); + query.next(); + } + } + return dmIdList; +} + +QStringList RecordsManagementDb::storedMsgLocations(qint64 dmId) const +{ + QSqlQuery query(m_db); + + QString queryStr = "SELECT separator, joined_locations " + "FROM stored_files_messages WHERE dm_id = :dm_id"; + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return QStringList(); + } + query.bindValue(":dm_id", dmId); + if (query.exec() && query.isActive()) { + query.first(); + if (query.isValid()) { + QString separator(query.value(0).toString()); + return query.value(1).toString().split(separator); + } else { + return QStringList(); + } + } else { + logErrorNL( + "Cannot execute SQL query and/or read SQL data: %s.", + query.lastError().text().toUtf8().constData()); + return QStringList(); + } +} + +QList RecordsManagementDb::listOfTables(void) +{ + static QList tables; + if (tables.isEmpty()) { + tables.append(&srvcInfTbl); + tables.append(&strdFlsMsgsTbl); + } + return tables; +} + +RecordsManagementDb *globRecordsManagementDbPtr = Q_NULLPTR; diff -Nru datovka-4.8.3/src/io/records_management_db.h datovka-4.9.3/src/io/records_management_db.h --- datovka-4.8.3/src/io/records_management_db.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/io/records_management_db.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _RECORDS_MANAGEMENT_DB_H_ +#define _RECORDS_MANAGEMENT_DB_H_ + +#include +#include +#include + +#include "src/io/sqlite/db.h" + +/*! + * @brief Encapsulates records management database. + */ +class RecordsManagementDb : public SQLiteDb { + +public: + class ServiceInfoEntry { + public: + /*! + * @brief Constructor. + */ + ServiceInfoEntry(void) + : url(), name(), tokenName(), logoSvg() + { + } + + /*! + * @brief Return true in entry is valid. + */ + inline + bool isValid(void) const { + return !url.isEmpty(); + } + + QString url; /*!< Service URL. */ + QString name; /*!< Service name. */ + QString tokenName; /*!< Token name. */ + QByteArray logoSvg; /*!< Raw SVG data. */ + }; + + /*! + * @brief Constructor. + * + * @param[in] connectionName Connection name. + */ + explicit RecordsManagementDb(const QString &connectionName); + + /*! + * @brief Open database file. + * + * @param[in] fileName File name. + * @return True on success, false on any error. + */ + bool openDb(const QString &fileName); + + /*! + * @brief Erases all database entries. + * + * @return True on success. + */ + bool deleteAllEntries(void); + + /*! + * @brief Update service info entry. + * + * @note There can be only one service info entry. + * + * @param[in] entry Service info entry. + */ + bool updateServiceInfo(const ServiceInfoEntry &entry); + + /*! + * @brief Obtain service information from database. + * + * @return Invalid service info if no valid service information found. + */ + ServiceInfoEntry serviceInfo(void) const; + + /*! + * @brief Deletes all message-related data. + * + * @return True on success. + */ + bool deleteAllStoredMsg(void); + + /*! + * @brief Deletes stored locations for given message. + * + * @param[in] dmId Message identifier. + * @return True on success. + */ + bool deleteStoredMsg(qint64 dmId); + + /*! + * @brief Inserts or replaces stored locations for given message. + * + * @param[in] dmId Message identifier. + * @param[in] locations List of locations to be stored. + * @return True on success. + */ + bool updateStoredMsg(qint64 dmId, const QStringList &locations); + + /*! + * @brief Obtains all message identifiers. + * + * @return List of message identifiers, empty list on error. + */ + QList getAllDmIds(void) const; + + /*! + * @brief Reads stored location or given message. + * + * @param[in] dmId Message identifier. + * @return List of locations, empty list on error. + */ + QStringList storedMsgLocations(qint64 dmId) const; + +private: + /*! + * @brief Returns list of tables. + * + * @return List of pointers to tables. + */ + static + QList listOfTables(void); +}; + +/*! + * @brief Global records management database. + */ +extern RecordsManagementDb *globRecordsManagementDbPtr; + +#endif /* _RECORDS_MANAGEMENT_DB_H_ */ diff -Nru datovka-4.8.3/src/io/tag_db_container.cpp datovka-4.9.3/src/io/tag_db_container.cpp --- datovka-4.8.3/src/io/tag_db_container.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/tag_db_container.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - - -#include -#include -#include - -#include "src/io/tag_db_container.h" -#include "src/models/accounts_model.h" -#include "src/settings/preferences.h" - -/* ========================================================================= */ -TagDbContainer::TagDbContainer(const QString &connectionName) -/* ========================================================================= */ - : QMap(), - m_connectionName(connectionName) -{ -} - - -/* ========================================================================= */ -TagDbContainer::~TagDbContainer(void) -/* ========================================================================= */ -{ - QMap::iterator i; - - for (i = this->begin(); i != this->end(); ++i) { - delete i.value(); - } -} - -/* ========================================================================= */ -/* - * Access/create+open message database related to item. - */ -TagDb *TagDbContainer::accessTagDb(const QString &key) -/* ========================================================================= */ -{ - TagDb *db = NULL; - bool open_ret; - - QString dbTagName = constructDbTagName(key); - - - /* Already opened. */ - if (this->find(dbTagName) != this->end()) { - return (*this)[dbTagName]; - } - - db = new(std::nothrow) TagDb(dbTagName); - if (NULL == db) { - Q_ASSERT(0); - return NULL; - } - - open_ret = db->openDb(dbTagName); - if (!open_ret) { - delete db; - return NULL; - } - - this->insert(dbTagName, db); - - return db; -} - - -/* ========================================================================= */ -/* - * Delete message db. - */ -bool TagDbContainer::deleteDb(TagDb *db) -/* ========================================================================= */ -{ - if (0 == db) { - Q_ASSERT(0); - return false; - } - - /* Find entry. */ - QMap::iterator it = this->begin(); - while ((it != this->end()) && (it.value() != db)) { - ++it; - } - /* Must exist. */ - if (this->end() == it) { - Q_ASSERT(0); - return false; - } - - /* Remove from container. */ - this->erase(it); - - /* Get file name. */ - QString fileName = db->fileName(); - - /* Close database. */ - delete db; - - if (fileName == TagDb::memoryLocation) { - return true; - } - - /* Delete file. */ - if (!QFile::remove(fileName)) { - return false; - } - - return true; -} - - -/* ========================================================================= */ -/* - * Creates the database name from supplied information. - */ -QString TagDbContainer::constructDbTagName(const QString &primaryKey) -/* ========================================================================= */ -{ - /* get current db file location */ - AcntSettings &itemSettings(AccountModel::globAccounts[primaryKey]); - QString dbDir = itemSettings.dbDir(); - if (dbDir.isEmpty()) { - dbDir = globPref.confDir(); - } - - return dbDir + QDir::separator() + primaryKey + "-tag.db"; -} - - -TagDbContainer * globWebDatovkaTagDbPtr = 0; diff -Nru datovka-4.8.3/src/io/tag_db_container.h datovka-4.9.3/src/io/tag_db_container.h --- datovka-4.8.3/src/io/tag_db_container.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/tag_db_container.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _TAG_DB_CONTAINER_H_ -#define _TAG_DB_CONTAINER_H_ - - -#include -#include - -#include "src/io/tag_db.h" - -/*! - * @brief Database container. - * - * TODO -- Should there be a single globally accessible instance? - * (Actually no singleton.) - */ -class TagDbContainer : private QMap { -public: - explicit TagDbContainer(const QString &connectionName); - ~TagDbContainer(void); - - /*! - * @brief Access/create+open message database set related to item. - * - * @param[in] primaryKey Part of database file name, usually the login. - * @return Pointer to database, zero pointer on error. - */ - TagDb *accessTagDb(const QString &key); - - /*! - * @brief Delete tag database. - * - * @param db Deleted database. - * @return True on success. - */ - bool deleteDb(TagDb *db); - - /*! - * @brief Creates the database name from supplied information. - * - * @param[in] key user name. - * @return Path to database file. - */ - static - QString constructDbTagName(const QString &key); - - const QString m_connectionName; -}; - -/*! - * @brief Global database container. - */ -extern TagDbContainer * globWebDatovkaTagDbPtr; - -#endif /* _TAG_DB_CONTAINER_H_ */ diff -Nru datovka-4.8.3/src/io/tag_db.cpp datovka-4.9.3/src/io/tag_db.cpp --- datovka-4.8.3/src/io/tag_db.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/tag_db.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ * the two. */ +#include #include #include #include @@ -31,6 +32,40 @@ #include "src/io/tag_db.h" #include "src/log/log.h" +#define DFLT_COLOUR "ffffff" + +TagDb::TagEntry::TagEntry(void) + : id(-1), + name(), + colour(DFLT_COLOUR) +{ +} + +TagDb::TagEntry::TagEntry(int i, const QString &n, const QString &c) + : id(i), + name(n), + colour(isValidColourStr(c) ? c : DFLT_COLOUR) +{ +} + +bool TagDb::TagEntry::isValid(void) const +{ + return (id >= 0) && !name.isEmpty() && (6 == colour.size()); +} + +bool TagDb::TagEntry::isValidColourStr(const QString &colourStr) +{ + QRegExp re("^[a-f0-9]{6,6}$"); + + return re.exactMatch(colourStr); +} + +bool TagDb::TagEntry::operator==(const TagEntry &other) const +{ + return (id == other.id) && (name == other.name) && + (colour == other.colour); +} + TagDb::TagDb(const QString &connectionName) : SQLiteDb(connectionName) { @@ -83,34 +118,6 @@ return true; } -bool TagDb::insertUpdateWebDatovkaTag(int id, - const QString &tagName, const QString &tagColor) -{ - QSqlQuery query(m_db); - - QString queryStr = "INSERT OR REPLACE INTO tag (id, tag_name, tag_color) " - "VALUES (:tag_id, :tag_name, :tag_color)"; - - if (!query.prepare(queryStr)) { - logErrorNL("Cannot prepare SQL query: %s.", - query.lastError().text().toUtf8().constData()); - return false; - } - - query.bindValue(":tag_id", id); - query.bindValue(":tag_name", tagName); - query.bindValue(":tag_color", tagColor); - - if (!query.exec()) { - logErrorNL("Cannot execute SQL query: %s.", - query.lastError().text().toUtf8().constData()); - return false; - } - - return true; -} - - bool TagDb::updateTag(int id, const QString &tagName, const QString &tagColor) { QSqlQuery query(m_db); @@ -191,7 +198,7 @@ } -TagItem TagDb::getTagData(int id) +TagDb::TagEntry TagDb::getTagData(int id) const { QSqlQuery query(m_db); @@ -204,7 +211,7 @@ query.bindValue(":id", id); if (query.exec() && query.isActive() && query.first() && query.isValid()) { - return TagItem(id, query.value(0).toString(), + return TagEntry(id, query.value(0).toString(), query.value(1).toString()); } else { logErrorNL( @@ -214,13 +221,13 @@ } fail: - return TagItem(); + return TagEntry(); } -QList TagDb::getAllTags(void) +QList TagDb::getAllTags(void) const { QSqlQuery query(m_db); - QList tagList; + QList tagList; QString queryStr = "SELECT * FROM tag ORDER BY tag_name ASC"; if (!query.prepare(queryStr)) { @@ -232,7 +239,7 @@ if (query.exec() && query.isActive()) { query.first(); while (query.isValid()) { - tagList.append(TagItem(query.value(0).toInt(), + tagList.append(TagEntry(query.value(0).toInt(), query.value(1).toString(), query.value(2).toString())); query.next(); @@ -245,13 +252,14 @@ return tagList; fail: - return QList(); + return QList(); } -TagItemList TagDb::getMessageTags(const QString &userName, quint64 msgId) +QList TagDb::getMessageTags(const QString &userName, + quint64 msgId) const { QSqlQuery query(m_db); - TagItemList tagList; + QList tagList; QString queryStr = "SELECT t.id, t.tag_name, t.tag_color " "FROM tag AS t " @@ -270,7 +278,7 @@ if (query.exec() && query.isActive()) { query.first(); while (query.isValid()) { - tagList.append(TagItem(query.value(0).toInt(), + tagList.append(TagEntry(query.value(0).toInt(), query.value(1).toString(), query.value(2).toString())); query.next(); @@ -283,7 +291,7 @@ } fail: - return TagItemList(); + return QList(); } bool TagDb::removeAllTagsFromMsg(const QString &userName, qint64 msgId) @@ -401,7 +409,7 @@ return true; } -QList TagDb::getMsgIdsContainSearchTagText(const QString &text) +QList TagDb::getMsgIdsContainSearchTagText(const QString &text) const { QSqlQuery query(m_db); QList msgIdList; @@ -447,3 +455,8 @@ } TagDb *globTagDbPtr = 0; + +uint qHash(const TagDb::TagEntry &entry, uint seed) +{ + return ::qHash(entry.id, seed); +} diff -Nru datovka-4.8.3/src/io/tag_db.h datovka-4.9.3/src/io/tag_db.h --- datovka-4.8.3/src/io/tag_db.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/tag_db.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +27,6 @@ #include #include -#include "src/delegates/tag_item.h" #include "src/io/sqlite/db.h" /*! @@ -37,6 +36,61 @@ public: /*! + * @brief Encapsulates database tag entry. + */ + class TagEntry { + public: + /*! + * @brief Constructor of invalid tag entry. + * + * @note Identifier is -1, has empty name, colour is 'ffffff'; + */ + TagEntry(void); + + /*! + * @brief Constructs a tag entry from supplied parameters. + * + * @param[in] i Tag identifier. + * @param[in] n Tag name. + * @param[in] c Tag colour in hex format without the leading hashtag. + */ + TagEntry(int i, const QString &n, const QString &c); + + /*! + * @brief Check for validity. + * + * @note Invalid tag has id equal to -1, empty name and bogus colour. + * + * @return True if tag contains valid data. + */ + bool isValid(void) const; + + /*! + * @brief Returns true if colour string is valid. + * + * @param[in] colourStr Colour string. + * @return True if colour string is valid. + */ + static + bool isValidColourStr(const QString &colourStr); + + /*! + * @brief Comparison operator. + * + * @param[in] other Another object to compare this one with. + * @return True is the other entry is equal to this one. + */ + bool operator==(const TagEntry &other) const; + + int id; /*!< Tag identifier. */ + QString name; /*!< Name of the tag. */ + QString colour; /*!< + * Colour of the tag in hex format without + * the leading hashtag. + */ + }; + + /*! * @brief Constructor. * * @param[in] connectionName Connection name. @@ -61,17 +115,6 @@ bool insertTag(const QString &tagName, const QString &tagColor); /*! - * @brief Insert new or update webdatovka tag into database file. - * - * @param[in] id id of tag form webdatovka. - * @param[in] tagName text label of tag. - * @param[in] tagColor color of tag in HEX format. - * @return True on success, false on any error. - */ - bool insertUpdateWebDatovkaTag(int id, const QString &tagName, - const QString &tagColor); - - /*! * @brief Update tag in database file. * * @param[in] id id of tag. @@ -102,14 +145,14 @@ * @param[in] id id of tag. * @return tag struct with data. */ - TagItem getTagData(int id); + TagEntry getTagData(int id) const; /*! * @brief Get all tags from database file. * - * @return Llist of TagItem. + * @return List of tag entries. */ - QList getAllTags(void); + QList getAllTags(void) const; /*! * @brief Get all tags related to given message. @@ -118,8 +161,8 @@ * @param[in] dmgId Message identifier. * @return List of tags related to message. */ - TagItemList getMessageTags(const QString &userName, - const quint64 msgId); + QList getMessageTags(const QString &userName, + const quint64 msgId) const; /*! * @brief Delete all tags for message ID @@ -165,7 +208,7 @@ * @param[in] text search text of tag name. * @return List of message IDs related to tag text. */ - QList getMsgIdsContainSearchTagText(const QString &text); + QList getMsgIdsContainSearchTagText(const QString &text) const; private: /*! @@ -182,4 +225,13 @@ */ extern TagDb *globTagDbPtr; +/*! + * @brief Return a hash value for the supplied tag entry. + * + * @param[in] entry Tag entry to compute hash from. + * @param[in] seed Is used to initialise the hash if specified. + * @return Hashed tag entry. + */ +uint qHash(const TagDb::TagEntry &entry, uint seed = 0); + #endif /* _TAG_DB_H_ */ diff -Nru datovka-4.8.3/src/io/wd_sessions.cpp datovka-4.9.3/src/io/wd_sessions.cpp --- datovka-4.8.3/src/io/wd_sessions.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/wd_sessions.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2014-2016 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - - -#include -#include - -#include "src/io/wd_sessions.h" -#include "src/log/log.h" - -GlobWDSessions wdSessions; - -/* ========================================================================= */ -GlobWDSessions::GlobWDSessions(void) -/* ========================================================================= */ - : m_wdSessions() -{ -} - - -/* ========================================================================= */ -GlobWDSessions::~GlobWDSessions(void) -/* ========================================================================= */ -{ - m_wdSessions.clear(); -} - - -/* ========================================================================= */ -bool GlobWDSessions::holdsSession(const QString &userName) const -/* ========================================================================= */ -{ - return m_wdSessions.contains(userName); -} - - -/* ========================================================================= */ -/* - * Is connect to databox given by account index - */ -bool GlobWDSessions::isConnectedToWebdatovka(const QString &userName) -/* ========================================================================= */ -{ - if (!holdsSession(userName)) { - return false; - } else { - if (m_wdSessions.value(userName).name().isEmpty()) { - return false; - } - if (m_wdSessions.value(userName).value().isEmpty()) { - return false; - } - } - return true; -} - - -/* ========================================================================= */ -/* - * Creates new session. - */ -void GlobWDSessions::createCleanSession(const QString &userName) -/* ========================================================================= */ -{ - m_wdSessions.insert(userName, QNetworkCookie()); -} - - -/* ========================================================================= */ -/* - * Set cookie to session associated to user name. - */ -bool GlobWDSessions::setSessionCookie(const QString &userName, - const QNetworkCookie &cookie) -/* ========================================================================= */ -{ - m_wdSessions.insert(userName, cookie); - return true; -} - - -/* ========================================================================= */ -/* - * Returns associated session. - */ -QNetworkCookie GlobWDSessions::sessionCookie(const QString &userName) const -/* ========================================================================= */ -{ - return m_wdSessions.value(userName); -} diff -Nru datovka-4.8.3/src/io/wd_sessions.h datovka-4.9.3/src/io/wd_sessions.h --- datovka-4.8.3/src/io/wd_sessions.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/io/wd_sessions.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2014-2016 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - - -#ifndef _WEBDATOVKA_SESSIONS_H_ -#define _WEBDATOVKA_SESSIONS_H_ - -#include -#include -#include - - -/*! - * @brief Holds the webdatovka context structures. - */ -class GlobWDSessions { - -public: - GlobWDSessions(void); - ~GlobWDSessions(void); - - /*! - * @brief Returns true is active session exists. - */ - bool holdsSession(const QString &userName) const; - - /*! - * @brief Returns associated session cookie. - */ - QNetworkCookie sessionCookie(const QString &userName) const; - - /*! - * @brief Ping of webdatovka. Test if connection is active. - */ - bool isConnectedToWebdatovka(const QString &userName); - - /*! - * @brief Creates new session. - */ - void createCleanSession(const QString &userName); - - /*! - * @brief Set cookie to session associated to user name. - * - * @return True on success. - */ - bool setSessionCookie(const QString &userName, - const QNetworkCookie &cookie); - -private: - QMap m_wdSessions; -}; - -/* Global webdatovka context container instance. */ -extern GlobWDSessions wdSessions; - -#endif /* _WEBDATOVKA_SESSIONS_H_ */ diff -Nru datovka-4.8.3/src/isds/isds_conversion.cpp datovka-4.9.3/src/isds/isds_conversion.cpp --- datovka-4.8.3/src/isds/isds_conversion.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/isds/isds_conversion.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include "src/io/isds_sessions.h" +#include "src/isds/isds_conversion.h" +#include "src/log/log.h" + +const QString &IsdsConversion::attachmentTypeToStr(int val) +{ + static const QString main("main"), encl("encl"), sign("sign"), + meta("meta"); + static const QString invalid; + + switch (val) { + case FILEMETATYPE_MAIN: return main; break; + case FILEMETATYPE_ENCLOSURE: return encl; break; + case FILEMETATYPE_SIGNATURE: return sign; break; + case FILEMETATYPE_META: return sign; break; + default: + logWarningNL("Unknown attachment type value '%d'.", val); + return invalid; + break; + } +} + +QString IsdsConversion::boxStateToText(int val) +{ + switch (val) { + case DBSTATE_ACCESSIBLE: + /* Datová schránka je přístupná, lze do ní dodávat zprávy, na Portále lze vyhledat. */ + return tr( + "The data box is accessible. It is possible to send messages into it. It can be looked up on the Portal."); + break; + case DBSTATE_TEMP_UNACCESSIBLE: + /* Datová schránka je dočasně znepřístupněna (na vlastní žádost), může být později opět zpřístupněna. */ + return tr( + "The data box is temporarily inaccessible (at own request). It may be made accessible again at some point in the future."); + break; + case DBSTATE_NOT_YET_ACCESSIBLE: + /* Datová schránka je dosud neaktivní. Vlastník schránky se musí poprvé přihlásit do webového rozhraní, aby došlo k aktivaci schránky. */ + return tr( + "The data box is so far inactive. The owner of the box has to log into the web interface at first in order to activate the box."); + break; + case DBSTATE_PERM_UNACCESSIBLE: + /* Datová schránka je trvale znepřístupněna, čeká na smazání (může být opět zpřístupněna). */ + return tr( + "The data box is permanently inaccessible. It is waiting to be deleted (but it may be made accessible again)."); + break; + case DBSTATE_REMOVED: + /* Datová schránka je smazána (přesto existuje v ISDS). */ + return tr( + "The data box has been deleted (none the less it exists in ISDS)."); + break; + case DBSTATE_TEMP_UNACCESSIBLE_LAW: + /* Datová schránka je dočasně znepřístupněna (z důvodů vyjmenovaných v zákoně), může být později opět zpřístupněna. */ + return tr( + "The data box is temporarily inaccessible (because of reasons listed in law). It may be made accessible again at some point in the future."); + break; + default: + logWarningNL("Unknown data box status value '%d'.", val); + return tr("An error occurred while checking the status."); + break; + } +} + +/* + * DBTYPE_OVM_MAIN is a special value introduced in git version of libisds. + * It appears not to be included in officially released source packages. + * TODO -- Check the function of DBTYPE_OVM_MAIN. + */ +#define STR_OVM_MAIN "OVM_MAIN" +#define STR_SYSTEM "SYSTEM" +#define STR_OVM "OVM" +#define STR_OVM_NOTAR "OVM_NOTAR" +#define STR_OVM_EXEKUT "OVM_EXEKUT" +#define STR_OVM_REQ "OVM_REQ" +#define STR_OVM_FO "OVM_FO" +#define STR_OVM_PFO "OVM_PFO" +#define STR_OVM_PO "OVM_PO" +#define STR_PO "PO" +#define STR_PO_ZAK "PO_ZAK" +#define STR_PO_REQ "PO_REQ" +#define STR_PFO "PFO" +#define STR_PFO_ADVOK "PFO_ADVOK" +#define STR_PFO_DANPOR "PFO_DANPOR" +#define STR_PFO_INSSPR "PFO_INSSPR" +#define STR_PFO_AUDITOR "PFO_AUDITOR" +#define STR_FO "FO" + +const QString &IsdsConversion::boxTypeToStr(int val) +{ + static const QString system(STR_SYSTEM), + ovm(STR_OVM), ovmNotar(STR_OVM_NOTAR), ovmExekut(STR_OVM_EXEKUT), + ovmReq(STR_OVM_REQ), ovmFo(STR_OVM_FO), ovmPfo(STR_OVM_PFO), + ovmPo(STR_OVM_PO), po(STR_PO), poZak(STR_PO_ZAK), poReq(STR_PO_REQ), + pfo(STR_PFO), pfoAdvok(STR_PFO_ADVOK), pfoDanpor(STR_PFO_DANPOR), + pfoInsspr(STR_PFO_INSSPR), pfoAuditor(STR_PFO_AUDITOR), fo(STR_FO); + static const QString invalid; + + switch (val) { + case DBTYPE_SYSTEM: return system; break; + case DBTYPE_OVM: return ovm; break; + case DBTYPE_OVM_NOTAR: return ovmNotar; break; + case DBTYPE_OVM_EXEKUT: return ovmExekut; break; + case DBTYPE_OVM_REQ: return ovmReq; break; + case DBTYPE_OVM_FO: return ovmFo; break; + case DBTYPE_OVM_PFO: return ovmPfo; break; + case DBTYPE_OVM_PO: return ovmPo; break; + case DBTYPE_PO: return po; break; + case DBTYPE_PO_ZAK: return poZak; break; + case DBTYPE_PO_REQ: return poReq; break; + case DBTYPE_PFO: return pfo; break; + case DBTYPE_PFO_ADVOK: return pfoAdvok; break; + case DBTYPE_PFO_DANPOR: return pfoDanpor; break; + case DBTYPE_PFO_INSSPR: return pfoInsspr; break; + case DBTYPE_PFO_AUDITOR: return pfoAuditor; break; + case DBTYPE_FO: return fo; break; + default: + logWarningNL("Unknown data box type value '%d'.", val); + return invalid; + break; + } +} + +int IsdsConversion::boxTypeStrToInt(const QString &val) +{ + if (val == QLatin1String(STR_SYSTEM)) return DBTYPE_SYSTEM; + else if (val == QLatin1String(STR_OVM)) return DBTYPE_OVM; + else if (val == QLatin1String(STR_OVM_NOTAR)) return DBTYPE_OVM_NOTAR; + else if (val == QLatin1String(STR_OVM_EXEKUT)) return DBTYPE_OVM_EXEKUT; + else if (val == QLatin1String(STR_OVM_REQ)) return DBTYPE_OVM_REQ; + else if (val == QLatin1String(STR_OVM_FO)) return DBTYPE_OVM_FO; + else if (val == QLatin1String(STR_OVM_PFO)) return DBTYPE_OVM_PFO; + else if (val == QLatin1String(STR_OVM_PO)) return DBTYPE_OVM_PO; + else if (val == QLatin1String(STR_PO)) return DBTYPE_PO; + else if (val == QLatin1String(STR_PO_ZAK)) return DBTYPE_PO_ZAK; + else if (val == QLatin1String(STR_PO_REQ)) return DBTYPE_PO_REQ; + else if (val == QLatin1String(STR_PFO)) return DBTYPE_PFO; + else if (val == QLatin1String(STR_PFO_ADVOK)) return DBTYPE_PFO_ADVOK; + else if (val == QLatin1String(STR_PFO_DANPOR)) return DBTYPE_PFO_DANPOR; + else if (val == QLatin1String(STR_PFO_INSSPR)) return DBTYPE_PFO_INSSPR; + else if (val == QLatin1String(STR_PFO_AUDITOR)) return DBTYPE_PFO_AUDITOR; + else if (val == QLatin1String(STR_FO)) return DBTYPE_FO; + else { + logWarningNL("Unknown data box type '%s'.", + val.toUtf8().constData()); + return DBTYPE_SYSTEM; + } +} + +QString IsdsConversion::senderBoxTypeToText(int val) +{ + switch (val) { + case DBTYPE_SYSTEM: return tr("System ISDS"); break; + case DBTYPE_OVM: return tr("Public authority"); break; + case DBTYPE_PO: return tr("Legal person"); break; + case DBTYPE_PFO: return tr("Self-employed person"); break; /* (OSVC) */ + case DBTYPE_FO: return tr("Natural person"); break; + default: + logWarningNL("Unknown sender data box type value '%d'.", val); + return QString(); + break; + } +} + +QString IsdsConversion::dmTypeToText(const QString &val) +{ + if (val.size() != 1) { + logWarningNL("Unknown message type value '%s'.", + val.toUtf8().constData()); + return QString(); + } + + switch (val[0].toLatin1()) { + case 'K': + return tr("Postal data message"); + break; + case 'I': + return tr("Initialising postal data message"); + break; + case 'O': + return tr("Reply postal data message"); + break; + case 'X': + return tr("Initialising postal data message - expired"); + break; + case 'Y': + return tr("Initialising postal data message - used"); + break; + default: + logWarningNL("Unknown message type value '%c'.", + val[0].toLatin1()); + return QString(); + break; + } +} + +const QString &IsdsConversion::eventTypeToStr(int val) +{ + static const QString ev0("EV0"), ev1("EV1"), ev2("EV2"), ev3("EV3"), + ev4("EV4"), ev5("EV5"), ev11("EV11"), ev12("EV12"), ev13("EV13"); + static const QString invalid; + + switch (val) { + case EVENT_ACCEPTED_BY_RECIPIENT: return ev4; break; + case EVENT_ACCEPTED_BY_FICTION: return ev2; break; + case EVENT_UNDELIVERABLE: return ev3; break; + case EVENT_COMMERCIAL_ACCEPTED: return ev1; break; + case EVENT_ENTERED_SYSTEM: return ev0; break; + case EVENT_DELIVERED: return ev5; break; + case EVENT_PRIMARY_LOGIN: return ev11; break; + case EVENT_ENTRUSTED_LOGIN: return ev12; break; + case EVENT_SYSCERT_LOGIN: return ev13; break; + case EVENT_UKNOWN: + default: + logWarningNL("Unknown event type value '%d'.", val); + return invalid; + break; + } +} + +#define STR_MD5 "MD5" +#define STR_SHA_1 "SHA-1" +#define STR_SHA_224 "SHA-224" +#define STR_SHA_256 "SHA-256" +#define STR_SHA_384 "SHA-384" +#define STR_SHA_512 "SHA-512" + +const QString &IsdsConversion::hashAlgToStr(int val) +{ + static const QString md5(STR_MD5), sha1(STR_SHA_1), sha224(STR_SHA_224), + sha256(STR_SHA_256), sha384(STR_SHA_384), sha512(STR_SHA_512); + static const QString invalid; + + switch (val) { + case HASH_ALGORITHM_MD5: return md5; break; + case HASH_ALGORITHM_SHA_1: return sha1; break; + case HASH_ALGORITHM_SHA_224: return sha224; break; + case HASH_ALGORITHM_SHA_256: return sha256; break; + case HASH_ALGORITHM_SHA_384: return sha384; break; + case HASH_ALGORITHM_SHA_512: return sha512; break; + default: + logWarningNL("Unknown hash algorithm value '%d'.", val); + return invalid; + break; + } +} + +int IsdsConversion::hashAlgStrToInt(const QString &val) +{ + if (val == QLatin1String(STR_MD5)) return HASH_ALGORITHM_MD5; + else if (val == QLatin1String(STR_SHA_1)) return HASH_ALGORITHM_SHA_1; + else if (val == QLatin1String(STR_SHA_224)) return HASH_ALGORITHM_SHA_224; + else if (val == QLatin1String(STR_SHA_256)) return HASH_ALGORITHM_SHA_256; + else if (val == QLatin1String(STR_SHA_384)) return HASH_ALGORITHM_SHA_384; + else if (val == QLatin1String(STR_SHA_512)) return HASH_ALGORITHM_SHA_512; + else { + logWarningNL("Unknown hash algorithm '%s'.", + val.toUtf8().constData()); + return HASH_ALGORITHM_MD5; + } +} + +int IsdsConversion::msgStatusIsdsToDbRepr(int val) +{ + switch (val) { + case MESSAGESTATE_SENT: return 1; break; + case MESSAGESTATE_STAMPED: return 2; break; + case MESSAGESTATE_INFECTED: return 3; break; + case MESSAGESTATE_DELIVERED: return 4; break; + case MESSAGESTATE_SUBSTITUTED: return 5; break; + case MESSAGESTATE_RECEIVED: return 6; break; + case MESSAGESTATE_READ: return 7; break; + case MESSAGESTATE_UNDELIVERABLE: return 8; break; + case MESSAGESTATE_REMOVED: return 9; break; + case MESSAGESTATE_IN_SAFE: return 10; break; + default: + logWarningNL("Unknown message state value '%d'.", val); + return 0; + break; + } +} + +QString IsdsConversion::msgStatusDbToText(int val) +{ + switch (val) { + case 1: + /* Zprava byla podana (vznikla v ISDS). */ + return tr("Message has been submitted (has been created in ISDS)"); + break; + case 2: + /* + * Datová zprava vcetne pisemnosti podepsana casovym razitkem. + */ + return tr("Data message including its attachments signed with time-stamp."); + break; + case 3: + /* + * Zprava neprosla AV kontrolou; nakazena pisemnost je smazana; + * konecny stav zpravy pred smazanim. + */ + return tr("Message did not pass through AV check; " + "infected paper deleted; final status before deletion."); + break; + case 4: + /* Zprava dodana do ISDS (zapsan cas dodani). */ + return tr("Message handed into ISDS (delivery time recorded)."); + break; + case 5: + /* + * Uplynulo 10 dnu od dodani verejne zpravy, ktera dosud nebyla + * dorucena prihlasenim (predpoklad dorucení fikci u neOVM DS); + * u komercni zpravy nemuze tento stav nastat. + */ + return tr("10 days have passed since the delivery of " + "the public message which has not been accepted by " + "logging-in (assumption of acceptance through fiction in non-OVM " + "DS); this state cannot occur for commercial messages."); + break; + case 6: + /* + * Osoba opravnena cist tuto zpravu se prihlasila - dodana + * zprava byla dorucena.", + */ + return tr("A person authorised to read this message " + "has logged in -- delivered message has been accepted."); + break; + case 7: + /* Zprava byla prectena (na portale nebo akci ESS). */ + return tr("Message has been read (on the portal or by ESS action)."); + break; + case 8: + /* + * Zprava byla oznacena jako nedorucitelna, protoze DS adresata + * byla zpetne znepristupnena. + */ + return tr("Message marked as undeliverable because " + "the target DS has been made inaccessible."); + break; + case 9: + /* + * Obsah zpravy byl smazan, obalka zpravy vcetne hashu + * presunuta do archivu. + */ + return tr("Message content deleted, envelope " + "including hashes has been moved into archive."); + break; + case 10: + /* Zprava je v Datovem trezoru. */ + return tr("Message resides in data vault."); + break; + default: + logWarningNL("Unknown message state value '%d'.", val); + return QString(); + break; + } +} + +#define STR_PRIMARY_USER "PRIMARY_USER" +#define STR_ENTRUSTED_USER "ENTRUSTED_USER" +#define STR_ADMINISTRATOR "ADMINISTRATOR" +#define STR_OFFICIAL "OFFICIAL" +#define STR_VIRTUAL "VIRTUAL" +#define STR_OFFICIAL_CERT "OFFICIAL_CERT" +#define STR_LIQUIDATOR "LIQUIDATOR" +#define STR_RECEIVER "RECEIVER" +#define STR_GUARDIAN "GUARDIAN" + +const QString &IsdsConversion::senderTypeToStr(int val) +{ + static const QString pu(STR_PRIMARY_USER), eu(STR_ENTRUSTED_USER), + a(STR_ADMINISTRATOR), o(STR_OFFICIAL), v(STR_VIRTUAL), + oc(STR_OFFICIAL_CERT), l(STR_LIQUIDATOR), r(STR_RECEIVER), + g(STR_GUARDIAN); + static const QString invalid; + + switch (val) { + case SENDERTYPE_PRIMARY: return pu; break; + case SENDERTYPE_ENTRUSTED: return eu; break; + case SENDERTYPE_ADMINISTRATOR: return a; break; + case SENDERTYPE_OFFICIAL: return o; break; + case SENDERTYPE_VIRTUAL: return v; break; + case SENDERTYPE_OFFICIAL_CERT: return oc; break; + case SENDERTYPE_LIQUIDATOR: return l; break; + case SENDERTYPE_RECEIVER: return r; break; + case SENDERTYPE_GUARDIAN: return g; break; + default: + logWarningNL("Unknown sender type value '%d'.", val); + return invalid; + break; + } +} + +QString IsdsConversion::senderTypeStrToText(const QString &val) +{ + if (val == QLatin1String(STR_PRIMARY_USER)) { + /* Opravnena osoba nebo likvidator. */ + return tr("Primary user"); + } else if (val == QLatin1String(STR_ENTRUSTED_USER)) { + /* Poverena osoba. */ + return tr("Entrusted user"); + } else if (val == QLatin1String(STR_ADMINISTRATOR)) { + /* Systemove DZ. */ + return tr("Administrator"); + } else if (val == QLatin1String(STR_OFFICIAL)) { + /* Systemove DZ. */ + return tr("Official"); + } else if (val == QLatin1String(STR_VIRTUAL)) { + /* Spisovka. */ + return tr("Virtual"); + } else if (val == QLatin1String(STR_OFFICIAL_CERT)) { + return tr("???"); + } else if (val == QLatin1String(STR_LIQUIDATOR)) { + return tr("Liquidator"); + } else if (val == QLatin1String(STR_RECEIVER)) { + return tr("Receiver"); + } else if (val == QLatin1String(STR_GUARDIAN)) { + return tr("Guardian"); + } else { + logWarningNL("Unknown author type '%s'.", + val.toUtf8().constData()); + return QString(); + } +} + +const QString &IsdsConversion::userTypeToStr(int val) +{ + static const QString pu(STR_PRIMARY_USER), eu(STR_ENTRUSTED_USER), + a(STR_ADMINISTRATOR), l(STR_LIQUIDATOR), ou("OFFICIAL_USER"), + ocu("OFFICIAL_CERT_USER"), r(STR_RECEIVER), g(STR_GUARDIAN); + static const QString invalid; + + switch (val) { + case USERTYPE_PRIMARY: return pu; break; + case USERTYPE_ENTRUSTED: return eu; break; + case USERTYPE_ADMINISTRATOR: return a; break; + case USERTYPE_LIQUIDATOR: return l; break; + case USERTYPE_OFFICIAL: return ou; break; + case USERTYPE_OFFICIAL_CERT: return ocu; break; + case USERTYPE_RECEIVER: return r; break; + case USERTYPE_GUARDIAN: return g; break; + default: + logWarningNL("Unknown user type value '%d'.", val); + return invalid; + break; + } +} + +QString IsdsConversion::userPrivilsToText(int val) +{ + QString privStr; + const QString sepPref("
  • - "), sepSuff("
  • "); + + if (val == 255) { + return tr("Full control"); + } else { + privStr = tr("Restricted control"); + } + + if (val & PRIVIL_READ_NON_PERSONAL) { + // "stahovat a číst došlé DZ" + privStr += sepPref + tr("download and read incoming DM") + + sepSuff; + } + if (val & PRIVIL_READ_ALL) { + // "stahovat a číst DZ určené do vlastních rukou" + privStr += sepPref + + tr("download and read DM sent into own hands") + sepSuff; + } + if (val & PRIVIL_CREATE_DM) { + // "vytvářet a odesílat DZ, stahovat odeslané DZ" + privStr += sepPref + + tr("create and send DM, download sent DM") + sepSuff; + } + if (val & PRIVIL_VIEW_INFO) { + // "načítat seznamy DZ, Dodejky a Doručenky" + privStr += sepPref + + tr("retrieve DM lists, delivery and acceptance reports") + + sepSuff; + } + if (val & PRIVIL_SEARCH_DB) { + // "vyhledávat DS" + privStr += sepPref + tr("search for data boxes") + sepSuff; + } + if (val & PRIVIL_OWNER_ADM) { + // "spravovat DS" + privStr += sepPref + tr("manage the data box") + sepSuff; + } + if (val & PRIVIL_READ_VAULT) { + // "číst zprávy v DT" + privStr += sepPref + tr("read message in data vault") + sepSuff; + } + if (val & PRIVIL_ERASE_VAULT) { + // "mazat zprávy v DT" + privStr += sepPref + tr("erase messages from data vault") + + sepSuff; + } + return privStr; +} diff -Nru datovka-4.8.3/src/isds/isds_conversion.h datovka-4.9.3/src/isds/isds_conversion.h --- datovka-4.8.3/src/isds/isds_conversion.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/isds/isds_conversion.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _ISDS_CONVERSION_H_ +#define _ISDS_CONVERSION_H_ + +#include // Q_DECLARE_TR_FUNCTIONS +#include + +/*! + * @brief Provides conversion functions for ISDS types. + */ +class IsdsConversion { + Q_DECLARE_TR_FUNCTIONS(IsdsConversion) + +private: + /*! + * @brief Private constructor. + */ + IsdsConversion(void); + +public: + /*! + * @brief Return attachment type as string. + * + * @param[in] val Attachment type value as used by libisds. + * @return Attachment type description. + */ + static + const QString &attachmentTypeToStr(int val); + + /*! + * @brief Convert data box state to localised text + * + * @param[in] val Data box status value as used by libisds. + * @return Data box status description string. + */ + static + QString boxStateToText(int val); + + /*! + * @brief Convert data box type to string. + * + * @param[in] val Data box type value as used by libisds. + * @return Data box type description. + */ + static + const QString &boxTypeToStr(int val); + + /*! + * @brief Convert data box type string to int as used by libisds. + * + * @param[in] val Data box type string. + * @return Data box type integer value. + */ + static + int boxTypeStrToInt(const QString &val); + + /*! + * @brief Return localised sender data box type description string. + * + * @param[in] val Sender data box type value as used by libisds. + * @return Sender data box type description. + */ + static + QString senderBoxTypeToText(int val); + + /*! + * @brief Translates message type to localised text. + * + * @param[in] val Message type value as used by libisds. + * @return Message type description. + */ + static + QString dmTypeToText(const QString &val); + + /*! + * @brief Convert event type to string. + * + * @param[in] val Event type value as used by libisds. + * @return Event string (not the description). + */ + static + const QString &eventTypeToStr(int val); + + /*! + * @brief Return hash algorithm string identifier. + * + * @param[in] val Hash algorithm value as used by libisds. + * @return Hash algorithm type string. + */ + static + const QString &hashAlgToStr(int val); + + /*! + * @brief Converts hash algorithm type string to int as used by libisds. + * + * @param[in] val Hash algorithm string. + * @return Hash algorithm type integer value. + */ + static + int hashAlgStrToInt(const QString &val); + + /*! + * @brief Converts libisds message state to database value as used by + * Datovka. + * + * @param[in] val Message status value as used by libisds. + * @return Datovka status value as stored in database. + */ + static + int msgStatusIsdsToDbRepr(int val); + + /*! + * @brief Returns localised message status description text. + * + * @param[in] val Message status value as used in database. + * @return Localised message status description. + */ + static + QString msgStatusDbToText(int val); + + /*! + * @brief Convert sender type to string identifier. + * + * @param[in] val Sender type value as used by libisds. + * @return Sender type string identifier. + */ + static + const QString &senderTypeToStr(int val); + + /*! + * @brief Translates sender type string to localised text. + * + * @param[in] val Sender type string. + * @return Sender type description. + */ + static + QString senderTypeStrToText(const QString &val); + + /*! + * @brief Convert type of user to string. + * + * @param[in] val User type value as used by libisds. + * @return User type string. + */ + static + const QString &userTypeToStr(int val); + + /*! + * @brief Return privileges as html string from number representation. + * + * @param[in] val Privilege value flags. + * @return Privilege description. + */ + static + QString userPrivilsToText(int val); +}; + +#endif /* _ISDS_CONVERSION_H_ */ diff -Nru datovka-4.8.3/src/log/log.cpp datovka-4.9.3/src/log/log.cpp --- datovka-4.8.3/src/log/log.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/log/log.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,6 @@ * the two. */ - #include #include /* NULL */ #include @@ -33,26 +32,18 @@ #include #include -#include "log.h" - +#include "src/log/log.h" #define LOG_TIME_FMT "MMM dd hh:mm:ss" +LogDevice globLog; -GlobLog globLog; - - -/* ========================================================================= */ -/* - * Message output function. - */ void globalLogOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) -/* ========================================================================= */ { QByteArray localMsg = msg.toLocal8Bit(); QString dateTime = QDateTime::currentDateTime().toString(LOG_TIME_FMT); - uint8_t level = GlobLog::levelFromType(type); + uint8_t level = LogDevice::levelFromType(type); switch (type) { case QtDebugMsg: @@ -84,13 +75,7 @@ } } - -/* ========================================================================= */ -/* - * Debugging using Qt-defined output. - */ void qDebugCall(const char *fmt, ...) -/* ========================================================================= */ { va_list argp; @@ -104,13 +89,7 @@ va_end(argp); } - -/* ========================================================================= */ -/* - * Debugging using Qt-defined output. - */ void qDebugCallV(const char *fmt, va_list ap) -/* ========================================================================= */ { QString outStr; outStr.vsprintf(fmt, ap); @@ -118,7 +97,6 @@ qDebug("%s", outStr.toUtf8().constData()); } - /*! * @brief A convenience macro for getting levels for a given facility * and source. @@ -126,13 +104,7 @@ #define facilityLevels(facility, source) \ facDescVect[(facility)].levels[(source)] - -/* ========================================================================= */ -/* - * Constructor. - */ -GlobLog::GlobLog(void) -/* ========================================================================= */ +LogDevice::LogDevice(void) : m_mutex(), m_hostName(QHostInfo::localHostName()), m_logVerbosity(0), @@ -150,13 +122,7 @@ /* TODO -- Initialise syslog. */ } - -/* ========================================================================= */ -/* - * Destructor. - */ -GlobLog::~GlobLog(void) -/* ========================================================================= */ +LogDevice::~LogDevice(void) { /* TODO -- De-initialise syslog. */ @@ -167,13 +133,7 @@ } } - -/* ========================================================================= */ -/* - * Get log verbosity. - */ -int GlobLog::logVerbosity(void) -/* ========================================================================= */ +int LogDevice::logVerbosity(void) { int ret; @@ -186,13 +146,7 @@ return ret; } - -/* ========================================================================= */ -/* - * Set log verbosity. - */ -void GlobLog::setLogVerbosity(int verb) -/* ========================================================================= */ +void LogDevice::setLogVerbosity(int verb) { m_mutex.lock(); @@ -207,13 +161,7 @@ m_mutex.unlock(); } - -/* ========================================================================= */ -/* - * Get debug verbosity. - */ -int GlobLog::debugVerbosity(void) -/* ========================================================================= */ +int LogDevice::debugVerbosity(void) { int ret; @@ -226,13 +174,7 @@ return ret; } - -/* ========================================================================= */ -/* - * Set debug verbosity. - */ -void GlobLog::setDebugVerbosity(int verb) -/* ========================================================================= */ +void LogDevice::setDebugVerbosity(int verb) { m_mutex.lock(); @@ -241,13 +183,7 @@ m_mutex.unlock(); } - -/* ========================================================================= */ -/* - * Opens a log file as a logging facility. - */ -int GlobLog::openFile(const QString &fName, LogMode mode) -/* ========================================================================= */ +int LogDevice::openFile(const QString &fName, LogMode mode) { FILE *of; const char *openMode; @@ -295,13 +231,7 @@ return -1; } - -/* ========================================================================= */ -/* - * Returns the log levels for the given facility and source. - */ -uint8_t GlobLog::logLevels(int facility, int source) -/* ========================================================================= */ +uint8_t LogDevice::logLevels(int facility, int source) { uint8_t ret; @@ -317,13 +247,7 @@ return ret; } - -/* ========================================================================= */ -/* - * Sets the log levels for the selected facility and source. - */ -void GlobLog::setLogLevels(int facility, int source, uint8_t levels) -/* ========================================================================= */ +void LogDevice::setLogLevels(int facility, int source, uint8_t levels) { Q_ASSERT((facility >= 0) && (facility < MAX_LOG_FILES)); Q_ASSERT((source >= -1) && (source < MAX_SOURCES)); @@ -341,13 +265,7 @@ m_mutex.unlock(); } - -/* ========================================================================= */ -/* - * Add log levels to the selected facility and source. - */ -void GlobLog::addLogLevels(int facility, int source, uint8_t levels) -/* ========================================================================= */ +void LogDevice::addLogLevels(int facility, int source, uint8_t levels) { int i; @@ -367,13 +285,7 @@ m_mutex.unlock(); } - -/* ========================================================================= */ -/* - * Returns the id of a new unique source that can be used. - */ -int GlobLog::acquireUniqueLogSource(void) -/* ========================================================================= */ +int LogDevice::acquireUniqueLogSource(void) { int ret; @@ -391,13 +303,7 @@ return ret; } - -/* ========================================================================= */ -/* - * Log message. - */ -int GlobLog::log(int source, uint8_t level, const char *fmt, ...) -/* ========================================================================= */ +int LogDevice::log(int source, uint8_t level, const char *fmt, ...) { const char *prefix; va_list argp; @@ -423,13 +329,7 @@ return 0; } - -/* ========================================================================= */ -/* - * Log message. - */ -int GlobLog::logVlog(int source, uint8_t level, const char *fmt, va_list ap) -/* ========================================================================= */ +int LogDevice::logVlog(int source, uint8_t level, const char *fmt, va_list ap) { const char *prefix; @@ -450,13 +350,7 @@ return 0; } - -/* ========================================================================= */ -/* - * Log multi-line message. - */ -int GlobLog::logMl(int source, uint8_t level, const char *fmt, ...) -/* ========================================================================= */ +int LogDevice::logMl(int source, uint8_t level, const char *fmt, ...) { const char *prefix; va_list argp; @@ -482,13 +376,7 @@ return 0; } - -/* ========================================================================= */ -/* - * Log multi-line message. - */ -int GlobLog::logVlogMl(int source, uint8_t level, const char *fmt, va_list ap) -/* ========================================================================= */ +int LogDevice::logVlogMl(int source, uint8_t level, const char *fmt, va_list ap) { const char *prefix; @@ -509,13 +397,7 @@ return 0; } - -/* ========================================================================= */ -/* - * Returns a string containing log urgency prefix. - */ -const char * GlobLog::urgencyPrefix(uint8_t level) -/* ========================================================================= */ +const char *LogDevice::urgencyPrefix(uint8_t level) { const char *prefix; @@ -528,19 +410,13 @@ case LOG_NOTICE : prefix = "notice: "; break; case LOG_INFO : prefix = "info: "; break; case LOG_DEBUG : prefix = "debug: "; break; - default : prefix = NULL; + default : prefix = NULL; break; } return prefix; } - -/* ========================================================================= */ -/* - * converts message type to urgency level. - */ -uint8_t GlobLog::levelFromType(QtMsgType type) -/* ========================================================================= */ +uint8_t LogDevice::levelFromType(QtMsgType type) { switch (type) { case QtDebugMsg: @@ -567,14 +443,8 @@ } } - -/* ========================================================================= */ -/* - * Log message. - */ -void GlobLog::logPrefixVlog(int source, uint8_t level, +void LogDevice::logPrefixVlog(int source, uint8_t level, const char *prefix, const char *format, va_list ap) -/* ========================================================================= */ { uint8_t logMask; int i; @@ -647,14 +517,8 @@ } } - -/* ========================================================================= */ -/* - * Log multi-line message. - */ -void GlobLog::logPrefixVlogMl(int source, uint8_t level, +void LogDevice::logPrefixVlogMl(int source, uint8_t level, const char *prefix, const char *format, va_list ap) -/* ========================================================================= */ { uint8_t logMask; int i; diff -Nru datovka-4.8.3/src/log/log.h datovka-4.9.3/src/log/log.h --- datovka-4.8.3/src/log/log.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/log/log.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,25 +21,25 @@ * the two. */ - #ifndef _LOG_H_ #define _LOG_H_ - #include #include #include #include "src/log/log_common.h" - /*! * @brief Message output function. + * + * @param[in] type Type of message sent to message handler. + * @param[in] context Additional information about a log message. + * @param[in] msg Message to be handled. */ void globalLogOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg); - /*! * @brief Debugging using Qt-defined output. * @@ -47,15 +47,14 @@ */ void qDebugCall(const char *fmt, ...); - /*! * @brief Debugging using Qt-defined output. * * @param[in] fmt Format string. + * @param[in,out] ap Variable arguments list. */ void qDebugCallV(const char *fmt, va_list ap); - /*! * @brief Generates location debug information. */ @@ -70,7 +69,6 @@ # define debugSlotCall() do {} while(0) #endif - /*! * @brief Generates location debug information. */ @@ -85,23 +83,20 @@ # define debugFuncCall() do {} while(0) #endif - /*! * @brief Maximal number of simultaneously opened files. */ #define MAX_LOG_FILES 64 - /*! * @brief Maximal number of sources to write to log facility. */ #define MAX_SOURCES 64 - /*! - * @brief Global logger class. + * @brief Logging device class. */ -class GlobLog { +class LogDevice { public: enum LogFac { LF_SYSLOG = 0, /*!< @brief Syslog facility. */ @@ -120,8 +115,8 @@ FILE *fout; /*!< Output file. */ }; - GlobLog(void); - ~GlobLog(void); + LogDevice(void); + ~LogDevice(void); /*! * @brief Get log verbosity. @@ -267,7 +262,7 @@ * @brief Converts log level to urgency prefix. */ static - const char * urgencyPrefix(uint8_t level); + const char *urgencyPrefix(uint8_t level); /*! * @brief converts message type to urgency level. @@ -307,8 +302,7 @@ const char *prefix, const char *format, va_list ap); }; - -extern GlobLog globLog; /*!< Global log facility. */ +extern LogDevice globLog; /*!< Global log facility. */ /*! * @brief Logging macro used for internal purposes. @@ -353,7 +347,6 @@ (void) 0 #endif /* DEBUG */ - /*! * @brief Logs the debugging information even if the threshold was not set. * @@ -363,7 +356,6 @@ #define logDebugLv0NL(format, ...) \ logDebugNL(-1, format, __VA_ARGS__) - /*! * @brief Logs the debugging information only if the verbosity exceeds 0. * @@ -373,7 +365,6 @@ #define logDebugLv1NL(format, ...) \ logDebugNL(0, format, __VA_ARGS__) - /*! * @brief Logs the debugging information only if the verbosity exceeds 1. * @@ -383,7 +374,6 @@ #define logDebugLv2NL(format, ...) \ logDebugNL(1, format, __VA_ARGS__) - /*! * @brief Logs the debugging information only if the verbosity exceeds 2. * @@ -393,7 +383,6 @@ #define logDebugLv3NL(format, ...) \ logDebugNL(2, format, __VA_ARGS__) - /*! * @brief Logs multi-line debugging message. * @@ -408,7 +397,6 @@ } \ } while (0) - /*! * @brief Logs the debugging information even if the threshold was not set. * @@ -418,7 +406,6 @@ #define logDebugMlLv0(format, ...) \ logDebugMl(-1, format, __VA_ARGS__) - /*! * @brief Logs the debugging information only if the verbosity exceeds 0. * @@ -428,7 +415,6 @@ #define logDebugMlLv1(format, ...) \ logDebugMl(0, format, __VA_ARGS__) - /*! * @brief Logs the debugging information only if the verbosity exceeds 1. * @@ -438,7 +424,6 @@ #define logDebugMlLv2(format, ...) \ logDebugMl(1, format, __VA_ARGS__) - /*! * @brief Logs the debugging information only if the verbosity exceeds 2. * @@ -448,7 +433,6 @@ #define logDebugMlLv3(format, ...) \ logDebugMl(2, format, __VA_ARGS__) - /*! * @brief Logs information message. * @@ -480,7 +464,6 @@ globLog.logMl(LOGSRC_DEF, LOG_INFO, format, __VA_ARGS__); \ } while (0) - /*! * @brief Logs warning message. * @@ -512,7 +495,6 @@ globLog.logMl(LOGSRC_DEF, LOG_WARNING, format, __VA_ARGS__); \ } while (0) - /*! * @brief Logs error message. * @@ -524,7 +506,6 @@ globLog.log(LOGSRC_DEF, LOG_ERR, format, __VA_ARGS__); \ } while (0) - /*! * @brief Logs error message. Automatic newline is added. * @@ -545,5 +526,4 @@ globLog.logMl(LOGSRC_DEF, LOG_ERR, format, __VA_ARGS__); \ } while (0) - #endif /* _LOG_H_ */ diff -Nru datovka-4.8.3/src/main_cli.cpp datovka-4.9.3/src/main_cli.cpp --- datovka-4.8.3/src/main_cli.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/main_cli.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include +#include /* qsrand() */ +#include + +#include "src/about.h" +#include "src/cli/cli_parser.h" +#include "src/crypto/crypto_funcs.h" +#include "src/crypto/crypto_threads.h" +#include "src/initialisation.h" +#include "src/io/db_tables.h" +#include "src/io/filesystem.h" +#include "src/io/sqlite/db.h" +#include "src/log/log.h" +#include "src/settings/accounts.h" +#include "src/settings/proxy.h" +#include "src/single/single_instance.h" +#include "src/worker/pool.h" + +int main(int argc, char *argv[]) +{ + /* Set random generator. */ + qsrand(QDateTime::currentDateTime().toTime_t()); + + /* Log warnings. */ + globLog.setLogLevels(LogDevice::LF_STDERR, LOGSRC_ANY, + LOG_UPTO(LOG_WARNING)); + + setDefaultLocale(); + + /* TODO -- Make the following assignments configurable. */ + QCoreApplication::setApplicationName("Datovka CLI"); + QCoreApplication::setApplicationVersion(VERSION " -- [" + + libraryDependencies().join("; ") + "]"); + + qInstallMessageHandler(globalLogOutput); + + QCoreApplication app(argc, argv); + + QCommandLineParser parser; + if (0 != CLIParser::setupCmdLineParser(parser)) { + logErrorNL("%s", "Cannot set up command-line parser."); + return EXIT_FAILURE; + } + + /* Process command-line arguments. */ + parser.process(app); + + if (0 != preferencesSetUp(parser, globPref, globLog)) { + logErrorNL("%s", + "Cannot apply command line arguments on global settings."); + return EXIT_FAILURE; + } + + const QStringList srvcArgs( + CLIParser::CLIServiceArgs(parser.optionNames())); + if (srvcArgs.isEmpty()) { + logErrorNL("%s", + "No command line arguments supplied. Exiting."); + return EXIT_FAILURE; + } + + /* Ensure only one instance with given configuration file. */ + SingleInstance singleInstance(globPref.loadConfPath()); + if (singleInstance.existsInSystem()) { + logErrorNL("%s", + "Another application already uses same configuration. Exiting."); + return EXIT_FAILURE; + } + + qint64 start, stop, diff; + start = QDateTime::currentMSecsSinceEpoch(); + logInfo("Starting at %lld.%03lld .\n", start / 1000, start % 1000); + + /* Create configuration file is file is missing. */ + GlobPreferences::ensureConfPresence(); + + if (0 != crypto_init()) { + logError("%s\n", "Cannot load cryptographic back-end."); + /* + * TODO -- the function should fail only when all certificates + * failed to load. + */ + return EXIT_FAILURE; + } + crypto_init_threads(); + + { + /* Stuff related to configuration file. */ + + logDebugLv0NL("Load: '%s'.", + globPref.loadConfPath().toUtf8().constData()); + logDebugLv0NL("Save: '%s'.", + globPref.saveConfPath().toUtf8().constData()); + + /* Change "\" to "/" */ + confFileFixBackSlashes(globPref.loadConfPath()); + } + + /* Set up proxy. */ + { + QSettings settings(globPref.loadConfPath(), + QSettings::IniFormat); + settings.setIniCodec("UTF-8"); + /* Load proxy settings. */ + globProxSet.loadFromSettings(settings); + /* Apply settings onto the environment because of libcurl. */ + globProxSet.setProxyEnvVars(); + } + + /* Start downloading the CRL files. */ + downloadCRL(); + + if (!SQLiteDb::dbDriverSupport()) { + logError("Cannot load database driver '%s'.\n", + SQLiteDb::dbDriverType.toUtf8().constData()); + /* TODO -- throw a dialog notifying the user. */ + return EXIT_FAILURE; + } + + logDebugLv0NL("CLI main thread: %p.", QThread::currentThreadId()); + + logDebugLv0NL("App path: '%s'.", + app.applicationDirPath().toUtf8().constData()); + + loadLocalisation(globPref); + + /* Localise description in tables. */ + localiseTableDescriptions(); + + if (0 != allocateGlobalObjects(globPref)) { + return EXIT_FAILURE; + } + + int ret = EXIT_SUCCESS; + + /* Parse account information. */ + { + QSettings settings(globPref.loadConfPath(), + QSettings::IniFormat); + settings.setIniCodec("UTF-8"); + globAccounts.loadFromSettings(settings); + } + + /* Start worker threads. */ + globWorkPool.start(); + logInfo("%s\n", "Worker pool started."); + + ret = CLIParser::runCLIService(srvcArgs, parser); + + /* Wait until all threads finished. */ + logInfo("%s\n", "Waiting for pending worker threads."); + globWorkPool.wait(); + globWorkPool.stop(); + logInfo("%s\n", "All worker threads finished"); + + stop = QDateTime::currentMSecsSinceEpoch(); + diff = stop - start; + logInfo("Stopping at %lld.%03lld; ran for %lld.%03lld seconds.\n", + stop / 1000, stop % 1000, diff / 1000, diff % 1000); + + /* + * TODO -- The following clean-up function causes troubles. + * on OS X libcurl occasionally seems to operate while the lock + * de-initialisation is performed causing the application to crash + * on exit. + */ + //crypto_cleanup_threads(); + + deallocateGlobalObjects(); + + return ret; +} diff -Nru datovka-4.8.3/src/main.cpp datovka-4.9.3/src/main.cpp --- datovka-4.8.3/src/main.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/main.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -21,116 +21,52 @@ * the two. */ - -#ifndef WIN32 -#include -#endif /* !WIN32 */ #include #include #include -#include -#include +#include +#include +#include /* qsrand() */ +#include -#include "src/cli/cli.h" -#include "src/crypto/crypto.h" -#include "src/crypto/crypto_threads.h" +#include "src/about.h" +#include "src/cli/cli_parser.h" #include "src/crypto/crypto_funcs.h" +#include "src/crypto/crypto_threads.h" #include "src/gui/datovka.h" -#include "src/gui/dlg_about.h" #include "src/gui/dlg_view_zfo.h" +#include "src/initialisation.h" #include "src/io/db_tables.h" -#include "src/io/file_downloader.h" #include "src/io/filesystem.h" -#include "src/io/message_db_set_container.h" -#include "src/io/tag_db.h" -#include "src/io/tag_db_container.h" #include "src/io/sqlite/db.h" -#include "src/localisation/localisation.h" #include "src/log/log.h" -#include "src/models/accounts_model.h" +#include "src/settings/accounts.h" #include "src/settings/proxy.h" #include "src/single/single_instance.h" #include "src/worker/pool.h" -#define CONF_SUBDIR_OPT "conf-subdir" -#define LOAD_CONF_OPT "load-conf" -#define SAVE_CONF_OPT "save-conf" -#define LOG_FILE "log-file" - -#define LOG_VERBOSITY_OPT "log-verbosity" -#define DEBUG_OPT "debug" -#define DEBUG_VERBOSITY_OPT "debug-verbosity" - -#define RUN_MODE_GUI 0 -#define RUN_MODE_CLI 1 -#define RUN_MODE_ZFO 2 - -/* ========================================================================= */ -static -int doCLI(const QStringList &serList, const QCommandLineParser &parser) -/* ========================================================================= */ -{ - int ret = CLI_EXIT_ERROR; - QString errmsg; - QString serName; - int index = 0; - QTextStream cout(stderr); - - // every valid CLI action must have only one login parameter - // or one login parameter and one name service - switch (serList.count()) { - case 0: - errmsg = "No service has been defined for CLI action!"; - break; - case 1: - if (serList.contains(SER_LOGIN)) { - ret = runService(parser.value(SER_LOGIN), - NULL, NULL); - return ret; - } else { - errmsg = "Only service name was set. " - "Login parameter is missing!"; - } - break; - case 2: - if (serList.contains(SER_LOGIN)) { - index = serList.indexOf(SER_LOGIN); - if (index == 0) { - serName = serList.at(1); - } else { - serName = serList.at(0); - } - ret = runService(parser.value(SER_LOGIN), - serName, parser.value(serName)); - return ret; - } else { - errmsg = "Login parameter is missing! " - "Maybe two service names were set."; - } - break; - default: - errmsg = "More than two service names or logins were set! " - "This situation is not allowed."; - break; - } - - // print error to stderr - cout << CLI_PREFIX << " error(" << CLI_ERROR << ") : " - << errmsg << endl; - - return ret; -} - -/* ========================================================================= */ +/*! + * @brief Specified the mode the executable is being executed with. + */ +enum RunMode { + RM_GUI, /*!< Start with active GUI. */ + RM_CLI, /*!< Execute command line service. */ + RM_ZFO /*!< View ZFO content. */ +}; + +/*! + * @brief View data message from ZFO file. + * + * @param[in] fileName ZFO file name. + */ static int showZfo(const QString &fileName) -/* ========================================================================= */ { if (fileName.isEmpty()) { return -1; } - QDialog *viewDialog = new DlgViewZfo(fileName, 0); + QDialog *viewDialog = new DlgViewZfo(fileName, Q_NULLPTR); viewDialog->exec(); delete viewDialog; @@ -138,289 +74,28 @@ return 0; } -/* ========================================================================= */ -static -int setupCmdLineParser(QCommandLineParser &parser) -/* ========================================================================= */ -{ - parser.setApplicationDescription(QObject::tr("Data box application")); - parser.addHelpOption(); - parser.addVersionOption(); - /* Options with values. */ - if (!parser.addOption(QCommandLineOption(CONF_SUBDIR_OPT, - QObject::tr( - "Use subdirectory for configuration."), - QObject::tr("conf-subdir")))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(LOAD_CONF_OPT, - QObject::tr("On start load file."), - QObject::tr("conf")))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(SAVE_CONF_OPT, - QObject::tr("On stop save file."), - QObject::tr("conf")))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(LOG_FILE, - QObject::tr("Log messages to ."), - QObject::tr("file")))) { - return -1; - } - QCommandLineOption logVerb(QStringList() << "L" << LOG_VERBOSITY_OPT, - QObject::tr("Set verbosity of logged messages to . " - "Default is ") + QString::number(globLog.logVerbosity()) + ".", - QObject::tr("level")); - if (!parser.addOption(logVerb)) { - return -1; - } - /* Boolean options. */ -#ifdef DEBUG - QCommandLineOption debugOpt(QStringList() << "D" << DEBUG_OPT, - "Enable debugging information."); - if (!parser.addOption(debugOpt)) { - return -1; - } - QCommandLineOption debugVerb(QStringList() << "V" << DEBUG_VERBOSITY_OPT, - QObject::tr("Set debugging verbosity to . Default is ") + - QString::number(globLog.debugVerbosity()) + ".", - QObject::tr("level")); - if (!parser.addOption(debugVerb)) { - return -1; - } -#endif /* DEBUG */ - - /* Options with values. */ - if (!parser.addOption(QCommandLineOption(SER_LOGIN, - QObject::tr("Service: connect to isds and login into databox."), - QObject::tr("string-of-parameters")))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(SER_GET_MSG_LIST, - QObject::tr("Service: download list of received/sent " - "messages from ISDS."), - QObject::tr("string-of-parameters")))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(SER_SEND_MSG, - QObject::tr("Service: create and send a new message to ISDS."), - QObject::tr("string-of-parameters")))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(SER_GET_MSG, - QObject::tr("Service: download complete message with " - "signature and time stamp of MV."), - QObject::tr("string-of-parameters")))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(SER_GET_DEL_INFO, - QObject::tr("Service: download acceptance info of message " - "with signature and time stamp of MV."), - QObject::tr("string-of-parameters")))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(SER_GET_USER_INFO, - QObject::tr("Service: get information about user " - "(role, privileges, ...)."), - NULL))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(SER_GET_OWNER_INFO, - QObject::tr("Service: get information about owner and " - "its databox."), - NULL))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(SER_CHECK_ATTACHMENT, - QObject::tr("Service: get list of messages where " - "attachment missing (local database only)."), - NULL))) { - return -1; - } - if (!parser.addOption(QCommandLineOption(SER_FIND_DATABOX, - QObject::tr("Service: find a databox via several parameters."), - QObject::tr("string-of-parameters")))) { - return -1; - } - - parser.addPositionalArgument("[zfo-file]", - QObject::tr("ZFO file to be viewed.")); - - return 0; -} - -/* ========================================================================= */ -static -int setupPreferences(const QCommandLineParser &parser, - GlobPreferences &prefs, GlobLog &log) -/* ========================================================================= */ -{ - int logFileId = -1; - - if (parser.isSet(CONF_SUBDIR_OPT)) { - prefs.confSubdir = parser.value(CONF_SUBDIR_OPT); - } - if (parser.isSet(LOAD_CONF_OPT)) { - prefs.loadFromConf = parser.value(LOAD_CONF_OPT); - } - if (parser.isSet(SAVE_CONF_OPT)) { - prefs.saveToConf = parser.value(SAVE_CONF_OPT); - } - if (parser.isSet(LOG_FILE)) { - QString logFileName = parser.value(LOG_FILE); - logFileId = log.openFile(logFileName.toUtf8().constData(), - GlobLog::LM_APPEND); - if (-1 == logFileId) { - logError("Cannot open log file '%s'.\n", - logFileName.toUtf8().constData()); - return -1; - } - /* Log warnings. */ - log.setLogLevels(logFileId, LOGSRC_ANY, - LOG_UPTO(LOG_WARNING)); - } -#ifdef DEBUG - if (parser.isSet(DEBUG_OPT) || parser.isSet(DEBUG_VERBOSITY_OPT)) { - log.setLogLevels(GlobLog::LF_STDERR, LOGSRC_ANY, - LOG_UPTO(LOG_DEBUG)); - if (-1 != logFileId) { - log.setLogLevels(logFileId, LOGSRC_ANY, - LOG_UPTO(LOG_DEBUG)); - } - } - if (parser.isSet(DEBUG_VERBOSITY_OPT)) { - bool ok; - int value = parser.value(DEBUG_VERBOSITY_OPT).toInt(&ok, 10); - if (!ok) { - logError("%s\n", "Invalid debug-verbosity parameter."); - exit(EXIT_FAILURE); - } - logInfo("Setting debugging verbosity to value '%d'.\n", value); - log.setDebugVerbosity(value); - } -#endif /* DEBUG */ - if (parser.isSet(LOG_VERBOSITY_OPT)) { - bool ok; - int value = parser.value(LOG_VERBOSITY_OPT).toInt(&ok, 10); - if (!ok) { - logError("%s\n", "Invalid log-verbosity parameter."); - exit(EXIT_FAILURE); - } - logInfo("Setting logging verbosity to value '%d'.\n", value); - log.setLogVerbosity(value); - } - - return 0; -} - -/* ========================================================================= */ -static -void loadLocalisation(QApplication &app) -/* ========================================================================= */ -{ - static QTranslator qtTranslator, appTranslator; - - QSettings settings(globPref.loadConfPath(), - QSettings::IniFormat); - settings.setIniCodec("UTF-8"); - - QString language = - settings.value("preferences/language").toString(); - - /* Check for application localisation location. */ - QString localisationDir; - QString localisationFile; - - - localisationDir = appLocalisationDir(); - - logInfo("Loading application localisation from path '%s'.\n", - localisationDir.toUtf8().constData()); - - localisationFile = "datovka_" + Localisation::shortLangName(language); - - Localisation::setProgramLocale(language); - - if (!appTranslator.load(localisationFile, localisationDir)) { - logWarning("Could not load localisation file '%s' " - "from directory '%s'.\n", - localisationFile.toUtf8().constData(), - localisationDir.toUtf8().constData()); - } - - app.installTranslator(&appTranslator); - - - localisationDir = qtLocalisationDir(); - - logInfo("Loading Qt localisation from path '%s'.\n", - localisationDir.toUtf8().constData()); - - { - const QString langName(Localisation::shortLangName(language)); - if (langName != Localisation::langEn) { - localisationFile = - "qtbase_" + Localisation::shortLangName(language); - } else { - localisationFile = QString(); - } - } - - if (!localisationFile.isEmpty() && - !qtTranslator.load(localisationFile, localisationDir)) { - logWarning("Could not load localisation file '%s' " - "from directory '%s'.\n", - localisationFile.toUtf8().constData(), - localisationDir.toUtf8().constData()); - } - - app.installTranslator(&qtTranslator); -} - -/* ========================================================================= */ -/* ========================================================================= */ int main(int argc, char *argv[]) -/* ========================================================================= */ -/* ========================================================================= */ { /* Set random generator. */ qsrand(QDateTime::currentDateTime().toTime_t()); /* Log warnings. */ - globLog.setLogLevels(GlobLog::LF_STDERR, LOGSRC_ANY, + globLog.setLogLevels(LogDevice::LF_STDERR, LOGSRC_ANY, LOG_UPTO(LOG_WARNING)); -#ifndef WIN32 - { - QProcessEnvironment env = - QProcessEnvironment::systemEnvironment(); - QString lang = env.value("LANG"); - if (lang.isEmpty() || ("c" == lang.toLower())) { -#define LANG_DEF "en_GB.UTF-8" - logWarning("The LANG environment variable " - "is missing or unset. Setting to '%s'.\n", - LANG_DEF); - if (NULL == setlocale(LC_ALL, LANG_DEF)) { - logError("Setting locale to '%s' failed.\n", - LANG_DEF); - } -#undef LANG_DEF - } - } -#endif /* !WIN32 */ + setDefaultLocale(); /* TODO -- Make the following assignments configurable. */ QCoreApplication::setApplicationName("Datovka"); QCoreApplication::setApplicationVersion(VERSION " -- [" + - DlgAbout::libraryDependencies().join("; ") + "]"); + libraryDependencies().join("; ") + "]"); qInstallMessageHandler(globalLogOutput); QApplication app(argc, argv); QCommandLineParser parser; - if (0 != setupCmdLineParser(parser)) { + if (0 != CLIParser::setupCmdLineParser(parser)) { logErrorNL("%s", "Cannot set up command-line parser."); return EXIT_FAILURE; } @@ -428,33 +103,23 @@ /* Process command-line arguments. */ parser.process(app); - if (0 != setupPreferences(parser, globPref, globLog)) { + if (0 != preferencesSetUp(parser, globPref, globLog)) { logErrorNL("%s", "Cannot apply command line arguments on global settings."); return EXIT_FAILURE; } - QStringList cmdLineFileNames = parser.positionalArguments(); - QStringList inOptions = parser.optionNames(); - QStringList serList; - - // check if any CLI service was set from command line - for (int i = 0; i < inOptions.count(); ++i) { - for (int j = 0; j < serviceList.count(); ++j) { - if (inOptions.at(i) == serviceList.at(j)) { - serList.append(inOptions.at(i)); - break; - } - } - } + const QStringList cmdLineFileNames(parser.positionalArguments()); + const QStringList srvcArgs( + CLIParser::CLIServiceArgs(parser.optionNames())); - short runMode = RUN_MODE_GUI; - QSplashScreen * splash = new QSplashScreen; + enum RunMode runMode = RM_GUI; + QSplashScreen *splash = new QSplashScreen; - if (!serList.isEmpty()) { - runMode = RUN_MODE_CLI; + if (!srvcArgs.isEmpty()) { + runMode = RM_CLI; } else if (!cmdLineFileNames.isEmpty()) { - runMode = RUN_MODE_ZFO; + runMode = RM_ZFO; } else { splash->setPixmap(QPixmap(":/splash/datovka-splash.png")); splash->show(); @@ -479,7 +144,7 @@ logInfo("Starting at %lld.%03lld .\n", start / 1000, start % 1000); /* Create configuration file is file is missing. */ - MainWindow::ensureConfPresence(); + GlobPreferences::ensureConfPresence(); if (0 != crypto_init()) { logError("%s\n", "Cannot load cryptographic back-end."); @@ -515,41 +180,8 @@ globProxSet.setProxyEnvVars(); } - { - /* Start downloading the CRL files. */ - QList urlList; - FileDownloader fDown(true); - const struct crl_location *crl = crl_locations; - const char **url; - while ((NULL != crl) && (NULL != crl->file_name)) { - urlList.clear(); - - url = crl->urls; - while ((NULL != url) && (NULL != *url)) { - urlList.append(QUrl(*url)); - ++url; - } - - QByteArray data = fDown.download(urlList, 2000); - if (!data.isEmpty()) { - if (0 != crypto_add_crl(data.data(), - data.size())) { - logWarning("Couldn't load downloaded " - "CRL file '%s'.\n", - crl->file_name); - } else { - logInfo("Loaded CRL file '%s'.\n", - crl->file_name); - } - } else { - logWarning( - "Couldn't download CRL file '%s'.\n", - crl->file_name); - } - - ++crl; - } - } + /* Start downloading the CRL files. */ + downloadCRL(); if (!SQLiteDb::dbDriverSupport()) { logError("Cannot load database driver '%s'.\n", @@ -563,10 +195,10 @@ logDebugLv0NL("App path: '%s'.", app.applicationDirPath().toUtf8().constData()); - loadLocalisation(app); + loadLocalisation(globPref); /* set splash action text */ - if (runMode == RUN_MODE_GUI) { + if (runMode == RM_GUI) { Qt::Alignment align = Qt::AlignCenter; splash->showMessage(QObject::tr("Application is loading..."), align, Qt::white); @@ -574,69 +206,12 @@ } /* Localise description in tables. */ - accntinfTbl.reloadLocalisedDescription(); - userinfTbl.reloadLocalisedDescription(); - pwdexpdtTbl.reloadLocalisedDescription(); - msgsTbl.reloadLocalisedDescription(); - flsTbl.reloadLocalisedDescription(); - hshsTbl.reloadLocalisedDescription(); - evntsTbl.reloadLocalisedDescription(); - prcstTbl.reloadLocalisedDescription(); - rwmsgdtTbl.reloadLocalisedDescription(); - rwdlvrinfdtTbl.reloadLocalisedDescription(); - smsgdtTbl.reloadLocalisedDescription(); - crtdtTbl.reloadLocalisedDescription(); - msgcrtdtTbl.reloadLocalisedDescription(); + localiseTableDescriptions(); - /* - * These objects cannot be globally accessible static objects. - * The unpredictable order of constructing and destructing these - * objects causes segmentation faults upon their destruction. - * - * TODO -- Solve the problem of this globally accessible structures. - */ - { - globAccountDbPtr = new (std::nothrow) AccountDb("accountDb"); - if (0 == globAccountDbPtr) { - logErrorNL("%s", "Cannot allocate account db."); - return EXIT_FAILURE; - } - /* Open accounts database. */ - if (!globAccountDbPtr->openDb(globPref.accountDbPath())) { - logErrorNL("Error opening account db '%s'.", - globPref.accountDbPath().toUtf8().constData()); - return EXIT_FAILURE; - } - - /* Create message DB container. */ - globMessageDbsPtr = new (std::nothrow) DbContainer("GLOBALDBS"); - if (0 == globMessageDbsPtr) { - logErrorNL("%s", - "Cannot allocate message db container."); - return EXIT_FAILURE; - } - - globTagDbPtr = new (std::nothrow) TagDb("tagDb"); - if (0 == globTagDbPtr) { - logErrorNL("%s", "Cannot allocate tag db."); - return EXIT_FAILURE; - } - /* Open tags database. */ - if (!globTagDbPtr->openDb(globPref.tagDbPath())) { - logErrorNL("Error opening tag db '%s'.", - globPref.tagDbPath().toUtf8().constData()); - return EXIT_FAILURE; - } - - /* Create tag DB container. */ - globWebDatovkaTagDbPtr = new (std::nothrow) TagDbContainer("tagDbWebDatovka"); - if (0 == globWebDatovkaTagDbPtr) { - logErrorNL("%s", "Cannot allocate webdatovka tag db container."); - return EXIT_FAILURE; - } + if (0 != allocateGlobalObjects(globPref)) { + return EXIT_FAILURE; } - int ret = EXIT_SUCCESS; /* Parse account information. */ @@ -644,7 +219,7 @@ QSettings settings(globPref.loadConfPath(), QSettings::IniFormat); settings.setIniCodec("UTF-8"); - AccountModel::globAccounts.loadFromSettings(settings); + globAccounts.loadFromSettings(settings); } /* Start worker threads. */ @@ -657,10 +232,10 @@ //QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif /* >= Qt-5.6 */ - if (runMode == RUN_MODE_CLI) { + if (runMode == RM_CLI) { delete splash; - ret = doCLI(serList, parser); - } else if (runMode == RUN_MODE_ZFO) { + ret = CLIParser::runCLIService(srvcArgs, parser); + } else if (runMode == RM_ZFO) { delete splash; foreach (const QString &fileName, cmdLineFileNames) { ret = showZfo(fileName); @@ -695,24 +270,7 @@ */ //crypto_cleanup_threads(); - if (0 != globTagDbPtr) { - delete globTagDbPtr; - globTagDbPtr = 0; - } - - if (0 != globWebDatovkaTagDbPtr) { - delete globWebDatovkaTagDbPtr; - globWebDatovkaTagDbPtr = 0; - } - - if (0 != globMessageDbsPtr) { - delete globMessageDbsPtr; - globMessageDbsPtr = 0; - } - if (0 != globAccountDbPtr) { - delete globAccountDbPtr; - globAccountDbPtr = 0; - } + deallocateGlobalObjects(); return ret; } diff -Nru datovka-4.8.3/src/model_interaction/account_interaction.cpp datovka-4.9.3/src/model_interaction/account_interaction.cpp --- datovka-4.8.3/src/model_interaction/account_interaction.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/model_interaction/account_interaction.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include "src/io/message_db_set.h" +#include "src/io/message_db_set_container.h" +#include "src/log/log.h" +#include "src/model_interaction/account_interaction.h" +#include "src/settings/account.h" +#include "src/settings/accounts.h" +#include "src/settings/preferences.h" + +/* TODO -- The method must be made shorter. */ +MessageDbSet *AccountInteraction::accessDbSet(const QString &userName, + enum AccessStatus &status, QString &dbDir, QString &namesStr) +{ + MessageDbSet *dbSet = Q_NULLPTR; + int flags, dbPresenceCode; + dbDir.clear(); + namesStr.clear(); + + if (Q_UNLIKELY(userName.isEmpty())) { + Q_ASSERT(0); + status = AS_ERR; + return Q_NULLPTR; + } + + /* Get user name and db location. */ + AcntSettings &itemSettings(globAccounts[userName]); + + if (!itemSettings.isValid()) { + logWarningNL( + "Attempting to accessing database for user name '%s'. " + "The account seems not to exist.", + userName.toUtf8().constData()); + status = AS_ERR; + return Q_NULLPTR; + } + + dbDir = itemSettings.dbDir(); + if (dbDir.isEmpty()) { + /* Set default directory name. */ + dbDir = globPref.confDir(); + } + + flags = 0; + if (itemSettings.isTestAccount()) { + flags |= MDS_FLG_TESTING; + } + if (itemSettings._createdFromScratch()) { + /* Check database structure on account creation. */ + flags |= MDS_FLG_CHECK_QUICK; + } + dbPresenceCode = + MessageDbSet::checkExistingDbFile(dbDir, userName, flags); + + switch (dbPresenceCode) { + case MDS_ERR_OK: + if (itemSettings._createdFromScratch()) { + /* Notify the user on account creation. */ + QStringList dbFileNames( + MessageDbSet::existingDbFileNamesInLocation( + dbDir, userName, + itemSettings.isTestAccount(), + MessageDbSet::DO_UNKNOWN, true)); + Q_ASSERT(!dbFileNames.isEmpty()); + namesStr = "'" + dbFileNames[0] + "'"; + for (int i = 1; i < dbFileNames.size(); ++i) { + namesStr += ", '" + dbFileNames[i] + "'"; + } + logInfoNL( + "Database files %s for user name '%s' already present in '%s'.", + namesStr.toUtf8().constData(), + userName.toUtf8().constData(), + dbDir.toUtf8().constData()); + status = AS_DB_ALREADY_PRESENT; + } else { + status = AS_OK; + } + dbSet = globMessageDbsPtr->accessDbSet(dbDir, userName, + itemSettings.isTestAccount(), + MessageDbSet::DO_UNKNOWN, + MessageDbSet::CM_MUST_EXIST); + break; + case MDS_ERR_MISSFILE: + if (!itemSettings._createdFromScratch()) { + /* Not on account creation. */ + logWarningNL( + "Missing database files for user name '%s' in '%s'.", + userName.toUtf8().constData(), + dbDir.toUtf8().constData()); + status = AS_DB_NOT_PRESENT; + } else { + status = AS_OK; + } + dbSet = globMessageDbsPtr->accessDbSet(dbDir, userName, + itemSettings.isTestAccount(), + MessageDbSet::DO_YEARLY, + MessageDbSet::CM_CREATE_EMPTY_CURRENT); + break; + case MDS_ERR_NOTAFILE: + { + /* Notify the user that the location is not a file. */ + QStringList dbFileNames( + MessageDbSet::existingDbFileNamesInLocation( + dbDir, userName, + itemSettings.isTestAccount(), + MessageDbSet::DO_UNKNOWN, true)); + Q_ASSERT(!dbFileNames.isEmpty()); + namesStr = "'" + dbFileNames[0] + "'"; + for (int i = 1; i < dbFileNames.size(); ++i) { + namesStr += ", '" + dbFileNames[i] + "'"; + } + logWarningNL( + "Some databases of %s in '%s' related to user name '%s' are not a file.", + namesStr.toUtf8().constData(), + dbDir.toUtf8().constData(), + userName.toUtf8().constData()); + status = AS_DB_NOT_FILES; + } + break; + case MDS_ERR_ACCESS: + { + /* Notify that the user does not have enough rights. */ + QStringList dbFileNames( + MessageDbSet::existingDbFileNamesInLocation( + dbDir, userName, + itemSettings.isTestAccount(), + MessageDbSet::DO_UNKNOWN, true)); + Q_ASSERT(!dbFileNames.isEmpty()); + namesStr = "'" + dbFileNames[0] + "'"; + for (int i = 1; i < dbFileNames.size(); ++i) { + namesStr += ", '" + dbFileNames[i] + "'"; + } + logWarningNL( + "Some databases of '%s' in '%s' related to user name '%s' cannot be accessed.", + namesStr.toUtf8().constData(), + dbDir.toUtf8().constData(), + userName.toUtf8().constData()); + status = AS_DB_FILES_INACCESSIBLE; + } + break; + case MDS_ERR_CREATE: + { + /* This error should not be returned. */ + Q_ASSERT(0); + status = AS_ERR; + } + break; + case MDS_ERR_DATA: + { + /* + * Database file is not a database file or is + * corrupted. + */ + QStringList dbFileNames( + MessageDbSet::existingDbFileNamesInLocation( + dbDir, userName, + itemSettings.isTestAccount(), + MessageDbSet::DO_UNKNOWN, true)); + Q_ASSERT(!dbFileNames.isEmpty()); + namesStr = "'" + dbFileNames[0] + "'"; + for (int i = 1; i < dbFileNames.size(); ++i) { + namesStr += ", '" + dbFileNames[i] + "'"; + } + logWarningNL( + "Some databases of %s in '%s' related to user name '%s' is probably corrupted.", + namesStr.toUtf8().constData(), + dbDir.toUtf8().constData(), + userName.toUtf8().constData()); + status = AS_DB_FILES_CORRUPT; + } + break; + case MDS_ERR_MULTIPLE: + { + /* + * Multiple database organisation types reside in the + * same location. + */ + QStringList dbFileNames( + MessageDbSet::existingDbFileNamesInLocation( + dbDir, userName, + itemSettings.isTestAccount(), + MessageDbSet::DO_UNKNOWN, true)); + Q_ASSERT(!dbFileNames.isEmpty()); + namesStr = "'" + dbFileNames[0] + "'"; + for (int i = 1; i < dbFileNames.size(); ++i) { + namesStr += ", '" + dbFileNames[i] + "'"; + } + logWarningNL( + "Multiple databases %s for '%s' have been encountered in the location '%s'.", + namesStr.toUtf8().constData(), + userName.toUtf8().constData(), + dbDir.toUtf8().constData()); + status = AS_DB_CONFUSING_ORGANISATION; + } + break; + default: + /* The code should not end here. */ + Q_ASSERT(0); + status = AS_ERR; + break; + } + + if (itemSettings._createdFromScratch()) { + /* Notify only once. */ + itemSettings._setCreatedFromScratch(false); + } + + if (Q_NULLPTR == dbSet) { + logErrorNL( + "Database files for user name '%s' in '%s' cannot be created or is probably corrupted.", + userName.toUtf8().constData(), + dbDir.toUtf8().constData()); + } + + return dbSet; +} diff -Nru datovka-4.8.3/src/model_interaction/account_interaction.h datovka-4.9.3/src/model_interaction/account_interaction.h --- datovka-4.8.3/src/model_interaction/account_interaction.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/model_interaction/account_interaction.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _ACCOUNT_INTERACTION_H_ +#define _ACCOUNT_INTERACTION_H_ + +#include /* Q_DECLARE_TR_FUNCTIONS */ +#include + +class MessageDbSet; /* Forward declaration. */ + +/*! + * @brief Provides a namespace for convenience functions dealing with the + * account container. + * + * @note The account container is considered to be part of the account model. + * The methods are not part of the model because the code has to be + * separated from GUI dependencies. + */ +class AccountInteraction { + Q_DECLARE_TR_FUNCTIONS(AccountInteraction) + +private: + /*! + * @brief Private constructor. + */ + AccountInteraction(void); + +public: + enum AccessStatus { + AS_OK = 0, /*!< Database successfully opened. */ + AS_DB_ALREADY_PRESENT, /*!< Database already present even though it should not exist. */ + AS_DB_NOT_PRESENT, /*!< Database is not present even though it should exist. */ + AS_DB_NOT_FILES, /*!< Some of the database locations are not files. */ + AS_DB_FILES_INACCESSIBLE, /*!< Some files cannot be accessed. */ + AS_DB_FILES_CORRUPT, /*!< Some files do not contain valid database. */ + AS_DB_CONFUSING_ORGANISATION, /*!< Multiple organisation formats within same location. */ + AS_ERR /*!< Generic error. */ + }; + + /*! + * @brief Accesses database set for supplied user name. + * + * @note The returned pointer must not be freed. + * + * @param[in] userName User name identifying the account. + * @param[out] status Return status while accessing the databases. + * @param[out] dbDir Database location directory. + * @param[out] namesStr Database file names. + * @return Pointer to database set or Q_NULLPTR on error. + */ + static + MessageDbSet *accessDbSet(const QString &userName, + enum AccessStatus &status, QString &dbDir, QString &namesStr); +}; + +#endif /* _ACCOUNT_INTERACTION_H_ */ diff -Nru datovka-4.8.3/src/models/accounts_model.cpp datovka-4.9.3/src/models/accounts_model.cpp --- datovka-4.8.3/src/models/accounts_model.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/models/accounts_model.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -76,8 +76,6 @@ #define internalIdUserNameIndex(intId) \ (((unsigned) (intId)) >> TYPE_BITS) -AccountsMap AccountModel::globAccounts; - AccountModel::AccountModel(QObject *parent) : QAbstractItemModel(parent), m_userNames(), @@ -306,12 +304,8 @@ case Qt::DecorationRole: switch (type) { case nodeAccountTop: - if (isWebDatovkaAccount(uName)) { - return QIcon(":/mojeid.png"); - } else { - return QIcon(ICON_3PARTY_PATH + - QStringLiteral("letter_16.png")); - } + return QIcon(ICON_3PARTY_PATH + + QStringLiteral("letter_16.png")); break; case nodeRecentReceived: case nodeReceived: diff -Nru datovka-4.8.3/src/models/accounts_model.h datovka-4.9.3/src/models/accounts_model.h --- datovka-4.8.3/src/models/accounts_model.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/models/accounts_model.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,7 +32,6 @@ #include #include - #include "src/settings/accounts.h" /* Login method descriptors. */ @@ -41,7 +40,6 @@ #define LIM_USER_CERT "user_certificate" #define LIM_HOTP "hotp" #define LIM_TOTP "totp" -#define LIM_MOJEID "mojeid" /*! * @brief Account hierarchy. @@ -50,14 +48,6 @@ Q_OBJECT public: - /*! - * @brief Holds account data related to account. - * - * @note Key is userName. The user name is held by the user name list. - */ - static - AccountsMap globAccounts; - /* * nodeRoot (Invisible.) * | diff -Nru datovka-4.8.3/src/models/data_box_contacts_model.cpp datovka-4.9.3/src/models/data_box_contacts_model.cpp --- datovka-4.8.3/src/models/data_box_contacts_model.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/models/data_box_contacts_model.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -21,7 +21,7 @@ * the two. */ -#include "src/common.h" +#include "src/isds/isds_conversion.h" #include "src/models/data_box_contacts_model.h" BoxContactsModel::BoxContactsModel(QObject *parent) @@ -59,7 +59,7 @@ QVariant entry(_data(index, role)); if (!entry.isNull()) { - return convertDbTypeToString(entry.toInt()); + return IsdsConversion::boxTypeToStr(entry.toInt()); } else { return entry; } diff -Nru datovka-4.8.3/src/models/files_model.cpp datovka-4.9.3/src/models/files_model.cpp --- datovka-4.8.3/src/models/files_model.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/models/files_model.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -358,63 +358,59 @@ Qt::DisplayRole); } -bool DbFlsTblModel::setMessage(const struct isds_message *message) +void DbFlsTblModel::appendData( + const QList &entryList) { - if (NULL == message) { + if (Q_UNLIKELY(MessageDb::fileItemIds.size() != 6)) { Q_ASSERT(0); - return false; + return; } - beginResetModel(); - m_data.clear(); - m_rowsAllocated = 0; - m_rowCount = 0; - endResetModel(); + m_columnCount = 6; - /* m_columnCount = MAX_COL; */ + if (entryList.isEmpty()) { + /* Don't do anything. */ + return; + } - return appendMessageData(message); -} + beginInsertRows(QModelIndex(), rowCount(), + rowCount() + entryList.size() - 1); -void DbFlsTblModel::setQuery(QSqlQuery &query) -{ - beginResetModel(); - m_data.clear(); - m_rowsAllocated = 0; - m_rowCount = 0; - endResetModel(); + foreach (const MessageDb::AttachmentEntry &entry, entryList) { - /* Looks like empty results have column count set. */ - /* m_columnCount = MAX_COL; */ - if ((query.record().count() + 1) != m_columnCount) { - Q_ASSERT(0); - return; + reserveSpace(); + + QVector row(m_columnCount); + + row[ATTACHID_COL] = entry.id; + row[MSGID_COL] = entry.messageId; + row[CONTENT_COL] = entry.dmEncodedContent; + row[FNAME_COL] = entry.dmFileDescr; + row[MIME_COL] = entry.dmMimeType; + row[FSIZE_COL] = entry.size; + + m_data[m_rowCount++] = row; } - appendQueryData(query); + endInsertRows(); } -bool DbFlsTblModel::appendQueryData(QSqlQuery &query) +bool DbFlsTblModel::setMessage(const struct isds_message *message) { - if ((query.record().count() + 1) != m_columnCount) { + if (NULL == message) { + Q_ASSERT(0); return false; } - query.first(); - while (query.isActive() && query.isValid()) { - - QVector row(m_columnCount); - - queryToVector(row, query); - row[FPATH_COL] = LOCAL_DATABASE_STR; - - /* Don't check data duplicity! */ - insertVector(row, rowCount(), false); + beginResetModel(); + m_data.clear(); + m_rowsAllocated = 0; + m_rowCount = 0; + endResetModel(); - query.next(); - } + /* m_columnCount = MAX_COL; */ - return true; + return appendMessageData(message); } /* File content will be held within model. */ diff -Nru datovka-4.8.3/src/models/files_model.h datovka-4.9.3/src/models/files_model.h --- datovka-4.8.3/src/models/files_model.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/models/files_model.h 2017-09-06 11:49:23.000000000 +0000 @@ -28,6 +28,7 @@ #include #include +#include "src/io/message_db.h" #include "src/models/table_model.h" /*! @@ -100,7 +101,7 @@ * @brief Returns object containing serialised attachment data. * * @param[in] indexes List of indexes. - * @return Pointer to newly allocated mime data object, 0 on error. + * @return Pointer to newly allocated mime data object, Q_NULLPTR on error. */ virtual QMimeData *mimeData( @@ -142,30 +143,20 @@ void setHeader(void); /*! - * @brief Sets the content of the model according to the supplied - * message. + * @brief Appends data into the model. * - * @param[in] message Message structure. - * @return True on success. + * @brief entryList List of entries to append into the model. */ - bool setMessage(const struct isds_message *message); + void appendData(const QList &entryList); /*! - * @brief Sets the content of the model according to the supplied query. - * - * @param[in,out] qyery SQL query result. - */ - virtual - void setQuery(QSqlQuery &query) Q_DECL_OVERRIDE; - - /*! - * @brief Appends data from the supplied query to the model. + * @brief Sets the content of the model according to the supplied + * message. * - * @param[in,out] query SQL query result. + * @param[in] message Message structure. * @return True on success. */ - virtual - bool appendQueryData(QSqlQuery &query) Q_DECL_OVERRIDE; + bool setMessage(const struct isds_message *message); /*! * @brief Adds attachment file. diff -Nru datovka-4.8.3/src/models/messages_model.cpp datovka-4.9.3/src/models/messages_model.cpp --- datovka-4.8.3/src/models/messages_model.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/models/messages_model.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,16 +22,16 @@ */ #include -#include #include "src/common.h" #include "src/delegates/tag_item.h" -#include "src/io/tag_db.h" /* Direct access to tag database, */ +#include "src/graphics/graphics.h" #include "src/io/db_tables.h" #include "src/io/dbs.h" -#include "src/io/tag_db_container.h" -#include "src/models/messages_model.h" #include "src/io/message_db.h" +#include "src/io/records_management_db.h" +#include "src/io/tag_db.h" /* Direct access to tag database, */ +#include "src/models/messages_model.h" const int DbMsgsTblModel::rcvdMsgsColCnt(8); const int DbMsgsTblModel::sntMsgsColCnt(7); @@ -44,7 +44,8 @@ DbMsgsTblModel::DbMsgsTblModel(enum DbMsgsTblModel::Type type, QObject *parent) : TblModel(parent), - m_type(type) + m_type(type), + m_dsIco(ICON_3PARTY_PATH "up_16.png") { } @@ -52,17 +53,60 @@ { int dataType; - /* Leave additional to delegates. */ +#define TAGS_OFFS 1 /* Tags are located behind upload information. */ + + /* Draw upload information. */ + /* TODO -- This is only a temporal solution. */ + switch (m_type) { + case WORKING_RCVD: + if (index.column() == (PROCSNG_COL + TAGS_OFFS)) { + QStringList locations( + _data(index, Qt::DisplayRole).toStringList()); + switch (role) { + case Qt::DecorationRole: + return locations.isEmpty() ? QVariant() : m_dsIco; + break; + case Qt::ToolTipRole: + return locations.join("\n"); + break; + default: + return QVariant(); + break; + } + } + break; + case WORKING_SNT: + if (index.column() == (ATTDOWN_COL + TAGS_OFFS)) { + QStringList locations( + _data(index, Qt::DisplayRole).toStringList()); + switch (role) { + case Qt::DecorationRole: + return locations.isEmpty() ? QVariant() : m_dsIco; + break; + case Qt::ToolTipRole: + return locations.join("\n"); + break; + default: + return QVariant(); + break; + } + } + break; + default: + Q_ASSERT(0); + return QVariant(); + break; + } + + /* Leave additional tags to delegates. */ switch (m_type) { case WORKING_RCVD: - case DUMMY_RCVD: - if (index.column() > PROCSNG_COL) { + if (index.column() > (PROCSNG_COL + TAGS_OFFS)) { return _data(index, role); } break; case WORKING_SNT: - case DUMMY_SNT: - if (index.column() > ATTDOWN_COL) { + if (index.column() > (ATTDOWN_COL + TAGS_OFFS)) { return _data(index, role); } break; @@ -72,6 +116,8 @@ break; } +#undef TAGS_OFFS + switch (role) { case Qt::DisplayRole: dataType = _headerData(index.column(), Qt::Horizontal, @@ -211,13 +257,11 @@ /* Draw additional. */ switch (m_type) { case WORKING_RCVD: - case DUMMY_RCVD: if (section > PROCSNG_COL) { return _headerData(section, orientation, role); } break; case WORKING_SNT: - case DUMMY_SNT: if (section > ATTDOWN_COL) { return _headerData(section, orientation, role); } @@ -300,95 +344,170 @@ } } -void DbMsgsTblModel::setQuery(QSqlQuery &query, enum DbMsgsTblModel::Type type) +void DbMsgsTblModel::appendData(const QList &entryList, + int appendedColsNum) { - setType(type); - TblModel::setQuery(query); - /* TODO -- Check whether type matches query. */ + if (Q_UNLIKELY(appendedColsNum < 0)) { + Q_ASSERT(0); + return; + } + + /* Set column count if the model is empty. */ + if (rowCount() == 0) { + beginResetModel(); + m_type = WORKING_RCVD; + m_columnCount = MessageDb::rcvdItemIds.size() + appendedColsNum; + endResetModel(); + } else { + if (Q_UNLIKELY(m_type != WORKING_RCVD)) { + Q_ASSERT(0); + return; + } + if (Q_UNLIKELY(m_columnCount != + (MessageDb::rcvdItemIds.size() + appendedColsNum))) { + Q_ASSERT(0); + return; + } + } + + if (entryList.isEmpty()) { + /* Don't do anything. */ + return; + } + + beginInsertRows(QModelIndex(), rowCount(), + rowCount() + entryList.size() - 1); + + foreach (const MessageDb::RcvdEntry &entry, entryList) { + + reserveSpace(); + + QVector row(m_columnCount); + + row[DMID_COL] = entry.dmId; + row[ANNOT_COL] = entry.dmAnnotation; + row[2] = entry.dmSender; + row[DELIVERY_COL] = entry.dmDeliveryTime; + row[ACCEPT_COL] = entry.dmAcceptanceTime; + row[READLOC_COL] = entry.readLocally; + row[ATTDOWN_COL] = entry.isDownloaded; + row[PROCSNG_COL] = entry.processStatus; + + m_data[m_rowCount++] = row; + } + + endInsertRows(); } -bool DbMsgsTblModel::appendQueryData(QSqlQuery &query, - enum DbMsgsTblModel::Type type) +void DbMsgsTblModel::appendData(const QList &entryList, + int appendedColsNum) { - if (type != m_type) { - return false; + if (Q_UNLIKELY(appendedColsNum < 0)) { + Q_ASSERT(0); + return; + } + + /* Set column count if the model is empty. */ + if (rowCount() == 0) { + beginResetModel(); + m_type = WORKING_SNT; + m_columnCount = MessageDb::sntItemIds.size() + appendedColsNum; + endResetModel(); + } else { + if (Q_UNLIKELY(m_type != WORKING_SNT)) { + Q_ASSERT(0); + return; + } + if (Q_UNLIKELY(m_columnCount != + (MessageDb::sntItemIds.size() + appendedColsNum))) { + Q_ASSERT(0); + return; + } + } + + if (entryList.isEmpty()) { + /* Don't do anything. */ + return; } - return TblModel::appendQueryData(query); + + beginInsertRows(QModelIndex(), rowCount(), + rowCount() + entryList.size() - 1); + + foreach (const MessageDb::SntEntry &entry, entryList) { + + reserveSpace(); + + QVector row(m_columnCount); + + row[DMID_COL] = entry.dmId; + row[ANNOT_COL] = entry.dmAnnotation; + row[2] = entry.dmRecipient; + row[DELIVERY_COL] = entry.dmDeliveryTime; + row[ACCEPT_COL] = entry.dmAcceptanceTime; + row[5] = entry.dmMessageStatus; + row[ATTDOWN_COL] = entry.isDownloaded; + + m_data[m_rowCount++] = row; + } + + endInsertRows(); } bool DbMsgsTblModel::setType(enum DbMsgsTblModel::Type type) { m_type = type; - switch (m_type) { - case DUMMY_RCVD: - return setRcvdHeader(QStringList()); /* FIXME */ - break; - case DUMMY_SNT: - return setSntHeader(QStringList()); /* FIXME */ - break; - default: - return true; - break; - } + return true; } -const QVector &DbMsgsTblModel::rcvdItemIds(void) +static +void appendHeaderColumns(DbMsgsTblModel *model, int dfltHdrSize, + const QList &appendedCols) { - static QVector ids; - if (ids.size() == 0) { - ids.append("dmID"); - ids.append("dmAnnotation"); - ids.append("dmSender"); - ids.append("dmDeliveryTime"); - ids.append("dmAcceptanceTime"); - ids.append("read_locally"); - ids.append("is_downloaded"); - ids.append("process_status"); + if ((model == Q_NULLPTR) || (dfltHdrSize < 0)) { + Q_ASSERT(0); + return; } - return ids; -} -const QVector &DbMsgsTblModel::sntItemIds(void) -{ - static QVector ids; - if (ids.size() == 0) { - ids.append("dmID"); - ids.append("dmAnnotation"); - ids.append("dmRecipient"); - ids.append("dmDeliveryTime"); - ids.append("dmAcceptanceTime"); - ids.append("dmMessageStatus"); - ids.append("is_downloaded"); + for (int i = 0; i < appendedCols.size(); ++i) { + /* Description. */ + model->setHeaderData(dfltHdrSize + i, Qt::Horizontal, + appendedCols.at(i).display, Qt::DisplayRole); + model->setHeaderData(dfltHdrSize + i, Qt::Horizontal, + appendedCols.at(i).decoration, Qt::DecorationRole); + model->setHeaderData(dfltHdrSize + i, Qt::Horizontal, + appendedCols.at(i).toolTip, Qt::ToolTipRole); + /* Data type. */ + model->setHeaderData(dfltHdrSize + i, Qt::Horizontal, + DB_APPENDED_VARIANT, ROLE_MSGS_DB_ENTRY_TYPE); } - return ids; } -bool DbMsgsTblModel::setRcvdHeader(const QStringList &appendedCols) +bool DbMsgsTblModel::setRcvdHeader(const QList &appendedCols) { - for (int i = 0; i < rcvdItemIds().size(); ++i) { + for (int i = 0; i < MessageDb::rcvdItemIds.size(); ++i) { /* TODO -- Handle the joined tables in a better way. */ - if (msgsTbl.attrProps.find(rcvdItemIds()[i]) != + if (msgsTbl.attrProps.find(MessageDb::rcvdItemIds[i]) != msgsTbl.attrProps.end()) { /* Description. */ setHeaderData(i, Qt::Horizontal, - msgsTbl.attrProps.value(rcvdItemIds()[i]).desc, + msgsTbl.attrProps.value(MessageDb::rcvdItemIds[i]).desc, Qt::DisplayRole); /* Data type. */ setHeaderData(i, Qt::Horizontal, - msgsTbl.attrProps.value(rcvdItemIds()[i]).type, + msgsTbl.attrProps.value(MessageDb::rcvdItemIds[i]).type, ROLE_MSGS_DB_ENTRY_TYPE); - } else if (smsgdtTbl.attrProps.find(rcvdItemIds()[i]) != + } else if (smsgdtTbl.attrProps.find(MessageDb::rcvdItemIds[i]) != smsgdtTbl.attrProps.end()) { /* Description. */ setHeaderData(i, Qt::Horizontal, - smsgdtTbl.attrProps.value(rcvdItemIds()[i]).desc, + smsgdtTbl.attrProps.value(MessageDb::rcvdItemIds[i]).desc, Qt::DisplayRole); /* Data type. */ setHeaderData(i, Qt::Horizontal, - smsgdtTbl.attrProps.value(rcvdItemIds()[i]).type, + smsgdtTbl.attrProps.value(MessageDb::rcvdItemIds[i]).type, ROLE_MSGS_DB_ENTRY_TYPE); - } else if ("is_downloaded" == rcvdItemIds()[i]) { + } else if ("is_downloaded" == MessageDb::rcvdItemIds[i]) { /* Description. */ setHeaderData(i, Qt::Horizontal, tr("Attachments downloaded"), Qt::DisplayRole); @@ -396,7 +515,7 @@ setHeaderData(i, Qt::Horizontal, DB_BOOL_ATTACHMENT_DOWNLOADED, ROLE_MSGS_DB_ENTRY_TYPE); - } else if ("process_status" == rcvdItemIds()[i]) { + } else if ("process_status" == MessageDb::rcvdItemIds[i]) { /* Description. */ setHeaderData(i, Qt::Horizontal, tr("Processing state"), Qt::DisplayRole); @@ -408,33 +527,26 @@ } } - for (int i = 0; i < appendedCols.size(); ++i) { - /* Description. */ - setHeaderData(rcvdItemIds().size() + i, Qt::Horizontal, - appendedCols.at(i), Qt::DisplayRole); - /* Data type. */ - setHeaderData(rcvdItemIds().size() + i, Qt::Horizontal, - DB_APPENDED_VARIANT, ROLE_MSGS_DB_ENTRY_TYPE); - } + appendHeaderColumns(this, MessageDb::rcvdItemIds.size(), appendedCols); return true; } -bool DbMsgsTblModel::setSntHeader(const QStringList &appendedCols) +bool DbMsgsTblModel::setSntHeader(const QList &appendedCols) { - for (int i = 0; i < sntItemIds().size(); ++i) { + for (int i = 0; i < MessageDb::sntItemIds.size(); ++i) { /* TODO -- Handle the joined tables in a better way. */ - if (msgsTbl.attrProps.find(sntItemIds()[i]) != + if (msgsTbl.attrProps.find(MessageDb::sntItemIds[i]) != msgsTbl.attrProps.end()) { /* Description. */ setHeaderData(i, Qt::Horizontal, - msgsTbl.attrProps.value(sntItemIds()[i]).desc, + msgsTbl.attrProps.value(MessageDb::sntItemIds[i]).desc, Qt::DisplayRole); /* Data type. */ setHeaderData(i, Qt::Horizontal, - msgsTbl.attrProps.value(sntItemIds()[i]).type, + msgsTbl.attrProps.value(MessageDb::sntItemIds[i]).type, ROLE_MSGS_DB_ENTRY_TYPE); - } else if ("is_downloaded" == sntItemIds()[i]) { + } else if ("is_downloaded" == MessageDb::sntItemIds[i]) { /* Description. */ setHeaderData(i, Qt::Horizontal, tr("Attachments downloaded"), Qt::DisplayRole); @@ -447,14 +559,7 @@ } } - for (int i = 0; i < appendedCols.size(); ++i) { - /* Description. */ - setHeaderData(sntItemIds().size() + i, Qt::Horizontal, - appendedCols.at(i), Qt::DisplayRole); - /* Data type. */ - setHeaderData(sntItemIds().size() + i, Qt::Horizontal, - DB_APPENDED_VARIANT, ROLE_MSGS_DB_ENTRY_TYPE); - } + appendHeaderColumns(this, MessageDb::sntItemIds.size(), appendedCols); return true; } @@ -523,25 +628,9 @@ return false; } -DbMsgsTblModel &DbMsgsTblModel::dummyModel(enum DbMsgsTblModel::Type type) -{ - static DbMsgsTblModel dummy(DUMMY_RCVD); - dummy.setType(type); - return dummy; -} - bool DbMsgsTblModel::fillTagsColumn(const QString &userName, int col) { - TagDb *tagDb = 0; - - if (isWebDatovkaAccount(userName)) { - tagDb = globWebDatovkaTagDbPtr-> - accessTagDb(getWebDatovkaTagDbPrefix(userName)); - } else { - tagDb = globTagDbPtr; - } - - if (0 == tagDb) { + if (Q_NULLPTR == globTagDbPtr) { return false; } @@ -563,7 +652,7 @@ for (int row = 0; row < rowCount(); ++row) { qint64 dmId = TblModel::index(row, 0).data().toLongLong(); - TagItemList tagList(tagDb->getMessageTags(userName, dmId)); + TagItemList tagList(globTagDbPtr->getMessageTags(userName, dmId)); tagList.sortNames(); m_data[row][col] = QVariant::fromValue(tagList); } @@ -577,16 +666,7 @@ bool DbMsgsTblModel::refillTagsColumn(const QString &userName, const QList &dmIds, int col) { - TagDb *tagDb = 0; - - if (isWebDatovkaAccount(userName)) { - tagDb = globWebDatovkaTagDbPtr-> - accessTagDb(getWebDatovkaTagDbPrefix(userName)); - } else { - tagDb = globTagDbPtr; - } - - if (0 == tagDb) { + if (Q_NULLPTR == globTagDbPtr) { return false; } @@ -610,7 +690,7 @@ qint64 dmId = TblModel::index(row, 0).data().toLongLong(); if (dmIds.contains(dmId)) { TagItemList tagList( - tagDb->getMessageTags(userName, dmId)); + globTagDbPtr->getMessageTags(userName, dmId)); tagList.sortNames(); m_data[row][col] = QVariant::fromValue(tagList); emit dataChanged(TblModel::index(row, col), @@ -621,12 +701,87 @@ return true; } -void DbMsgsTblModel::setQuery(QSqlQuery &query) +bool DbMsgsTblModel::setRecordsManagementIcon(void) { - TblModel::setQuery(query); + if (Q_NULLPTR == globRecordsManagementDbPtr) { + m_dsIco = QIcon(ICON_3PARTY_PATH "up_16.png"); + return false; + } + + RecordsManagementDb::ServiceInfoEntry entry( + globRecordsManagementDbPtr->serviceInfo()); + if (!entry.isValid() || entry.logoSvg.isEmpty()) { + m_dsIco = QIcon(ICON_3PARTY_PATH "up_16.png"); + return false; + } + QPixmap pixmap(Graphics::pixmapFromSvg(entry.logoSvg, 16)); + if (pixmap.isNull()) { + m_dsIco = QIcon(ICON_3PARTY_PATH "up_16.png"); + return false; + } + + m_dsIco = QIcon(pixmap); + return true; +} + +bool DbMsgsTblModel::fillRecordsManagementColumn(int col) +{ + if (Q_NULLPTR == globRecordsManagementDbPtr) { + return false; + } + + /* Check indexes into column. */ + if (col >= 0) { + if (col > columnCount()) { + return false; + } + } else { + col += columnCount(); + if (col < 0) { + return false; + } + } + + for (int row = 0; row < rowCount(); ++row) { + qint64 dmId = TblModel::index(row, 0).data().toLongLong(); + m_data[row][col] = + globRecordsManagementDbPtr->storedMsgLocations(dmId); + } + + emit dataChanged(TblModel::index(0, col), + TblModel::index(rowCount() - 1, col)); + + return true; } -bool DbMsgsTblModel::appendQueryData(QSqlQuery &query) +bool DbMsgsTblModel::refillRecordsManagementColumn(const QList &dmIds, + int col) { - return TblModel::appendQueryData(query); + if (Q_NULLPTR == globRecordsManagementDbPtr) { + return false; + } + + /* Check indexes into column. */ + if (col >= 0) { + if (col > columnCount()) { + return false; + } + } else { + col += columnCount(); + if (col < 0) { + return false; + } + } + + for (int row = 0; row < rowCount(); ++row) { + qint64 dmId = TblModel::index(row, 0).data().toLongLong(); + if (dmIds.contains(dmId)) { + m_data[row][col] = + globRecordsManagementDbPtr->storedMsgLocations(dmId); + emit dataChanged(TblModel::index(row, col), + TblModel::index(row, col)); + } + } + + return true; } diff -Nru datovka-4.8.3/src/models/messages_model.h datovka-4.9.3/src/models/messages_model.h --- datovka-4.8.3/src/models/messages_model.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/models/messages_model.h 2017-09-06 11:49:23.000000000 +0000 @@ -24,11 +24,14 @@ #ifndef _MESSAGES_MODEL_H_ #define _MESSAGES_MODEL_H_ +#include +#include #include #include #include #include "src/common.h" /* enum MessageProcessState */ +#include "src/io/message_db.h" #include "src/models/table_model.h" /*! @@ -53,7 +56,9 @@ ACCEPT_COL = 4, /* Acceptance time column. */ READLOC_COL = 5, /* Read locally. */ ATTDOWN_COL = 6, /* Attachments downloaded. */ - PROCSNG_COL = 7 /* Processing state. */ + PROCSNG_COL = 7, /* Processing state. */ + REC_MGMT_NEG_COL = -2, /* Records management service. */ + TAGS_NEG_COL = -1 /* Tags. */ }; /*! @@ -62,10 +67,27 @@ * @note Dummies are used to fake empty models. */ enum Type { - WORKING_RCVD = 0, /*!< Ordinary model created from SQL query. */ - WORKING_SNT, /*!< Ordinary model created from SQL query. */ - DUMMY_RCVD, /*!< Empty received dummy. */ - DUMMY_SNT /*!< Empty sent dummy. */ + WORKING_RCVD = 0, /*!< Ordinary model created from SQL query result. */ + WORKING_SNT /*!< Ordinary model created from SQL query result. */ + }; + + /*! + * @brief Describes appended header entry. + */ + class AppendedCol { + public: + /*! + * @brief Constructor. + */ + explicit AppendedCol(const QString &dis, + const QIcon &dec = QIcon(), const QString &tip = QString()) + : display(dis), decoration(dec), toolTip(tip) + { + } + + QString display; /*!< What to show on display role. */ + QIcon decoration; /*!< What to display on decoration role. */ + QString toolTip; /*!< What to display in tool tip. */ }; /*! @@ -75,7 +97,7 @@ * @param[in] parent Parent object. */ explicit DbMsgsTblModel(enum Type type = WORKING_RCVD, - QObject *parent = 0); + QObject *parent = Q_NULLPTR); /*! * @brief Returns the data stored under the given role. @@ -101,21 +123,22 @@ int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; /*! - * @brief Sets the content of the model according to the supplied query. + * @brief Appends received entry data into the model. * - * @param[in,out] qyery SQL query result. - * @param[in] type Working received or sent. + * @param[in] entryList List of entries to append into the model. + * @param[in] appendedColsNum Number of added empty columns. */ - void setQuery(QSqlQuery &query, enum Type type); + void appendData(const QList &entryList, + int appendedColsNum); /*! - * @brief Appends data from the supplied query to the model. + * @brief Appends sent entry data into the model. * - * @param[in,out] query SQL query result. - * @param[in] type Working received or sent. - * @return True on success. + * @param[in] entryList List of entries to append into the model. + * @param[in] appendedColsNum Number of added empty columns. */ - bool appendQueryData(QSqlQuery &query, enum Type type); + void appendData(const QList &entryList, + int appendedColsNum); /*! * @brief Sets the type of the model. @@ -128,34 +151,18 @@ bool setType(enum Type type); /*! - * @brief Singleton method returning received column identifiers. - * - * @return List of received column identifiers. - */ - static - const QVector &rcvdItemIds(void); - - /*! - * @brief Singleton method returning sent column identifiers. - * - * @return List of sent column identifiers. - */ - static - const QVector &sntItemIds(void); - - /*! * @brief Set header data for received model. * * @return False on error. */ - bool setRcvdHeader(const QStringList &appendedCols); + bool setRcvdHeader(const QList &appendedCols); /*! * @Brief Set header data for sent model. * * @return False on error. */ - bool setSntHeader(const QStringList &appendedCols); + bool setSntHeader(const QList &appendedCols); /*! * @brief Override message as being read. @@ -193,17 +200,6 @@ enum MessageProcessState forceState); /*! - * @brief Returns reference to a dummy model. - * - * @note Beware of the static initialization order fiasco. - * - * @param[in] type Type of the table model. - * @returns Reference to a static dummy model. - */ - static - DbMsgsTblModel &dummyModel(enum Type type); - - /*! * @brief Fills the model with tag information. * * @param[in] userName Account user name. @@ -225,13 +221,30 @@ bool refillTagsColumn(const QString &userName, const QList &dmIds, int col); -private: - /* Make these methods private so nobody is likely to mess with them. */ - virtual - void setQuery(QSqlQuery &query) Q_DECL_OVERRIDE; - virtual - bool appendQueryData(QSqlQuery &query) Q_DECL_OVERRIDE; + /*! + * @brief Sets records management service notification icon. + * @return True on success. + */ + bool setRecordsManagementIcon(void); + + /*! + * @brief Fills the model with records management service information. + * + * @param[in] col Negative number specifying the column to write into. + * @return True on success. + */ + bool fillRecordsManagementColumn(int col); + + /*! + * @brief Reload records management service information in given rows. + * + * @param[in] dmIds List of message ids for which to load tags. + * @param[in] col Negative number specifying the column to write into. + * @return True on success. + */ + bool refillRecordsManagementColumn(const QList &dmIds, int col); +private: enum Type m_type; /*!< * Whether this is a model dummy or contains data. */ @@ -246,6 +259,8 @@ * Number of columns when displaying sent * messages (without added columns). */ + + QIcon m_dsIco; /*!< Records management icon. */ }; #endif /* _MESSAGES_MODEL_H_ */ diff -Nru datovka-4.8.3/src/models/table_model.cpp datovka-4.9.3/src/models/table_model.cpp --- datovka-4.8.3/src/models/table_model.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/models/table_model.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -73,47 +73,6 @@ return _headerData(section, orientation, role); } -void TblModel::setQuery(QSqlQuery &query) -{ - beginResetModel(); - m_data.clear(); - m_rowsAllocated = 0; - m_rowCount = 0; - endResetModel(); - - /* Looks like empty results have column count set. */ - m_columnCount = query.record().count(); - - appendQueryData(query); -} - -bool TblModel::appendQueryData(QSqlQuery &query) -{ - if (query.record().count() != m_columnCount) { - return false; - } - - beginResetModel(); - - query.first(); - while (query.isActive() && query.isValid()) { - - reserveSpace(); - - QVector row(m_columnCount); - - queryToVector(row, query); - - m_data[m_rowCount++] = row; - - query.next(); - } - - endResetModel(); - - return true; -} - bool TblModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) { @@ -203,6 +162,48 @@ return true; } + +void TblModel::setQuery(QSqlQuery &query) +{ + beginResetModel(); + m_data.clear(); + m_rowsAllocated = 0; + m_rowCount = 0; + + /* Looks like empty results have column count set. */ + m_columnCount = query.record().count(); + + endResetModel(); + + appendQueryData(query); +} + +bool TblModel::appendQueryData(QSqlQuery &query) +{ + if (query.record().count() != m_columnCount) { + return false; + } + + beginResetModel(); + + query.first(); + while (query.isActive() && query.isValid()) { + + reserveSpace(); + + QVector row(m_columnCount); + + queryToVector(row, query); + + m_data[m_rowCount++] = row; + + query.next(); + } + + endResetModel(); + + return true; +} QVariant TblModel::_data(const QModelIndex &index, int role) const { diff -Nru datovka-4.8.3/src/models/table_model.h datovka-4.9.3/src/models/table_model.h --- datovka-4.8.3/src/models/table_model.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/models/table_model.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,7 +39,7 @@ * * @param[in] parent Parent object. */ - explicit TblModel(QObject *parent = 0); + explicit TblModel(QObject *parent = Q_NULLPTR); /*! * @brief Returns number of rows under given parent. @@ -98,23 +98,6 @@ int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; /*! - * @brief Sets the content of the model according to the supplied query. - * - * @param[in,out] qyery SQL query result. - */ - virtual - void setQuery(QSqlQuery &query); - - /*! - * @brief Appends data from the supplied query to the model. - * - * @param[in,out] query SQL query result. - * @return True on success. - */ - virtual - bool appendQueryData(QSqlQuery &query); - - /*! * @brief Move rows. * * @param[in] sourceParent Source parent. @@ -143,6 +126,23 @@ protected: /*! + * @brief Sets the content of the model according to the supplied query. + * + * @param[in,out] qyery SQL query result. + */ + virtual + void setQuery(QSqlQuery &query); + + /*! + * @brief Appends data from the supplied query to the model. + * + * @param[in,out] query SQL query result. + * @return True on success. + */ + virtual + bool appendQueryData(QSqlQuery &query); + + /*! * @brief Returns raw data stored under the given role. * * @param[in] index Position. diff -Nru datovka-4.8.3/src/records_management/conversion.cpp datovka-4.9.3/src/records_management/conversion.cpp --- datovka-4.8.3/src/records_management/conversion.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/conversion.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/records_management/conversion.h" + +QList createIdList(const QStringList &strList, bool *ok) +{ + QList idList; + bool iOk = false; + foreach (const QString &str, strList) { + qint64 id = str.toLongLong(&iOk); + idList.append(id); + if (!iOk) { + if (ok != Q_NULLPTR) { + *ok = false; + } + qCritical("Cannot convert '%s' into qint64.", + str.toUtf8().constData()); + return QList(); + } + if (id < 0) { + if (ok != Q_NULLPTR) { + *ok = false; + } + qCritical("%s", "Received negative identifier."); + return QList(); + } + } + + if (ok != Q_NULLPTR) { + *ok = true; + } + return idList; +} diff -Nru datovka-4.8.3/src/records_management/conversion.h datovka-4.9.3/src/records_management/conversion.h --- datovka-4.8.3/src/records_management/conversion.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/conversion.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _CONVERSION_H_ +#define _CONVERSION_H_ + +#include +#include + +/*! + * @brief Convert list of strings into list of qint64. + * + * @param[in] strList String list. + * @param[out] ok Set to true if all entries are successfully converted. + * @return List if qint64. + */ +QList createIdList(const QStringList &strList, bool *ok); + +#endif /* _CONVERSION_H_ */ diff -Nru datovka-4.8.3/src/records_management/gui/dlg_records_management.cpp datovka-4.9.3/src/records_management/gui/dlg_records_management.cpp --- datovka-4.8.3/src/records_management/gui/dlg_records_management.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/gui/dlg_records_management.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/io/records_management_db.h" +#include "src/records_management/gui/dlg_records_management.h" +#include "src/records_management/json/service_info.h" +#include "src/records_management/widgets/svg_view.h" +#include "ui_dlg_records_management.h" + +/*! + * @brief Return disabled palette. + */ +static +const QPalette &disableEditPalette(void) +{ + static QPalette palette; + static bool prepared = false; + if (!prepared) { + palette.setColor(QPalette::Base, Qt::lightGray); + palette.setColor(QPalette::Text, Qt::darkGray); + prepared = true; + } + return palette; +} + +DlgRecordsManagement::DlgRecordsManagement(const QString &urlStr, + const QString &tokenStr, QWidget *parent) + : QDialog(parent), + m_ui(new (std::nothrow) Ui::DlgRecordsManagement), + m_rmc(RecordsManagementConnection::ignoreSslErrorsDflt, this), + m_logoSvg() +{ + m_ui->setupUi(this); + + m_ui->graphicsView->setSvgData(QByteArray()); + + m_ui->urlLine->setText(urlStr); + m_ui->tokenLine->setText(tokenStr); + + m_ui->infoButton->setEnabled(false); + m_ui->eraseButton->setEnabled(!m_ui->urlLine->text().isEmpty() || + !m_ui->tokenLine->text().isEmpty()); + + m_ui->nameLine->setReadOnly(true); + m_ui->nameLine->setPalette(disableEditPalette()); + m_ui->tokenNameLine->setReadOnly(true); + m_ui->tokenNameLine->setPalette(disableEditPalette()); + + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + + connect(m_ui->urlLine, SIGNAL(textChanged(QString)), + this, SLOT(activateServiceButtons())); + connect(m_ui->tokenLine, SIGNAL(textChanged(QString)), + this, SLOT(activateServiceButtons())); + + connect(m_ui->infoButton, SIGNAL(clicked(bool)), + this, SLOT(callServiceInfo())); + connect(m_ui->eraseButton, SIGNAL(clicked(bool)), + this, SLOT(eraseContent())); + + connect(&m_rmc, SIGNAL(connectionError(QString)), + this, SLOT(notifyCommunicationError(QString))); + + loadStoredServiceInfo(); +} + +DlgRecordsManagement::~DlgRecordsManagement(void) +{ + delete m_ui; +} + +bool DlgRecordsManagement::updateSettings( + RecordsManagementSettings &recMgmtSettings, QWidget *parent) +{ + if (Q_NULLPTR == globRecordsManagementDbPtr) { + return false; + } + + DlgRecordsManagement dlg(recMgmtSettings.url, recMgmtSettings.token, + parent); + if (QDialog::Accepted != dlg.exec()) { + return false; + } + + if (!dlg.m_ui->urlLine->text().trimmed().isEmpty()) { + Q_ASSERT(!dlg.m_ui->tokenLine->text().trimmed().isEmpty()); + + /* Update entry. */ + RecordsManagementDb::ServiceInfoEntry entry; + entry.url = dlg.m_ui->urlLine->text().trimmed(); + entry.name = dlg.m_ui->nameLine->text(); + entry.tokenName = dlg.m_ui->tokenNameLine->text(); + entry.logoSvg = dlg.m_logoSvg; + globRecordsManagementDbPtr->updateServiceInfo(entry); + + if (recMgmtSettings.url != dlg.m_ui->urlLine->text()) { + /* Erase all message-related data as URL has changed. */ + globRecordsManagementDbPtr->deleteAllStoredMsg(); + } + } else { + globRecordsManagementDbPtr->deleteAllEntries(); + } + + /* Save changes to settings. */ + recMgmtSettings.url = dlg.m_ui->urlLine->text().trimmed(); + recMgmtSettings.token = dlg.m_ui->tokenLine->text().trimmed(); + + return true; +} + +void DlgRecordsManagement::activateServiceButtons(void) +{ + m_ui->infoButton->setEnabled(!m_ui->urlLine->text().isEmpty() && + !m_ui->tokenLine->text().isEmpty()); + m_ui->eraseButton->setEnabled(!m_ui->urlLine->text().isEmpty() || + !m_ui->tokenLine->text().isEmpty()); + + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); +} + +void DlgRecordsManagement::callServiceInfo(void) +{ + QByteArray response; + + m_rmc.setConnection(m_ui->urlLine->text().trimmed(), + m_ui->tokenLine->text().trimmed()); + + if (m_rmc.communicate(RecordsManagementConnection::SRVC_SERVICE_INFO, + QByteArray(), response)) { + if (!response.isEmpty()) { + bool ok = false; + ServiceInfoResp siRes( + ServiceInfoResp::fromJson(response, &ok)); + if (!ok || !siRes.isValid()) { + QMessageBox::critical(this, + tr("Communication Error"), + tr("Received invalid response.")); + return; + } + + setResponseContent(siRes.logoSvg(), siRes.name(), + siRes.tokenName()); + } else { + QMessageBox::critical(this, tr("Communication Error"), + tr("Received empty response.")); + return; + } + } else { + return; + } + + m_ui->infoButton->setEnabled(false); + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); +} + +void DlgRecordsManagement::eraseContent(void) +{ + m_ui->urlLine->setText(QString()); + m_ui->tokenLine->setText(QString()); + + m_ui->graphicsView->setSvgData(QByteArray()); + m_logoSvg = QByteArray(); + m_ui->nameLine->setText(QString()); + m_ui->tokenNameLine->setText(QString()); + + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); +} + +void DlgRecordsManagement::notifyCommunicationError(const QString &errMsg) +{ + QMessageBox::critical(this, tr("Communication Error"), errMsg); +} + +void DlgRecordsManagement::loadStoredServiceInfo(void) +{ + if (Q_NULLPTR == globRecordsManagementDbPtr) { + return; + } + + RecordsManagementDb::ServiceInfoEntry entry( + globRecordsManagementDbPtr->serviceInfo()); + if (!entry.isValid()) { + return; + } + + setResponseContent(entry.logoSvg, entry.name, entry.tokenName); +} + +void DlgRecordsManagement::setResponseContent(const QByteArray &logoSvg, + const QString &name, const QString &tokenName) +{ + m_ui->graphicsView->setSvgData(logoSvg); + m_logoSvg = logoSvg; + m_ui->nameLine->setText(name); + m_ui->tokenNameLine->setText(tokenName); +} diff -Nru datovka-4.8.3/src/records_management/gui/dlg_records_management.h datovka-4.9.3/src/records_management/gui/dlg_records_management.h --- datovka-4.8.3/src/records_management/gui/dlg_records_management.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/gui/dlg_records_management.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _DLG_RECORDS_MANAGEMENT_H_ +#define _DLG_RECORDS_MANAGEMENT_H_ + +#include +#include + +#include "src/records_management/io/records_management_connection.h" +#include "src/settings/records_management.h" + +namespace Ui { + class DlgRecordsManagement; +} + +/*! + * @brief Encapsulated records management service settings dialogue. + */ +class DlgRecordsManagement : public QDialog { + Q_OBJECT + +private: + /*! + * @brief Constructor. + * + * @param[in] urlStr String containing service location URL. + * @param[in] tokenStr String containing service token. + * @param[in] parent Parent widget. + */ + explicit DlgRecordsManagement(const QString &urlStr, + const QString &tokenStr, QWidget *parent = Q_NULLPTR); + +public: + /*! + * @brief Destructor. + */ + ~DlgRecordsManagement(void); + + /*! + * @brief Update record management settings. + * + * @param[in] recMgmtSettings Settings structure to be modified. + * @param[in] parent Window parent widget. + * @return True when data have been updated, false else. + */ + static + bool updateSettings(RecordsManagementSettings &recMgmtSettings, + QWidget *parent = Q_NULLPTR); + +private slots: + /*! + * @brief Enables service-related buttons. + */ + void activateServiceButtons(void); + + /*! + * @brief calls service info and displays results. + */ + void callServiceInfo(void); + + /*! + * @brief Erases all entries. + */ + void eraseContent(void); + + /*! + * @brief Notifies the user about communication error. + * + * @param[in] errMsg Error message. + */ + void notifyCommunicationError(const QString &errMsg); + +private: + /*! + * @brief Loads service information from storage. + */ + void loadStoredServiceInfo(void); + + /*! + * @brief Set window content according to service info response. + * + * @param[in] logoSvg Raw SVG data. + * @param[in] name Service name. + * @param[in] tokenName Access token name. + */ + void setResponseContent(const QByteArray &logoSvg, const QString &name, + const QString &tokenName); + + Ui::DlgRecordsManagement *m_ui; /*!< UI generated from UI file. */ + + RecordsManagementConnection m_rmc; /*!< Connection to records management service. */ + QByteArray m_logoSvg; /*!< Raw SVG data. */ +}; + +#endif /* _DLG_RECORDS_MANAGEMENT_H_ */ diff -Nru datovka-4.8.3/src/records_management/gui/dlg_records_management_stored.cpp datovka-4.9.3/src/records_management/gui/dlg_records_management_stored.cpp --- datovka-4.8.3/src/records_management/gui/dlg_records_management_stored.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/gui/dlg_records_management_stored.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/graphics/graphics.h" +#include "src/io/records_management_db.h" +#include "src/log/log.h" +#include "src/records_management/gui/dlg_records_management_stored.h" +#include "src/worker/message_emitter.h" +#include "src/worker/pool.h" +#include "src/worker/task_records_management_stored_messages.h" +#include "ui_dlg_records_management_stored.h" + +#define LOGO_EDGE 64 + +#define PROGRESS_MIN 0 +#define PROGRESS_MAX 100 + +#define RUN_DELAY_MS 500 + +DlgRecordsManagementStored::DlgRecordsManagementStored(const QString &urlStr, + const QString &tokenStr, const QList &accounts, QWidget *parent) + : QDialog(parent), + m_ui(new (std::nothrow) Ui::DlgRecordsManagementStored), + m_url(urlStr), + m_token(tokenStr), + m_accounts(accounts), + m_accIdx(0), + m_taskIncr(PROGRESS_MAX / (1.0 + accounts.size())), + m_cancel(false) +{ + Q_ASSERT(!m_url.isEmpty()); + Q_ASSERT(!m_token.isEmpty()); + + m_ui->setupUi(this); + + /* Just to make the progress bar stationary. */ + m_ui->taskLabel->setText(QStringLiteral("\n")); + + loadRecordsManagementPixmap(LOGO_EDGE); + + m_ui->taskProgress->setRange(PROGRESS_MIN, PROGRESS_MAX); + m_ui->taskProgress->setValue(PROGRESS_MIN); + + m_ui->buttonBox->setStandardButtons(QDialogButtonBox::Cancel); + + connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(cancelLoop())); + connect(&globMsgProcEmitter, + SIGNAL(recordsManagementStoredMessagesFinished(QString)), + this, SLOT(downloadAndStoreContinue())); + + /* Currently there is no means how to detect whether dialogue is shown. */ + QTimer::singleShot(RUN_DELAY_MS, this, SLOT(downloadAndStoreStart())); +} + +DlgRecordsManagementStored::~DlgRecordsManagementStored(void) +{ + delete m_ui; +} + +bool DlgRecordsManagementStored::updateStoredInformation( + const RecordsManagementSettings &recMgmtSettings, + const QList &accounts, QWidget *parent) +{ + if (Q_NULLPTR == globRecordsManagementDbPtr) { + return false; + } + + if (!recMgmtSettings.isSet()) { + return false; + } + + DlgRecordsManagementStored dlg(recMgmtSettings.url, + recMgmtSettings.token, accounts, parent); + dlg.exec(); + + return true; +} + +void DlgRecordsManagementStored::downloadAndStoreStart(void) +{ + QProgressBar *pBar = m_ui->taskProgress; + + /* Update already held information. */ + { + if (m_cancel) { + goto cancel; + } + + m_ui->taskLabel->setText( + tr("Updating stored information about messages.") + + QStringLiteral("\n")); + + TaskRecordsManagementStoredMessages *task = + new (::std::nothrow) TaskRecordsManagementStoredMessages( + m_url, m_token, + TaskRecordsManagementStoredMessages::RM_UPDATE_STORED, + Q_NULLPTR); + if (Q_NULLPTR == task) { + logErrorNL("%s", + "Cannot create stored_files update task."); + return; + } + task->setAutoDelete(true); + /* Run in background. */ + globWorkPool.assignHi(task); + + return; + } + +cancel: + pBar->setValue(PROGRESS_MAX); + + this->close(); +} + +void DlgRecordsManagementStored::downloadAndStoreContinue(void) +{ + QProgressBar *pBar = m_ui->taskProgress; + + pBar->setValue(pBar->value() + m_taskIncr); + + while (m_accIdx < m_accounts.size()) { + if (m_cancel) { + goto cancel; + } + + const AcntData &account(m_accounts.at(m_accIdx)); + + m_ui->taskLabel->setText( + tr("Downloading information about messages from account:\n%1 (%2).") + .arg(account.accountName).arg(account.userName)); + + if (account.dbSet == Q_NULLPTR) { + Q_ASSERT(0); + pBar->setValue(pBar->value() + m_taskIncr); + ++m_accIdx; + continue; + } + + TaskRecordsManagementStoredMessages *task = + new (::std::nothrow) TaskRecordsManagementStoredMessages( + m_url, m_token, + TaskRecordsManagementStoredMessages::RM_DOWNLOAD_ALL, + account.dbSet); + if (Q_NULLPTR == task) { + logErrorNL("Cannot create stored_files task for '%s'.", + account.userName.toUtf8().constData()); + pBar->setValue(pBar->value() + m_taskIncr); + ++m_accIdx; + continue; + } + task->setAutoDelete(true); + /* Run in background. */ + globWorkPool.assignHi(task); + + ++m_accIdx; + return; + } + +cancel: + pBar->setValue(PROGRESS_MAX); + + this->close(); +} + +void DlgRecordsManagementStored::cancelLoop(void) +{ + m_cancel = true; +} + +void DlgRecordsManagementStored::loadRecordsManagementPixmap(int width) +{ + if (Q_NULLPTR == globRecordsManagementDbPtr) { + return; + } + + RecordsManagementDb::ServiceInfoEntry entry( + globRecordsManagementDbPtr->serviceInfo()); + if (!entry.isValid() || entry.logoSvg.isEmpty()) { + return; + } + QPixmap pixmap(Graphics::pixmapFromSvg(entry.logoSvg, width)); + if (!pixmap.isNull()) { + m_ui->pixmapLabel->setPixmap(pixmap); + } +} diff -Nru datovka-4.8.3/src/records_management/gui/dlg_records_management_stored.h datovka-4.9.3/src/records_management/gui/dlg_records_management_stored.h --- datovka-4.8.3/src/records_management/gui/dlg_records_management_stored.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/gui/dlg_records_management_stored.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _DLG_RECORDS_MANAGEMENT_STORED_H_ +#define _DLG_RECORDS_MANAGEMENT_STORED_H_ + +#include +#include +#include + +#include "src/settings/records_management.h" + +namespace Ui { + class DlgRecordsManagementStored; +} + +class MessageDbSet; /* Forward declaration. */ + +/*! + * @brief Encapsulated records management service stored messages dialogue. + */ +class DlgRecordsManagementStored : public QDialog { + Q_OBJECT + +public: + /*! + * @brief Describes account information. + */ + class AcntData { + public: + AcntData(const QString &aName, const QString &uName, + const MessageDbSet *dSet) + : accountName(aName), userName(uName), dbSet(dSet) + { + } + + QString accountName; /*!< Account name. */ + QString userName; /*!< User name (login). */ + const MessageDbSet *dbSet; /*!< Database set related to account. */ + }; + +private: + /*! + * @brief Constructor. + * + * @param[in] urlStr String containing service location URL. + * @param[in] tokenStr String containing service token. + * @param[in] accounts List of accounts to take message identifiers from. + * @param[in] parent Parent widget. + */ + explicit DlgRecordsManagementStored(const QString &urlStr, + const QString &tokenStr, const QList &accounts, + QWidget *parent = Q_NULLPTR); + +public: + /*! + * @brief Destructor. + */ + ~DlgRecordsManagementStored(void); + + /*! + * @brief Updates stored information about messages uploaded into + * records management service. + * + * @param[in] recMgmtSettings Settings containing URL and token. + * @param[in] accounts List of accounts to take message identifiers from. + * @param[in] parent Parent widget. + */ + static + bool updateStoredInformation( + const RecordsManagementSettings &recMgmtSettings, + const QList &accounts, QWidget *parent = Q_NULLPTR); + +private slots: + /*! + * @brief Starts the download action. + */ + void downloadAndStoreStart(void); + + /*! + * @brief Continues with the download action. + */ + void downloadAndStoreContinue(void); + + /*! + * @brief Set variable to cancel the download loop. + */ + void cancelLoop(void); + +private: + /*! + * @brief Loads records management service logo and sets the logo label. + * + * @param[in] width Sets the image width (and height). + */ + void loadRecordsManagementPixmap(int width); + + Ui::DlgRecordsManagementStored *m_ui; /*!< UI generated from UI file. */ + + const QString m_url; /*!< Records management service URL. */ + const QString m_token; /*!< Records management service access token. */ + const QList &m_accounts; /*!< Account to use. */ + int m_accIdx; /*!< Index of next account to be processed. */ + + int m_taskIncr; /*!< Task progress bar increment. */ + + bool m_cancel; /*!< Set by slot to cancel loop. */ +}; + +#endif /* _DLG_RECORDS_MANAGEMENT_STORED_H_ */ diff -Nru datovka-4.8.3/src/records_management/gui/dlg_records_management_upload.cpp datovka-4.9.3/src/records_management/gui/dlg_records_management_upload.cpp --- datovka-4.8.3/src/records_management/gui/dlg_records_management_upload.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/gui/dlg_records_management_upload.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include + +#include "src/graphics/graphics.h" +#include "src/io/records_management_db.h" +#include "src/log/log.h" +#include "src/models/sort_filter_proxy_model.h" +#include "src/records_management/gui/dlg_records_management_upload.h" +#include "src/records_management/json/upload_file.h" +#include "src/records_management/json/upload_hierarchy.h" +#include "ui_dlg_records_management_upload.h" + +#define LOGO_EDGE 64 + +#define RUN_DELAY_MS 500 + +DlgRecordsManagementUpload::DlgRecordsManagementUpload(const QString &urlStr, + const QString &tokenStr, qint64 dmId, QWidget *parent) + : QDialog(parent), + m_ui(new (std::nothrow) Ui::DlgRecordsManagementUpload), + m_url(urlStr), + m_token(tokenStr), + m_rmc(RecordsManagementConnection::ignoreSslErrorsDflt, this), + m_uploadModel(), + m_uploadProxyModel(), + m_selectedUploadIds() +{ + m_ui->setupUi(this); + + loadRecordsManagementPixmap(LOGO_EDGE); + m_ui->appealLabel->setText( + tr("Select the location where you want\nto upload the message '%1' into.") + .arg(dmId)); + + connect(m_ui->reloadButton, SIGNAL(clicked(bool)), + this, SLOT(callUploadHierarchy())); + + m_ui->filterLine->setClearButtonEnabled(true); + connect(m_ui->filterLine, SIGNAL(textChanged(QString)), + this, SLOT(filterHierarchy(QString))); + + m_ui->uploadView->setNarrowedLineHeight(); + + m_ui->uploadView->setModel(&m_uploadProxyModel); + m_uploadProxyModel.setSourceModel(&m_uploadModel); + connect(m_ui->uploadView->selectionModel(), + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(uploadHierarchySelectionChanged())); + + m_ui->uploadView->sortByColumn(0, Qt::AscendingOrder); + m_ui->uploadView->setSortingEnabled(true); + + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + + connect(&m_rmc, SIGNAL(connectionError(QString)), + this, SLOT(notifyCommunicationError(QString))); + + /* Currently there is no means how to detect whether dialogue is shown. */ + QTimer::singleShot(RUN_DELAY_MS, this, SLOT(callUploadHierarchy())); +} + +DlgRecordsManagementUpload::~DlgRecordsManagementUpload(void) +{ + delete m_ui; +} + +bool DlgRecordsManagementUpload::uploadMessage( + const RecordsManagementSettings &recMgmtSettings, qint64 dmId, + const QString &msgFileName, const QByteArray &msgData, QWidget *parent) +{ + if (!recMgmtSettings.isSet()) { + Q_ASSERT(0); + return false; + } + + if (msgFileName.isEmpty() || msgData.isEmpty()) { + Q_ASSERT(0); + return false; + } + + DlgRecordsManagementUpload dlg(recMgmtSettings.url, + recMgmtSettings.token, dmId, parent); + if (QDialog::Accepted != dlg.exec()) { + return false; + } + + if (dlg.m_selectedUploadIds.isEmpty()) { + Q_ASSERT(0); + return false; + } + + /* The connection should be still working. */ + return uploadFile(dlg.m_rmc, dmId, dlg.m_selectedUploadIds, msgFileName, + msgData, parent); +} + +void DlgRecordsManagementUpload::callUploadHierarchy(void) +{ + QByteArray response; + + /* Clear model. */ + m_uploadModel.setHierarchy(UploadHierarchyResp()); + + m_rmc.setConnection(m_url, m_token); + + if (m_rmc.communicate(RecordsManagementConnection::SRVC_UPLOAD_HIERARCHY, + QByteArray(), response)) { + if (!response.isEmpty()) { + bool ok = false; + UploadHierarchyResp uhRes( + UploadHierarchyResp::fromJson(response, &ok)); + if (!ok || !uhRes.isValid()) { + QMessageBox::critical(this, + tr("Communication Error"), + tr("Received invalid response.")); + return; + } + + m_uploadModel.setHierarchy(uhRes); + m_ui->uploadView->expandAll(); + } else { + QMessageBox::critical(this, tr("Communication Error"), + tr("Received empty response.")); + return; + } + } else { + return; + } +} + +void DlgRecordsManagementUpload::filterHierarchy(const QString &text) +{ + m_uploadProxyModel.setFilterRole(UploadHierarchyModel::ROLE_FILTER); + + m_uploadProxyModel.setFilterRegExp(QRegExp(text, + Qt::CaseInsensitive, QRegExp::FixedString)); + + m_uploadProxyModel.setFilterKeyColumn(0); + + m_ui->uploadView->expandAll(); + + if (text.isEmpty()) { + m_ui->filterLine->setStyleSheet( + SortFilterProxyModel::blankFilterEditStyle); + } else if (m_uploadProxyModel.rowCount() != 0) { + m_ui->filterLine->setStyleSheet( + SortFilterProxyModel::foundFilterEditStyle); + } else { + m_ui->filterLine->setStyleSheet( + SortFilterProxyModel::notFoundFilterEditStyle); + } +} + +void DlgRecordsManagementUpload::uploadHierarchySelectionChanged(void) +{ + m_selectedUploadIds.clear(); + + const QModelIndexList indexes( + m_ui->uploadView->selectionModel()->selectedIndexes()); + + /* Entries with empty identifiers should not be able to be selected. */ + foreach (const QModelIndex &index, indexes) { + const QString uploadId( + index.data(UploadHierarchyModel::ROLE_ID).toString()); + if (!uploadId.isEmpty()) { + m_selectedUploadIds.append(uploadId); + } else { + Q_ASSERT(0); + } + } + + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled( + !indexes.isEmpty()); +} + +void DlgRecordsManagementUpload::notifyCommunicationError(const QString &errMsg) +{ + QMessageBox::critical(this, tr("Communication Error"), errMsg); +} + +void DlgRecordsManagementUpload::loadRecordsManagementPixmap(int width) +{ + if (Q_NULLPTR == globRecordsManagementDbPtr) { + return; + } + + RecordsManagementDb::ServiceInfoEntry entry( + globRecordsManagementDbPtr->serviceInfo()); + if (!entry.isValid() || entry.logoSvg.isEmpty()) { + return; + } + QPixmap pixmap(Graphics::pixmapFromSvg(entry.logoSvg, width)); + if (!pixmap.isNull()) { + m_ui->pixmapLabel->setPixmap(pixmap); + } +} + +/*! + * @brief Process upload file service response. + * + * @note Stores location into database. + * + * @param[in] ifRes Response structure. + * @param[in] dmId Message identifier. + * @patam[in] parent Parent window for potential error dialogues. + * @return True if response could be processed and location has been saved. + */ +static +bool processUploadFileResponse(const UploadFileResp &ufRes, qint64 dmId, + QWidget *parent = Q_NULLPTR) +{ + if (ufRes.id().isEmpty()) { + QString errorMessage( + QObject::tr("Message '%1' could not be uploaded.") + .arg(dmId)); + errorMessage += QLatin1String("\n"); + errorMessage += QObject::tr("Received error") + + QLatin1String(": ") + ufRes.error().trVerbose(); + errorMessage += QLatin1String("\n"); + errorMessage += ufRes.error().description(); + + QMessageBox::critical(parent, QObject::tr("File Upload Error"), + errorMessage); + return false; + } + + QMessageBox::information(parent, QObject::tr("Successful File Upload"), + QObject::tr("Message '%1' was successfully uploaded into the records management service.").arg(dmId) + + QStringLiteral("\n") + + QObject::tr("It can be now found in the records management service in these locations:") + + QStringLiteral("\n") + + ufRes.locations().join(QStringLiteral("\n"))); + + if (!ufRes.locations().isEmpty()) { + logInfoNL( + "Message '%" PRId64 "'has been stored into records management service.", + dmId); + if (Q_NULLPTR != globRecordsManagementDbPtr) { + return globRecordsManagementDbPtr->updateStoredMsg(dmId, + ufRes.locations()); + } else { + Q_ASSERT(0); + return true; + } + } else { + logErrorNL( + "Received empty location list when uploading message '%" PRId64 "'.", + dmId); + } + + return false; +} + +bool DlgRecordsManagementUpload::uploadFile(RecordsManagementConnection &rmc, + qint64 dmId, const QStringList &uploadIds, const QString &msgFileName, + const QByteArray &msgData, QWidget *parent) +{ + UploadFileReq ufReq(uploadIds, msgFileName, msgData); + if (!ufReq.isValid()) { + Q_ASSERT(0); + return false; + } + + QByteArray response; + + if (rmc.communicate(RecordsManagementConnection::SRVC_UPLOAD_FILE, + ufReq.toJson(), response)) { + if (!response.isEmpty()) { + bool ok = false; + UploadFileResp ufRes( + UploadFileResp::fromJson(response, &ok)); + if (!ok || !ufRes.isValid()) { + QMessageBox::critical(parent, + tr("Communication Error"), + tr("Received invalid response.")); + logErrorNL("Received invalid response '%s'.", + QString(response).toUtf8().constData()); + return false; + } + + return processUploadFileResponse(ufRes, dmId, parent); + } else { + QMessageBox::critical(parent, tr("Communication Error"), + tr("Received empty response.")); + return false; + } + } else { + return false; + } +} diff -Nru datovka-4.8.3/src/records_management/gui/dlg_records_management_upload.h datovka-4.9.3/src/records_management/gui/dlg_records_management_upload.h --- datovka-4.8.3/src/records_management/gui/dlg_records_management_upload.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/gui/dlg_records_management_upload.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _DLG_RECORDS_MANAGEMENT_UPLOAD_H_ +#define _DLG_RECORDS_MANAGEMENT_UPLOAD_H_ + +#include +#include +#include +#include + +#include "src/records_management/io/records_management_connection.h" +#include "src/records_management/models/upload_hierarchy_model.h" +#include "src/records_management/models/upload_hierarchy_proxy_model.h" +#include "src/settings/records_management.h" + +namespace Ui { + class DlgRecordsManagementUpload; +} + +/*! + * @brief Encapsulated records management service upload dialogue. + */ +class DlgRecordsManagementUpload : public QDialog { + Q_OBJECT + +private: + /*! + * @brief Constructor. + * + * @param[in] urlStr String containing service location URL. + * @param[in] tokenStr String containing service token. + * @param[in] dmId Message identifier. + * @param[in] parent Parent widget. + */ + explicit DlgRecordsManagementUpload(const QString &urlStr, + const QString &tokenStr, qint64 dmId, QWidget *parent = Q_NULLPTR); + +public: + /*! + * @brief Destructor. + */ + ~DlgRecordsManagementUpload(void); + + /*! + * @brief Upload message into records management service. + * + * @param[in] recMgmtSettings Settings containing URL and token. + * @param[in] dmId Message identifier. + * @param[in] msgFileName Message file name. + * @param[in] msgData Message data. + * @param[in] parent Window parent widget. + * @return True when data have been updated, false else. + */ + static + bool uploadMessage(const RecordsManagementSettings &recMgmtSettings, + qint64 dmId, const QString &msgFileName, const QByteArray &msgData, + QWidget *parent = Q_NULLPTR); + +private slots: + /*! + * @brief Download upload hierarchy and set model. + */ + void callUploadHierarchy(void); + + /*! + * @brief Filter upload hierarchy. + * + * @param[in] text Filter text. + */ + void filterHierarchy(const QString &text); + + /*! + * @brief Checks selection and activates OK button. + */ + void uploadHierarchySelectionChanged(void); + + /*! + * @brief Notifies the user about communication error. + * + * @param[in] errMsg Error message. + */ + void notifyCommunicationError(const QString &errMsg); + +private: + /*! + * @brief Loads records management service logo and sets the logo label. + * + * @param[in] width Sets the image width (and height). + */ + void loadRecordsManagementPixmap(int width); + + /*! + * @brief Upload file into records management service. + * + * @param[in,out] rmc Connection object. + * @param[in] uploadIds Upload location identifiers. + * @param[in] dmId Message identifier. + * @param[in] msgFileName Message file name. + * @param[in] msgData Message data. + * @param[in] parent Window parent widget. + * @return True on success. + */ + static + bool uploadFile(RecordsManagementConnection &rmc, qint64 dmId, + const QStringList &uploadIds, const QString &msgFileName, + const QByteArray &msgData, QWidget *parent = Q_NULLPTR); + + Ui::DlgRecordsManagementUpload *m_ui; /*!< UI generated from UI file. */ + + const QString m_url; /*!< Service URL. */ + const QString m_token; /*!< Service token. */ + + RecordsManagementConnection m_rmc; /*!< Connection to records management service. */ + + UploadHierarchyModel m_uploadModel; /*!< Upload hierarchy model. */ + UploadHierarchyProxyModel m_uploadProxyModel; /*!< Used for filtering. */ + + QStringList m_selectedUploadIds; /*!< Upload location identifiers. */ +}; + +#endif /* _DLG_RECORDS_MANAGEMENT_UPLOAD_H_ */ diff -Nru datovka-4.8.3/src/records_management/io/records_management_connection.cpp datovka-4.9.3/src/records_management/io/records_management_connection.cpp --- datovka-4.8.3/src/records_management/io/records_management_connection.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/io/records_management_connection.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include + +#include "src/records_management/io/records_management_connection.h" + +/* Must be set to false for production releases. */ +const bool RecordsManagementConnection::ignoreSslErrorsDflt = true; + +#define logFuncCall() \ + qDebug("%s()", __func__) + +/*! + * @brief Converts service identifier onto service name. + */ +static +const QString &serviceName(enum RecordsManagementConnection::ServiceId srvcId) +{ + static const QString SrvServiceInfo(QStringLiteral("service_info")); + static const QString SrvUploadHierarchy(QStringLiteral("upload_hierarchy")); + static const QString SrvUploadFile(QStringLiteral("upload_file")); + static const QString SrvStoredFiles(QStringLiteral("stored_files")); + static const QString InvalidService; + + switch (srvcId) { + case RecordsManagementConnection::SRVC_SERVICE_INFO: + return SrvServiceInfo; + break; + case RecordsManagementConnection::SRVC_UPLOAD_HIERARCHY: + return SrvUploadHierarchy; + break; + case RecordsManagementConnection::SRVC_UPLOAD_FILE: + return SrvUploadFile; + break; + case RecordsManagementConnection::SRVC_STORED_FILES: + return SrvStoredFiles; + break; + default: + Q_ASSERT(0); + return InvalidService; + break; + } +} + +/*! + * @brief Create URL from base URL and from service identifier. + */ +static +QUrl constructUrl(QString baseUrl, + enum RecordsManagementConnection::ServiceId srvcId) +{ + const QString &srvcName(serviceName(srvcId)); + + if (baseUrl.isEmpty() || srvcName.isEmpty()) { + return QUrl(); + } + + if (baseUrl.at(baseUrl.length() - 1) != '/') { + baseUrl += '/'; + } + return QUrl(baseUrl + srvcName); +} + +RecordsManagementConnection::RecordsManagementConnection(bool ignoreSslErrors, + QObject *parent) + : QObject(parent), + m_baseUrlStr(), + m_tokenStr(), + m_agentName(), + m_timeOut(60000), /* Milliseconds. */ + m_ignoreSslErrors(ignoreSslErrors), + m_nam(this) +{ + connect(&m_nam, SIGNAL(sslErrors(QNetworkReply *, const QList)), + this, SLOT(handleSslErrors(QNetworkReply *, const QList))); +} + +void RecordsManagementConnection::setConnection(const QString &baseUrl, + const QString &token) +{ + m_baseUrlStr = baseUrl; + m_tokenStr = token; +} + +bool RecordsManagementConnection::communicate(enum ServiceId srvcId, + const QByteArray &requestData, QByteArray &replyData) +{ + logFuncCall(); + + QNetworkRequest request(createRequest(srvcId)); + + QNetworkReply *reply = sendRequest(request, requestData); + if (reply == Q_NULLPTR) { + return false; + } + + /* Set timeout timer */ + QTimer timer; + timer.setSingleShot(true); + QEventLoop eventLoop; + connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); + connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); + timer.start(m_timeOut); + eventLoop.exec(); + + qDebug("Loop exited, reply finished: %d", reply->isFinished()); + QList headerList(reply->rawHeaderList()); + if (!reply->rawHeaderPairs().isEmpty()) { + qDebug("%s", "Received raw headers:"); + foreach (const QNetworkReply::RawHeaderPair &pair, + reply->rawHeaderPairs()) { + qDebug("%s: %s", pair.first.constData(), + pair.second.constData()); + } + } + + bool retVal = false; + replyData.clear(); + + if (timer.isActive()) { + timer.stop(); + retVal = processReply(reply, replyData); + if (!retVal && (Q_NULLPTR != reply)) { + emit connectionError(reply->errorString()); + } + } else { + /* Timeout expired. */ + disconnect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); + qCritical("Connection timed out. Check your internet connection."); + reply->abort(); + } + + reply->deleteLater(); reply = Q_NULLPTR; + + return retVal; +} + +static +bool readAndAddCert(const QByteArray &certData, QSsl::EncodingFormat fmt) +{ + if (certData.isEmpty()) { + Q_ASSERT(0); + return false; + } + + QSslCertificate cert(certData, fmt); + if (certData.isNull()) { + return false; + } + + QSslSocket::addDefaultCaCertificate(cert); + + return true; +} + +bool RecordsManagementConnection::addTrustedCertificate(const QString &filePath) +{ + QByteArray certData; + + { + QFile certFile(filePath); + if (!certFile.open(QIODevice::ReadOnly)) { + return false; + } + certData = certFile.readAll(); + certFile.close(); + } + if (certData.isEmpty()) { + return false; + } + + if (readAndAddCert(certData, QSsl::Pem)) { + qDebug("Read PEN certificate '%s'.", + filePath.toUtf8().constData()); + return true; + } else { + qWarning("Supplied certificate '%s' is not in PEM format.", + filePath.toUtf8().constData()); + } + if (readAndAddCert(certData, QSsl::Der)) { + qDebug("Read DER certificate '%s'.", + filePath.toUtf8().constData()); + return true; + } else { + qWarning("Supplied certificate '%s' is not in DER format.", + filePath.toUtf8().constData()); + } + + qCritical("Could not read certificate '%s'.", + filePath.toUtf8().constData()); + return false; +} + +void RecordsManagementConnection::handleSslErrors(QNetworkReply *reply, + const QList &errors) +{ + Q_UNUSED(reply); + + QString errMsg("Unspecified SSL error."); + + if (!errors.isEmpty()) { + QStringList errList; + foreach (const QSslError &error, errors) { + errList.append(error.errorString()); + } + errMsg = errList.join(QStringLiteral("; ")); + } + + qCritical("%s", errMsg.toUtf8().constData()); + emit connectionError(errMsg); + + if (m_ignoreSslErrors) { + qWarning("Ignoring obtained SSL errors."); + emit connectionError(QStringLiteral("Ignoring obtained SSL errors.")); + + if (reply != Q_NULLPTR) { + reply->ignoreSslErrors(); + } + } +} + +QNetworkRequest RecordsManagementConnection::createRequest( + enum ServiceId srvcId) const +{ + logFuncCall(); + + QNetworkRequest request; + + request.setUrl(constructUrl(m_baseUrlStr, srvcId)); + + /* Fill request header. */ + request.setRawHeader("User-Agent", m_agentName.toUtf8()); + request.setRawHeader("Host", request.url().host().toUtf8()); + request.setRawHeader("Authentication", m_tokenStr.toUtf8()); + request.setRawHeader("Accept", "application/json"); + request.setRawHeader("Content-Type", "application/json"); + + return request; +} + +QNetworkReply *RecordsManagementConnection::sendRequest( + const QNetworkRequest &request, const QByteArray &data) +{ + logFuncCall(); + + switch (m_nam.networkAccessible()) { + case QNetworkAccessManager::UnknownAccessibility: + case QNetworkAccessManager::NotAccessible: + qCritical("%s", + "Internet connection is probably not available. Check your network settings."); + return Q_NULLPTR; + break; + default: + break; + } + + QNetworkReply *reply = Q_NULLPTR; + + if (data.isEmpty()) { + reply = m_nam.get(request); + } else { + reply = m_nam.post(request, data); + } + + if (reply == Q_NULLPTR) { + qCritical("%s", "No reply."); + return Q_NULLPTR; + } + + return reply; +} + +bool RecordsManagementConnection::processReply(QNetworkReply *reply, + QByteArray &replyData) +{ + logFuncCall(); + + if (reply == Q_NULLPTR) { + Q_ASSERT(0); + return false; + } + + /* Response status code */ + int statusCode = reply->attribute( + QNetworkRequest::HttpStatusCodeAttribute).toInt(); +#if 0 + /* Store cookies */ + QVariant variantCookies = + reply->header(QNetworkRequest::SetCookieHeader); + QList listOfCookies( + qvariant_cast< QList >(variantCookies)); +#endif + + replyData = reply->readAll(); + + QVariant possibleRedirectUrl; + + switch (statusCode) { + case 200: /* 200 OK */ + break; + case 302: /* 302 Found */ + possibleRedirectUrl = reply->attribute( + QNetworkRequest::RedirectionTargetAttribute); + qWarning("Redirection '%s'?", + possibleRedirectUrl.toString().toUtf8().constData()); + // possibleRedirectUrl.toString(); + break; + default: /* Any other error. */ + qCritical("%s", reply->errorString().toUtf8().constData()); + return false; + break; + } + + return true; +} diff -Nru datovka-4.8.3/src/records_management/io/records_management_connection.h datovka-4.9.3/src/records_management/io/records_management_connection.h --- datovka-4.8.3/src/records_management/io/records_management_connection.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/io/records_management_connection.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _RECORDS_MANAGEMENT_CONNECTION_H_ +#define _RECORDS_MANAGEMENT_CONNECTION_H_ + +#include +#include +#include +#include +#include +#include + +/*! + * @brief Encapsulates connection to records management service. + */ +class RecordsManagementConnection : public QObject { + Q_OBJECT + +public: + /*! + * @brief Records management service identifiers. + */ + enum ServiceId { + SRVC_SERVICE_INFO, + SRVC_UPLOAD_HIERARCHY, + SRVC_UPLOAD_FILE, + SRVC_STORED_FILES + }; + + /*! + * @brief Use for controlling of global behaviour on SSL errors. + */ + static + const bool ignoreSslErrorsDflt; + + /*! + * @brief Constructor. + */ + explicit RecordsManagementConnection(bool ignoreSslErrors = false, + QObject *parent = Q_NULLPTR); + + /*! + * @brief Set connection data. + * + * @param[in] baseUrl Service base URL. + * @param[in] token Authentication token. + */ + void setConnection(const QString &baseUrl, const QString &token); + + /*! + * @brief Send request and wait for reply. + * + * @param[in] srvcId Srvice identifier. + */ + bool communicate(enum ServiceId srvcId, const QByteArray &requestData, + QByteArray &replyData); + + /*! + * @brief Add certificate to certificate store. + * + * @param[in] filePath Path to certificate file. + * @return True on success. + */ + static + bool addTrustedCertificate(const QString &filePath); + +signals: + /*! + * @brief Emitted when some error during communication occurs. + * + * @param[in] message Message string containing error description. + */ + void connectionError(const QString &message); + +private slots: + void handleSslErrors(QNetworkReply *reply, + const QList &errors); + +private: + /*! + * @brief Create network request. + * + * @param[in] srvcId Srvice identifier. + * @return Created network request. + */ + QNetworkRequest createRequest(enum ServiceId srvcId) const; + + /*! + * @brief Send request. + * + * @param[in] request Network request. + * @param[in] data Data to be sent along with the request. + * @return Null pointer on failure. + */ + QNetworkReply *sendRequest(const QNetworkRequest &request, + const QByteArray &data); + + static + bool processReply(QNetworkReply *reply, QByteArray &replyData); + + QString m_baseUrlStr; /*!< Service base URL. */ + QString m_tokenStr; /*!< Authentication token. */ + QString m_agentName; /*!< Usually the application name. */ + + unsigned int m_timeOut; /*!< Communication timeout. */ + bool m_ignoreSslErrors; /*!< True if SSL errors should be ignored. */ + QNetworkAccessManager m_nam; /*!< Network access manager. */ +}; + +#endif /* _RECORDS_MANAGEMENT_CONNECTION_H_ */ diff -Nru datovka-4.8.3/src/records_management/json/entry_error.cpp datovka-4.9.3/src/records_management/json/entry_error.cpp --- datovka-4.8.3/src/records_management/json/entry_error.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/entry_error.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include + +#include "src/records_management/json/entry_error.h" +#include "src/records_management/json/helper.h" + +static +const QString keyCode("code"); +static +const QString keyDescription("description"); + +static const QString strNoError("NO_ERROR"); /* This one should not be used. */ +static const QString strMalformedRequest("MALFORMED_REQUEST"); +static const QString strMissingIdentifier("MISSING_IDENTIFIER"); +static const QString strWrongIdentifier("WRONG_IDENTIFIER"); +static const QString strUnsupportedFileFormat("UNSUPPORTED_FILE_FORMAT"); +static const QString strAlreadyPresent("ALREADY_PRESENT"); +static const QString strLimitExceeded("LIMIT_EXCEEDED"); +static const QString strUnspecified("UNSPECIFIED"); + +ErrorEntry::ErrorEntry(void) + : m_code(ERR_NO_ERROR), + m_description() +{ +} + +ErrorEntry::ErrorEntry(enum Code code, const QString &description) + : m_code(code), + m_description(description) +{ +} + +ErrorEntry::ErrorEntry(const ErrorEntry &ee) + : m_code(ee.m_code), + m_description(ee.m_description) +{ +} + +enum ErrorEntry::Code ErrorEntry::code(void) const +{ + return m_code; +} + +const QString &ErrorEntry::description(void) const +{ + return m_description; +} + +bool ErrorEntry::fromJsonVal(const QJsonValue *jsonVal) +{ + if (jsonVal == Q_NULLPTR) { + Q_ASSERT(0); + return false; + } + + if (jsonVal->isNull()) { + m_code = ERR_NO_ERROR; + m_description.clear(); + return true; + } + + if (!jsonVal->isObject()) { + return false; + } + + QJsonObject jsonObj(jsonVal->toObject()); + + QString codeStr, descrStr; + if (!JsonHelper::readString(jsonObj, keyCode, codeStr, false)) { + return false; + } + if (!JsonHelper::readString(jsonObj, keyDescription, descrStr, false)) { + return false; + } + + bool ok = false; + enum Code code = stringToCode(codeStr, &ok); + if (!ok) { + return false; + } + + m_code = code; + m_description = descrStr; + return true; +} + +bool ErrorEntry::toJsonVal(QJsonValue *jsonVal) const +{ + if (jsonVal == Q_NULLPTR) { + Q_ASSERT(0); + return false; + } + + if (m_code == ERR_NO_ERROR) { + *jsonVal = QJsonValue(); + return true; + } + + QJsonObject jsonObj; + jsonObj.insert(keyCode, codeToString(m_code)); + jsonObj.insert(keyDescription, m_description); + *jsonVal = jsonObj; + return true; +} + +QString ErrorEntry::trVerbose(void) const +{ + QString retStr(codeToString(m_code) + QLatin1String(" (")); + QString explanation; + + switch (m_code) { + case ERR_NO_ERROR: + explanation = tr("No error occurred"); + break; + case ERR_MALFORMED_REQUEST: + explanation = tr("Request was malformed"); + break; + case ERR_MISSING_IDENTIFIER: + explanation = tr("Identifier is missing"); + break; + case ERR_WRONG_IDENTIFIER: + explanation = tr("Supplied identifier is wrong"); + break; + case ERR_UNSUPPORTED_FILE_FORMAT: + explanation = tr("File format is not supported"); + break; + case ERR_ALREADY_PRESENT: + explanation = tr("Data are already present"); + break; + case ERR_LIMIT_EXCEEDED: + explanation = tr("Service limit was exceeded"); + break; + case ERR_UNSPECIFIED: + explanation = tr("Unspecified error"); + break; + default: + Q_ASSERT(0); + explanation = tr("Unknown error"); + break; + } + + retStr += explanation + QLatin1String(")"); + return retStr; +} + +const QString &ErrorEntry::codeToString(enum Code code) +{ + switch (code) { + case ERR_NO_ERROR: + Q_ASSERT(0); /* This one should never occur. */ + return strNoError; + break; + case ERR_MALFORMED_REQUEST: + return strMalformedRequest; + break; + case ERR_MISSING_IDENTIFIER: + return strMissingIdentifier; + break; + case ERR_WRONG_IDENTIFIER: + return strWrongIdentifier; + break; + case ERR_UNSUPPORTED_FILE_FORMAT: + return strUnsupportedFileFormat; + break; + case ERR_ALREADY_PRESENT: + return strAlreadyPresent; + break; + case ERR_LIMIT_EXCEEDED: + return strLimitExceeded; + break; + case ERR_UNSPECIFIED: + return strUnspecified; + break; + default: + Q_ASSERT(0); + return strUnspecified; + break; + } +} + +enum ErrorEntry::Code ErrorEntry::stringToCode(const QString &str, bool *ok) +{ + if (str == strNoError) { + if (ok != Q_NULLPTR) { + *ok = true; + } + return ErrorEntry::ERR_NO_ERROR; + } else if (str == strMalformedRequest) { + if (ok != Q_NULLPTR) { + *ok = true; + } + return ErrorEntry::ERR_MALFORMED_REQUEST; + } else if (str == strMissingIdentifier) { + if (ok != Q_NULLPTR) { + *ok = true; + } + return ERR_MISSING_IDENTIFIER; + } else if (str == strWrongIdentifier) { + if (ok != Q_NULLPTR) { + *ok = true; + } + return ERR_WRONG_IDENTIFIER; + } else if (str == strUnsupportedFileFormat) { + if (ok != Q_NULLPTR) { + *ok = true; + } + return ErrorEntry::ERR_UNSUPPORTED_FILE_FORMAT; + } else if (str == strAlreadyPresent) { + if (ok != Q_NULLPTR) { + *ok = true; + } + return ErrorEntry::ERR_ALREADY_PRESENT; + } else if (str == strLimitExceeded) { + if (ok != Q_NULLPTR) { + *ok = true; + } + return ErrorEntry::ERR_LIMIT_EXCEEDED; + } else if (str == strUnspecified) { + if (ok != Q_NULLPTR) { + *ok = true; + } + return ErrorEntry::ERR_UNSPECIFIED; + } else { + if (ok != Q_NULLPTR) { + *ok = false; + } + return ErrorEntry::ERR_UNSPECIFIED; + } +} diff -Nru datovka-4.8.3/src/records_management/json/entry_error.h datovka-4.9.3/src/records_management/json/entry_error.h --- datovka-4.8.3/src/records_management/json/entry_error.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/entry_error.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _ENTRY_ERROR_H_ +#define _ENTRY_ERROR_H_ + +#include /* Q_DECLARE_TR_FUNCTIONS() */ +#include + +class QJsonValue; /* Forward declaration. */ + +/*! + * @brief Encapsulates any error entry. + */ +class ErrorEntry { + Q_DECLARE_TR_FUNCTIONS(ErrorEntry) + +public: + /*! + * @brief Error codes. + */ + enum Code { + ERR_NO_ERROR, /*!< Just for convenience. */ + ERR_MALFORMED_REQUEST, /*!< JSON request was corrupt. */ + ERR_MISSING_IDENTIFIER, /*!< JSON request provided no identifier. */ + ERR_WRONG_IDENTIFIER, /*!< Wrong identifier provided in JSON request. */ + ERR_UNSUPPORTED_FILE_FORMAT, /*!< Uploaded file format not supported. */ + ERR_ALREADY_PRESENT, /*!< File is already present. */ + ERR_LIMIT_EXCEEDED, /*!< Too many identifiers in a single request. */ + ERR_UNSPECIFIED /*!< Unspecified error. */ + }; + + /*! + * @brief Constructor. Constructs a no-error entry. + */ + ErrorEntry(void); + + /*! + * @brief Constructor. + * + * @param[in] code Error code. + * @param[in] description Additional error description. + */ + ErrorEntry(enum Code code, const QString &description); + + /*! + * @brief Copy constructor. + * + * @param[in] ee Error entry. + */ + ErrorEntry(const ErrorEntry &ee); + + /*! + * @brief Returns error code. + * + * @return Error code. + */ + enum Code code(void) const; + + /*! + * @brief Returns error description. + * + * @return Error description. + */ + const QString &description(void) const; + + /*! + * @brief Set content according to JSON value. + * + * @note Method does not modify value of error entry if false returned. + * JSON null values are converted into no-error entries. + * + * @param[in] jsonVal Value to read from. + * @return True on success, false else. + */ + bool fromJsonVal(const QJsonValue *jsonVal); + + /*! + * @brief Set content of supplied JSON value. + * + * @note No-error entries are converted into JSON null values. + * + * @param[out] jsonVal Value to store to. + * @return True on success, false else. + */ + bool toJsonVal(QJsonValue *jsonVal) const; + + /*! + * @brief Returns translated error description. + * + * @return String containing localised description. + */ + QString trVerbose(void) const; + +private: + /*! + * @brief Converts error code into string as used in JSON. + * + * @param[in] code Code value to be converted into a string. + * @return JSON string code representation. + */ + static + const QString &codeToString(enum Code code); + + /*! + * @brief Converts error string as used in JSON into error code. + * + * @param[in] str JSON string code representation. + * @param[out] ok Set to true if conversion was ok. + * @return Code value. + */ + static + enum Code stringToCode(const QString &str, bool *ok = Q_NULLPTR); + + enum Code m_code; /*!< Error code. */ + QString m_description; /*!< Error description as obtained from JSON. */ +}; + +#endif /* _ENTRY_ERROR_H_ */ diff -Nru datovka-4.8.3/src/records_management/json/helper.cpp datovka-4.9.3/src/records_management/json/helper.cpp --- datovka-4.8.3/src/records_management/json/helper.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/helper.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include + +#include "src/records_management/json/helper.h" + +bool JsonHelper::readRootObject(const QByteArray &json, QJsonObject &jsonObj) +{ + QJsonDocument jsonDoc; + { + QJsonParseError parseErr; + jsonDoc = QJsonDocument::fromJson(json, &parseErr); + if (jsonDoc.isNull()) { + qCritical("Error parsing JSON: %s", + parseErr.errorString().toUtf8().constData()); + return false; + } + } + if (!jsonDoc.isObject()) { + qCritical("%s", "JSON document contains no object."); + return false; + } + + QJsonObject jsonTmpObj(jsonDoc.object()); + if (jsonTmpObj.isEmpty()) { + qCritical("%s", "JSON object is empty."); + return false; + } + + jsonObj = jsonTmpObj; + return true; +} + +bool JsonHelper::readValue(const QJsonObject &jsonObj, const QString &key, + QJsonValue &jsonVal) +{ + if (jsonObj.isEmpty() || key.isEmpty()) { + qCritical("%s", "JSON object or sought key is empty."); + return false; + } + + jsonVal = jsonObj.value(key); + if (jsonVal.isUndefined()) { + qCritical("Missing key '%s' in JSON object.", + key.toUtf8().constData()); + return false; + } + + return true; +} + +bool JsonHelper::readInt(const QJsonObject &jsonObj, const QString &key, + int &val, bool acceptNull) +{ + QJsonValue jsonVal; + if (!readValue(jsonObj, key, jsonVal)) { + return false; + } + if (jsonVal.isNull()) { + val = 0; /* Null value. */ + return acceptNull; + } + int readVal = jsonVal.toInt(-1); + if (readVal == -1) { + qCritical("Value related to key '%s' is not an integer.", + key.toUtf8().constData()); + return false; + } + + val = readVal; + return true; +} + +bool JsonHelper::readString(const QJsonObject &jsonObj, const QString &key, + QString &val, bool acceptNull) +{ + QJsonValue jsonVal; + if (!readValue(jsonObj, key, jsonVal)) { + return false; + } + if (jsonVal.isNull()) { + val = QString(); /* Null string. */ + return acceptNull; + } + if (!jsonVal.isString()) { + qCritical("Value related to key '%s' is not a string.", + key.toUtf8().constData()); + return false; + } + + val = jsonVal.toString(); + return true; +} + +bool JsonHelper::readArray(const QJsonObject &jsonObj, const QString &key, + QJsonArray &arr, bool acceptNull) +{ + QJsonValue jsonVal; + if (!readValue(jsonObj, key, jsonVal)) { + return false; + } + if (jsonVal.isNull()) { + arr = QJsonArray(); /* Null array. */ + return acceptNull; + } + if (!jsonVal.isArray()) { + qCritical("Value related to key '%s' is not an array.", + key.toUtf8().constData()); + return false; + } + + arr = jsonVal.toArray(); + return true; +} + +bool JsonHelper::readStringList(const QJsonObject &jsonObj, const QString &key, + QStringList &val, bool acceptNull) +{ + QJsonArray jsonArr; + if (!readArray(jsonObj, key, jsonArr, acceptNull)) { + return false; + } + + QStringList tmpList; + + foreach (const QJsonValue &jsonVal, jsonArr) { + if (jsonVal.isNull()) { + qCritical("%s", "Found null value in array."); + return false; + } + if (!jsonVal.isString()) { + qCritical("%s", "Found non-string value in array."); + return false; + } + + tmpList.append(jsonVal.toString()); + } + + val = tmpList; + return true; +} + +QString JsonHelper::toIndentedString(const QByteArray &json) +{ + if (json.isEmpty()) { + return QString(); + } + + QJsonDocument jsonDoc; + { + QJsonParseError parseErr; + jsonDoc = QJsonDocument::fromJson(json, &parseErr); + if (jsonDoc.isNull()) { + qCritical("Error parsing JSON: %s", + parseErr.errorString().toUtf8().constData()); + return QString(); + } + } + + return QString::fromUtf8(jsonDoc.toJson(QJsonDocument::Indented)); +} diff -Nru datovka-4.8.3/src/records_management/json/helper.h datovka-4.9.3/src/records_management/json/helper.h --- datovka-4.8.3/src/records_management/json/helper.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/helper.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _HELPER_H_ +#define _HELPER_H_ + +#include +#include +#include +#include + +/*! + * @brief JSON conversion helper functions. + */ +class JsonHelper { +private: + /*! + * @brief Private constructor. + */ + JsonHelper(void); + +public: + /*! + * @brief Reads a JSON object which comprises the document. + * + * @param[in] json JSON data. + * @param[out] jsonObj JSON object from the document. + * @return True on success, false else. + */ + static + bool readRootObject(const QByteArray &json, QJsonObject &jsonObj); + + /*! + * @brief Searches for a value on JSON object. + * + * @param[in] jsonObject Object to search in. + * @param[in] key Key to search for. + * @param[out] jsonVal Found value. + * @return True if key found, false else. + */ + static + bool readValue(const QJsonObject &jsonObj, const QString &key, + QJsonValue &jsonVal); + + /*! + * @brief Reads an integer value from supplied JSON object. + * + * @param[in] jsonObj JSON object. + * @param[in] key Key identifying the string. + * @param[out] val Value to be stored. + * @param[in] acceptNull True if null value should also be accepted. + * @return True on success, false else. + */ + static + bool readInt(const QJsonObject &jsonObj, const QString &key, + int &val, bool acceptNull); + + /*! + * @brief Reads a string value from supplied JSON object. + * + * @param[in] jsonObj JSON object. + * @param[in] key Key identifying the string. + * @param[out] val Value to be stored. + * @param[in] acceptNull True if null value should also be accepted. + * @return True on success, false else. + */ + static + bool readString(const QJsonObject &jsonObj, const QString &key, + QString &val, bool acceptNull); + + /*! + * @brief Reads an arry value from supplied JSON object. + * + * @param[in] jsonObj JSON object. + * @param[in] key Key identifying the string. + * @param[out] arr Array to be stored. + * @param[in] acceptNull True if null value should also be accepted. + * @return True on success, false else. + */ + static + bool readArray(const QJsonObject &jsonObj, const QString &key, + QJsonArray &arr, bool acceptNull); + + /*! + * @brief Reads a string list from supplied JSON object. + * + * @param[in] jsonObj JSON object. + * @param[in] key Key identifying the string list. + * @param[out] val Values to be stored. + * @param[in] acceptNull True if null value should also be accepted. + * @return True on success, false else. + */ + static + bool readStringList(const QJsonObject &jsonObj, const QString &key, + QStringList &val, bool acceptNull); + + /*! + * @brief Converts JSON document to indented string. + * + * @param[in] json JSON data. + * @retunr Non-empty indented string if JSON data could be read. + */ + static + QString toIndentedString(const QByteArray &json); +}; + +#endif /* _HELPER_H_ */ diff -Nru datovka-4.8.3/src/records_management/json/service_info.cpp datovka-4.9.3/src/records_management/json/service_info.cpp --- datovka-4.8.3/src/records_management/json/service_info.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/service_info.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include + +#include "src/records_management/json/helper.h" +#include "src/records_management/json/service_info.h" + +static +const QString keyLogoSvg("logo_svg"); +static +const QString keyName("name"); +static +const QString keyTokenName("token_name"); + +ServiceInfoResp::ServiceInfoResp(void) + : m_logoSvg(), + m_name(), + m_tokenName() +{ +} + +ServiceInfoResp::ServiceInfoResp(const QByteArray &logoSvg, const QString &name, + const QString &tokenName) + : m_logoSvg(logoSvg), + m_name(name), + m_tokenName(tokenName) +{ +} + +ServiceInfoResp::ServiceInfoResp(const ServiceInfoResp &sir) + : m_logoSvg(sir.m_logoSvg), + m_name(sir.m_name), + m_tokenName(sir.m_tokenName) +{ +} + +const QByteArray &ServiceInfoResp::logoSvg(void) const +{ + return m_logoSvg; +} + +const QString &ServiceInfoResp::name(void) const +{ + return m_name; +} + +const QString &ServiceInfoResp::tokenName(void) const +{ + return m_tokenName; +} + +bool ServiceInfoResp::isValid(void) const +{ + return !m_logoSvg.isNull() && !m_name.isNull() && !m_tokenName.isNull(); +} + +ServiceInfoResp ServiceInfoResp::fromJson(const QByteArray &json, bool *ok) +{ + QJsonObject jsonObj; + if (!JsonHelper::readRootObject(json, jsonObj)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return ServiceInfoResp(); + } + + ServiceInfoResp sir; + + { + QString valStr; + if (!JsonHelper::readString(jsonObj, keyLogoSvg, valStr, + false)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return ServiceInfoResp(); + } + + sir.m_logoSvg = QByteArray::fromBase64(valStr.toUtf8()); + } + + if (!JsonHelper::readString(jsonObj, keyName, sir.m_name, false)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return ServiceInfoResp(); + } + if (!JsonHelper::readString(jsonObj, keyTokenName, sir.m_tokenName, + false)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return ServiceInfoResp(); + } + + if (ok != Q_NULLPTR) { + *ok = true; + } + return sir; +} + +QByteArray ServiceInfoResp::toJson(void) const +{ + QJsonObject jsonObj; + jsonObj.insert(keyLogoSvg, !m_logoSvg.isNull() ? + QString::fromUtf8(m_logoSvg.toBase64()) : QJsonValue()); + jsonObj.insert(keyName, !m_name.isNull() ? m_name : QJsonValue()); + jsonObj.insert(keyTokenName, !m_tokenName.isNull() ? + m_tokenName : QJsonValue()); + + return QJsonDocument(jsonObj).toJson(QJsonDocument::Indented); +} diff -Nru datovka-4.8.3/src/records_management/json/service_info.h datovka-4.9.3/src/records_management/json/service_info.h --- datovka-4.8.3/src/records_management/json/service_info.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/service_info.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _SERVICE_INFO_H_ +#define _SERVICE_INFO_H_ + +#include +#include + +/*! + * @brief Encapsulates the service_info response. + */ +class ServiceInfoResp { +private: + /*! + * @brief Constructor. Creates an invalid structure. + */ + ServiceInfoResp(void); + + /*! + * @brief Constructor. + * + * @param[in] logoSvg SVG logo stored as raw data. + * @param[in] name Service provider name. + * @param[in] tokenMame Security token name. + */ + ServiceInfoResp(const QByteArray &logoSvg, const QString &name, + const QString &tokenName); + +public: + /*! + * @brief Copy constructor. + * + * @param[in] sir Service info response. + */ + ServiceInfoResp(const ServiceInfoResp &sir); + + /*! + * @brief Return raw SVG data. + * + * @return Stored raw SVG data. + */ + const QByteArray &logoSvg(void) const; + + /*! + * @brief Return service provider name. + * + * @return Stored name. + */ + const QString &name(void) const; + + /*! + * @brief Return security token name. + * + * @return Stored token name. + */ + const QString &tokenName(void) const; + + /*! + * @brief Check whether content is valid. + * + * @return True if content is valid. + */ + bool isValid(void) const; + + /*! + * @brief Creates a service info structure from supplied JSON document. + * + * @param[in] json JSON document. + * @param[out] ok Set to true on success. + * @return Invalid structure on error a valid structure else. + */ + static + ServiceInfoResp fromJson(const QByteArray &json, bool *ok = Q_NULLPTR); + + /*! + * @brief Converts service info structure into a JSON document. + * + * @note Unspecified values are stores as null into the JSON document. + * + * @return JSON document containing stored data. + */ + QByteArray toJson(void) const; + +private: + QByteArray m_logoSvg; /*!< Raw SVG data. */ + QString m_name; /*!< Service provider name. */ + QString m_tokenName; /*!< Obtained token identifier. */ +}; + +#endif /* _SERVICE_INFO_H_ */ diff -Nru datovka-4.8.3/src/records_management/json/stored_files.cpp datovka-4.9.3/src/records_management/json/stored_files.cpp --- datovka-4.8.3/src/records_management/json/stored_files.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/stored_files.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,517 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include +#include + +#include "src/records_management/conversion.h" +#include "src/records_management/json/helper.h" +#include "src/records_management/json/stored_files.h" + +static +const QString keyDmIds("dm_ids"); +static +const QString keyDiIds("di_ids"); + +static +const QString keyDmId("dm_id"); +static +const QString keyDiId("di_id"); +static +const QString keyLocations("locations"); + +static +const QString keyDms("dms"); +static +const QString keyDis("dis"); +static +const QString keyLimit("limit"); +static +const QString keyError("error"); + +StoredFilesReq::StoredFilesReq(void) + : m_dmIds(), + m_diIds() +{ +} + +StoredFilesReq::StoredFilesReq(const QList &dmIds, + const QList &diIds) + : m_dmIds(dmIds), + m_diIds(diIds) +{ +} + +StoredFilesReq::StoredFilesReq(const StoredFilesReq &sfr) + : m_dmIds(sfr.m_dmIds), + m_diIds(sfr.m_diIds) +{ +} + +const QList &StoredFilesReq::dmIds(void) const +{ + return m_dmIds; +} + +const QList &StoredFilesReq::diIds(void) const +{ + return m_diIds; +} + +bool StoredFilesReq::isValid(void) const +{ + return !m_dmIds.isEmpty() || !m_diIds.isEmpty(); +} + +StoredFilesReq StoredFilesReq::fromJson(const QByteArray &json, bool *ok) +{ + QJsonObject jsonObj; + if (!JsonHelper::readRootObject(json, jsonObj)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesReq(); + } + + StoredFilesReq sfr; + + { + QStringList strList; + if (!JsonHelper::readStringList(jsonObj, keyDmIds, strList, + false)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesReq(); + } + bool iOk = false; + sfr.m_dmIds = createIdList(strList, &iOk); + if (!iOk) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesReq(); + } + } + { + QStringList strList; + if (!JsonHelper::readStringList(jsonObj, keyDiIds, strList, + false)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesReq(); + } + bool iOk = false; + sfr.m_diIds = createIdList(strList, &iOk); + if (!iOk) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesReq(); + } + } + + if (ok != Q_NULLPTR) { + *ok = true; + } + return sfr; +} + +/*! + * @brief Convert list of qin64 into list of strings. + * + * @param[in] idList List of qint64. + * @return List of strings. + */ +static +QStringList createStrIdList(const QList &idList) +{ + QStringList strList; + foreach (qint64 id, idList) { + strList.append(QString::number(id)); + } + + return strList; +} + +QByteArray StoredFilesReq::toJson(void) const +{ + QJsonObject jsonObj; + jsonObj.insert(keyDmIds, + QJsonArray::fromStringList(createStrIdList(m_dmIds))); + jsonObj.insert(keyDiIds, + QJsonArray::fromStringList(createStrIdList(m_diIds))); + + return QJsonDocument(jsonObj).toJson(QJsonDocument::Indented); +} + +DmEntry::DmEntry(void) + : m_dmId(-1), + m_locations() +{ +} + +DmEntry::DmEntry(qint64 dmId, const QStringList &locations) + : m_dmId(dmId), + m_locations(locations) +{ +} + +DmEntry::DmEntry(const DmEntry &me) + : m_dmId(me.m_dmId), + m_locations(me.m_locations) +{ +} + +qint64 DmEntry::dmId(void) const +{ + return m_dmId; +} + +const QStringList &DmEntry::locations(void) const +{ + return m_locations; +} + +bool DmEntry::isValid(void) const +{ + return m_dmId >= 0; +} + +/*! + * @brief Read object content from JSON value. + * + * @param[in] jsnoVal JSON value. + * @param[in] idKey Key identifying data message or delivery info identifier. + * @param[out] id Read id. + * @param[out] locations Read list of locations. + * @return True on success, false else. + */ +static +bool fromJsonValue(const QJsonValue *jsonVal, const QString &idKey, + qint64 &id, QStringList &locations) +{ + if (jsonVal == Q_NULLPTR) { + Q_ASSERT(0); + return false; + } + + if (!jsonVal->isObject()) { + return false; + } + + QJsonObject jsonObj(jsonVal->toObject()); + + id = -1; + locations.clear(); + + QString idStr; + if (!JsonHelper::readString(jsonObj, idKey, idStr, false)) { + return false; + } + bool ok = false; + id = idStr.toLongLong(&ok); + if (!ok) { + return false; + } + if (id < 0) { + return false; + } + + if (!JsonHelper::readStringList(jsonObj, keyLocations, locations, + false)) { + return false; + } + + return true; +} + +bool DmEntry::fromJsonVal(const QJsonValue *jsonVal) +{ + qint64 id = -1; + QStringList locations; + if (!fromJsonValue(jsonVal, keyDmId, id, locations)) { + return false; + } + + m_dmId = id; + m_locations = locations; + return true; +} + +/*! + * @brief Write object to JSON value. + * + * @param[out] jsnoVal JSON value. + * @param[in] idKey Key identifying data message or delivery info identifier. + * @param[in] id Written id. + * @param[in] locations Written list of locations. + * @return True on success, false else. + */ +static +bool toJsonValue(QJsonValue *jsonVal, const QString &idKey, + qint64 id, const QStringList &locations) +{ + if (jsonVal == Q_NULLPTR) { + Q_ASSERT(0); + return false; + } + + QJsonObject jsonObj; + jsonObj.insert(idKey, QString::number(id)); + jsonObj.insert(keyLocations, QJsonArray::fromStringList(locations)); + *jsonVal = jsonObj; + return true; +} + +bool DmEntry::toJsonVal(QJsonValue *jsonVal) const +{ + return toJsonValue(jsonVal, keyDmId, m_dmId, m_locations); +} + +DiEntry::DiEntry(void) + : m_diId(-1), + m_locations() +{ +} + +DiEntry::DiEntry(qint64 diId, const QStringList &locations) + : m_diId(diId), + m_locations(locations) +{ +} + +DiEntry::DiEntry(const DiEntry &ie) + : m_diId(ie.m_diId), + m_locations(ie.m_locations) +{ +} + +qint64 DiEntry::diId(void) const +{ + return m_diId; +} + +const QStringList &DiEntry::locations(void) const +{ + return m_locations; +} + +bool DiEntry::isValid(void) const +{ + return m_diId >= 0; +} + +bool DiEntry::fromJsonVal(const QJsonValue *jsonVal) +{ + qint64 id = -1; + QStringList locations; + if (!fromJsonValue(jsonVal, keyDiId, id, locations)) { + return false; + } + + m_diId = id; + m_locations = locations; + return true; +} + +bool DiEntry::toJsonVal(QJsonValue *jsonVal) const +{ + return toJsonValue(jsonVal, keyDiId, m_diId, m_locations); +} + +StoredFilesResp::StoredFilesResp(void) + : m_dms(), + m_dis(), + m_limit(-1), + m_error() +{ +} + +StoredFilesResp::StoredFilesResp(const QList &dms, const QList &dis, + int limit, const ErrorEntry &error) + : m_dms(dms), + m_dis(dis), + m_limit(limit), + m_error(error) +{ +} + +StoredFilesResp::StoredFilesResp(const StoredFilesResp &sfr) + : m_dms(sfr.m_dms), + m_dis(sfr.m_dis), + m_limit(sfr.m_limit), + m_error(sfr.m_error) +{ +} + +const QList &StoredFilesResp::dms(void) const +{ + return m_dms; +} + +const QList &StoredFilesResp::dis(void) const +{ + return m_dis; +} + +int StoredFilesResp::limit(void) const +{ + return m_limit; +} + +const ErrorEntry &StoredFilesResp::error(void) const +{ + return m_error; +} + +bool StoredFilesResp::isValid(void) const +{ + return (m_limit > 0) && + ((!m_dms.isEmpty() || !m_dis.isEmpty()) || + (m_error.code() != ErrorEntry::ERR_NO_ERROR)); +} + +/*! + * @brief Template function that reads list of objects of type T from JSON + * array. + * + * @param[in] jsonObj JSON object to read data from. + * @param[in] idKey Key identifying the sought array of T. + * @param[out] list List to append read objects of type T to. + * @return True on success, false else. + */ +template +static +bool readArrayofObjects(const QJsonObject &jsonObj, const QString &idKey, + QList &list) +{ + QJsonValue jsonVal; + if (!JsonHelper::readValue(jsonObj, idKey, jsonVal)) { + return false; + } + if (!jsonVal.isArray()) { + return false; + } + foreach (const QJsonValue &jsonVal, jsonVal.toArray()) { + T te; /* Entry of type T. */ + if (!te.fromJsonVal(&jsonVal)) { + return false; + } + list.append(te); + } + return true; +} + +StoredFilesResp StoredFilesResp::fromJson(const QByteArray &json, bool *ok) +{ + QJsonObject jsonObj; + if (!JsonHelper::readRootObject(json, jsonObj)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesResp(); + } + + StoredFilesResp sfr; + if (!readArrayofObjects(jsonObj, keyDms, sfr.m_dms)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesResp(); + } + if (!readArrayofObjects(jsonObj, keyDis, sfr.m_dis)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesResp(); + } + { + if (!JsonHelper::readInt(jsonObj, keyLimit, sfr.m_limit, + false)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesResp(); + } + if (sfr.m_limit < 0) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesResp(); + } + } + { + QJsonValue jsonVal; + if (!JsonHelper::readValue(jsonObj, keyError, jsonVal)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesResp(); + } + if (!sfr.m_error.fromJsonVal(&jsonVal)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return StoredFilesResp(); + } + } + + if (ok != Q_NULLPTR) { + *ok = true; + } + return sfr; +} + +QByteArray StoredFilesResp::toJson(void) const +{ + QJsonObject jsonObj; + { + QJsonArray dms; + QJsonValue dmVal; + foreach (const DmEntry &me, m_dms) { + me.toJsonVal(&dmVal); + dms.append(dmVal); + } + jsonObj.insert(keyDms, dms); + } + { + QJsonArray dis; + QJsonValue diVal; + foreach (const DiEntry &ie, m_dis) { + ie.toJsonVal(&diVal); + dis.append(diVal); + } + jsonObj.insert(keyDis, dis); + } + jsonObj.insert(keyLimit, QString::number(m_limit)); + QJsonValue jsonVal; + m_error.toJsonVal(&jsonVal); + jsonObj.insert(keyError, jsonVal); + + return QJsonDocument(jsonObj).toJson(QJsonDocument::Indented); +} diff -Nru datovka-4.8.3/src/records_management/json/stored_files.h datovka-4.9.3/src/records_management/json/stored_files.h --- datovka-4.8.3/src/records_management/json/stored_files.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/stored_files.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _STORED_FILES_H_ +#define _STORED_FILES_H_ + +#include +#include +#include + +#include "src/records_management/json/entry_error.h" + +class QJsonValue; /* Forward declaration. */ + +/*! + * @brief Encapsulates the stored_files request. + */ +class StoredFilesReq { +private: + /*! + * @brief Constructor. Creates an invalid structure. + */ + StoredFilesReq(void); + +public: + /*! + * @brief Constructor. + * + * @param[in] dmIds Data message identifiers. + * @param[in] diIds Delivery info identifiers. + */ + StoredFilesReq(const QList &dmIds, const QList &diIds); + + /*! + * @brief Copy constructor. + * + * @param[in] sfr Stored files request. + */ + StoredFilesReq(const StoredFilesReq &sfr); + + /*! + * @brief Return data message identifiers. + * + * @return Data message identifiers as used in ISDS. + */ + const QList &dmIds(void) const; + + /*! + * @brief Return delivery info identifiers. + * + * @return Delivery info identifiers as used in ISDS. + */ + const QList &diIds(void) const; + + /*! + * @brief Check whether content is valid. + * + * @return True if content is valid. + */ + bool isValid(void) const; + + /*! + * @brief Creates a stored files request structure from supplied JSON + * document. + * + * @param[in] json JSON document. + * @param[out] ok Set to true on success. + * @return Invalid structure on error a valid structure else. + */ + static + StoredFilesReq fromJson(const QByteArray &json, bool *ok = Q_NULLPTR); + + /*! + * @brief Converts stored files structure into a JSON document. + * + * @note Unspecified values are stores as null into the JSON document. + * + * @return JSON document containing stored data. + */ + QByteArray toJson(void) const; + +private: + QList m_dmIds; /*!< Data message identifiers. */ + QList m_diIds; /*!< Delivery info identifiers. */ +}; + +/*! + * @brief Encapsulates stored_files data message entry structure. + */ +class DmEntry { +public: + /*! + * @brief Constructor. Constructs invalid entry. + */ + DmEntry(void); + + /*! + * @brief Constructor. + * + * @param[in] dmId Message identifier. + * @param[in] locations List of locations. + */ + DmEntry(qint64 dmId, const QStringList &locations); + + /*! + * @brief Copy constructor. + * + * @param[in] me Message entry. + */ + DmEntry(const DmEntry &me); + + /*! + * @brief Return message identifier. + * + * @return Data message identifier. + */ + qint64 dmId(void) const; + + /*! + * @brief Return list of locations. + * + * @return Locations. + */ + const QStringList &locations(void) const; + + /*! + * @brief Check whether content is valid. + * + * @return True if content is valid. + */ + bool isValid(void) const; + + /*! + * @brief Set content according to JSON value. + * + * @note Method does not modify value of error entry if false returned. + * JSON null values are converted into no-error entries. + * + * @param[in] jsonVal Value to read from. + * @return True on success, false else. + */ + bool fromJsonVal(const QJsonValue *jsonVal); + + /*! + * @brief Set content of supplied JSON value. + * + * @note No-error entries are converted into JSON null values. + * + * @param[out] jsonVal Value to store to. + * @return True on success, false else. + */ + bool toJsonVal(QJsonValue *jsonVal) const; + +private: + qint64 m_dmId; /*!< Data message identifier. */ + QStringList m_locations; /*!< Where the uploaded file is located in the service. */ +}; + +/*! + * @brief Encapsulates stored_files delivery info entry structure. + */ +class DiEntry { +public: + /*! + * @brief Constructor. Constructs invalid entry. + */ + DiEntry(void); + + /*! + * @brief Constructor. + * + * @param[in] diId Info identifier. + * @param[in] locations List of locations. + */ + DiEntry(qint64 diId, const QStringList &locations); + + /*! + * @brief Copy constructor. + * + * @param[in] ie Info entry. + */ + DiEntry(const DiEntry &ie); + + /*! + * @brief Return info identifier. + * + * @return Data info identifier. + */ + qint64 diId(void) const; + + /*! + * @brief Return list of locations. + * + * @return Locations. + */ + const QStringList &locations(void) const; + + /*! + * @brief Check whether content is valid. + * + * @return True if content is valid. + */ + bool isValid(void) const; + + /*! + * @brief Set content according to JSON value. + * + * @note Method does not modify value of error entry if false returned. + * JSON null values are converted into no-error entries. + * + * @param[in] jsonVal Value to read from. + * @return True on success, false else. + */ + bool fromJsonVal(const QJsonValue *jsonVal); + + /*! + * @brief Set content of supplied JSON value. + * + * @note No-error entries are converted into JSON null values. + * + * @param[out] jsonVal Value to store to. + * @return True on success, false else. + */ + bool toJsonVal(QJsonValue *jsonVal) const; + +private: + qint64 m_diId; /*!< Delivery info identifier. */ + QStringList m_locations; /*!< Where the uploaded file is located in the service. */ +}; + +/*! + * @brief Encapsulates the stored_files response. + */ +class StoredFilesResp { +private: + /*! + * @brief Constructor. Creates an invalid structure. + */ + StoredFilesResp(void); + + /*! + * @brief Constructor. + * + * @param[in] dms List of data message entries. + * @param[in] dis List of delivery information entries. + * @param[in] limit Request limit. + * @param[in] error Error entry. + */ + StoredFilesResp(const QList &dms, const QList &dis, + int limit, const ErrorEntry &error); + +public: + /*! + * @brief Copy constructor. + * + * @param[in] sfr Stored files response. + */ + StoredFilesResp(const StoredFilesResp &sfr); + + /*! + * @brief Return list of data message entries. + * + * @return List of held data message entries. + */ + const QList &dms(void) const; + + /*! + * @brief Return list of delivery info entries. + * + * @return List of held delivery info entries. + */ + const QList &dis(void) const; + + /*! + * @brief Return request limit. + * + * @return Request limit as obtained from the service. + */ + int limit(void) const; + + /*! + * @brief Return error entry. + * + * @return Error entry. + */ + const ErrorEntry &error(void) const; + + /*! + * @brief Check whether content is valid. + * + * @return True if content is valid. + */ + bool isValid(void) const; + + /*! + * @brief Creates a stored files response structure from supplied JSON + * document. + * + * @param[in] json JSON document. + * @param[out] ok Set to true on success. + * @return Invalid structure on error a valid structure else. + */ + static + StoredFilesResp fromJson(const QByteArray &json, + bool *ok = Q_NULLPTR); + + /*! + * @brief Converts stored files response structure into a JSON document. + * + * @note Unspecified values are stores as null into the JSON document. + * + * @return JSON document containing stored data. + */ + QByteArray toJson(void) const; + +private: + QList m_dms; /*!< List of received data message entries. */ + QList m_dis; /*!< List of received delivery info entries. */ + int m_limit; /*!< Request limit, must be greater than zero. */ + ErrorEntry m_error; /*!< Encountered error. */ +}; + +#endif /* _STORED_FILES_H_ */ diff -Nru datovka-4.8.3/src/records_management/json/upload_file.cpp datovka-4.9.3/src/records_management/json/upload_file.cpp --- datovka-4.8.3/src/records_management/json/upload_file.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/upload_file.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include + +#include "src/records_management/json/entry_error.h" +#include "src/records_management/json/helper.h" +#include "src/records_management/json/upload_file.h" + +static +const QString keyIds("ids"); +static +const QString keyFileName("file_name"); +static +const QString keyFileContent("file_content"); + +static +const QString keyId("id"); +static +const QString keyError("error"); +static +const QString keyLocations("locations"); + +UploadFileReq::UploadFileReq(void) + : m_ids(), + m_fileName(), + m_fileContent() +{ +} + +UploadFileReq::UploadFileReq(const QStringList &ids, const QString &fileName, + const QByteArray &fileContent) + : m_ids(ids), + m_fileName(fileName), + m_fileContent(fileContent) +{ +} + +UploadFileReq::UploadFileReq(const UploadFileReq &ufr) + : m_ids(ufr.m_ids), + m_fileName(ufr.m_fileName), + m_fileContent(ufr.m_fileContent) +{ +} + +const QStringList &UploadFileReq::ids(void) const +{ + return m_ids; +} + +const QString &UploadFileReq::fileName(void) const +{ + return m_fileName; +} + +const QByteArray &UploadFileReq::fileContent(void) const +{ + return m_fileContent; +} + +bool UploadFileReq::isValid(void) const +{ + bool valid = !m_ids.isEmpty() && !m_fileName.isEmpty() && + !m_fileContent.isEmpty(); + if (!valid) { + return false; + } + + foreach (const QString &id, m_ids) { + if (id.isEmpty()) { + return false; + } + } + + return true; +} + +UploadFileReq UploadFileReq::fromJson(const QByteArray &json, bool *ok) +{ + QJsonObject jsonObj; + if (!JsonHelper::readRootObject(json, jsonObj)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return UploadFileReq(); + } + + UploadFileReq ufr; + + if (!JsonHelper::readStringList(jsonObj, keyIds, ufr.m_ids, false)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return UploadFileReq(); + } + if (!JsonHelper::readString(jsonObj, keyFileName, ufr.m_fileName, + false)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return UploadFileReq(); + } + + { + QString valStr; + if (!JsonHelper::readString(jsonObj, keyFileContent, valStr, + false)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return UploadFileReq(); + } + + ufr.m_fileContent = QByteArray::fromBase64(valStr.toUtf8()); + } + + if (ok != Q_NULLPTR) { + *ok = true; + } + return ufr; +} + +QByteArray UploadFileReq::toJson(void) const +{ + QJsonObject jsonObj; + jsonObj.insert(keyIds, QJsonArray::fromStringList(m_ids)); + jsonObj.insert(keyFileName, !m_fileName.isNull() ? + m_fileName : QJsonValue()); + jsonObj.insert(keyFileContent, !m_fileContent.isNull() ? + QString::fromUtf8(m_fileContent.toBase64()) : QJsonValue()); + + return QJsonDocument(jsonObj).toJson(QJsonDocument::Indented); +} + +UploadFileResp::UploadFileResp(void) + : m_id(), + m_error(), + m_locations() +{ +} + +UploadFileResp::UploadFileResp(const QString &id, const ErrorEntry &error, + const QStringList &locations) + : m_id(id), + m_error(error), + m_locations(locations) +{ +} + +UploadFileResp::UploadFileResp(const UploadFileResp &ufr) + : m_id(ufr.m_id), + m_error(ufr.m_error), + m_locations(ufr.m_locations) +{ +} + +const QString &UploadFileResp::id(void) const +{ + return m_id; +} + +const ErrorEntry &UploadFileResp::error(void) const +{ + return m_error; +} + +const QStringList &UploadFileResp::locations(void) const +{ + return m_locations; +} + +bool UploadFileResp::isValid(void) const +{ + return (!m_id.isEmpty() && !m_locations.isEmpty()) || + (m_error.code() != ErrorEntry::ERR_NO_ERROR); +} + +UploadFileResp UploadFileResp::fromJson(const QByteArray &json, bool *ok) +{ + QJsonObject jsonObj; + if (!JsonHelper::readRootObject(json, jsonObj)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return UploadFileResp(); + } + + UploadFileResp ufr; + + if (!JsonHelper::readString(jsonObj, keyId, ufr.m_id, true)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return UploadFileResp(); + } + + { + QJsonValue jsonVal; + if (!JsonHelper::readValue(jsonObj, keyError, jsonVal)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return UploadFileResp(); + } + if (!ufr.m_error.fromJsonVal(&jsonVal)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return UploadFileResp(); + } + } + + if (!JsonHelper::readStringList(jsonObj, keyLocations, ufr.m_locations, + false)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return UploadFileResp(); + } + + if (ok != Q_NULLPTR) { + *ok = true; + } + return ufr; +} + +QByteArray UploadFileResp::toJson(void) const +{ + QJsonObject jsonObj; + jsonObj.insert(keyId, !m_id.isNull() ? m_id : QJsonValue()); + QJsonValue jsonVal; + m_error.toJsonVal(&jsonVal); + jsonObj.insert(keyError, jsonVal); + jsonObj.insert(keyLocations, QJsonArray::fromStringList(m_locations)); + + return QJsonDocument(jsonObj).toJson(QJsonDocument::Indented); +} diff -Nru datovka-4.8.3/src/records_management/json/upload_file.h datovka-4.9.3/src/records_management/json/upload_file.h --- datovka-4.8.3/src/records_management/json/upload_file.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/upload_file.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _UPLOAD_FILE_H_ +#define _UPLOAD_FILE_H_ + +#include +#include +#include +#include + +#include "src/records_management/json/entry_error.h" + +/*! + * @brief Encapsulates the upload_file request. + */ +class UploadFileReq { +private: + /*! + * @brief Constructor. Creates an invalid structure. + */ + UploadFileReq(void); + +public: + /*! + * @brief Constructor. + * + * @param[in] ids Location identifiers as obtained from upload_hierarchy. + * @param[in] fileName File name. + * @param[in] fileContent Raw file content. + */ + UploadFileReq(const QStringList &ids, const QString &fileName, + const QByteArray &fileContent); + + /*! + * @brief Copy constructor. + * + * @param[in] ufr Upload file request. + */ + UploadFileReq(const UploadFileReq &ufr); + + /*! + * @brief Return location identifier. + * + * @return Location identifier. + */ + const QStringList &ids(void) const; + + /*! + * @brief Return file name. + * + * @return File name. + */ + const QString &fileName(void) const; + + /*! + * @brief Return file content. + * + * @return Raw file content. + */ + const QByteArray &fileContent(void) const; + + /*! + * @brief Check whether content is valid. + * + * @return True if content is valid. + */ + bool isValid(void) const; + + /*! + * @brief Creates a upload file request structure from supplied JSON + * document. + * + * @param[in] json JSON document. + * @param[out] ok Set to true on success. + * @return Invalid structure on error a valid structure else. + */ + static + UploadFileReq fromJson(const QByteArray &json, bool *ok = Q_NULLPTR); + + /*! + * @brief Converts upload file structure into a JSON document. + * + * @note Unspecified values are stores as null into the JSON document. + * + * @return JSON document containing stored data. + */ + QByteArray toJson(void) const; + +private: + QStringList m_ids; /*!< Location identifiers as obtained from upload_hierarchy. */ + QString m_fileName; /*!< Uploaded file name. */ + QByteArray m_fileContent; /*!< Raw content of uploaded file. */ +}; + +/*! + * @brief Encapsulates the upload_file response. + */ +class UploadFileResp { +private: + /*! + * @brief Constructor. Creates an invalid structure. + */ + UploadFileResp(void); + + /*! + * @brief Constructor. + * + * @param[in] id File identifier. + * @param[in] error Error entry. + * @param[in] locations List of locations. + */ + UploadFileResp(const QString &id, const ErrorEntry &error, + const QStringList &locations); + +public: + /*! + * @brief Copy constructor. + * + * @param[in] ufr Upload file response. + */ + UploadFileResp(const UploadFileResp &ufr); + + /*! + * @brief Return file identifier. + * + * @return File identifier. + */ + const QString &id(void) const; + + /*! + * @brief Return error entry. + * + * @return Error entry. + */ + const ErrorEntry &error(void) const; + + /*! + * @brief Return location list. + * + * @return List of places where the file is stored in the service. + */ + const QStringList &locations(void) const; + + /*! + * @brief Check whether content is valid. + * + * @return True if content is valid. + */ + bool isValid(void) const; + + /*! + * @brief Creates a upload file response structure from supplied JSON + * document. + * + * @param[in] json JSON document. + * @param[out] ok Set to true on success. + * @return Invalid structure on error a valid structure else. + */ + static + UploadFileResp fromJson(const QByteArray &json, + bool *ok = Q_NULLPTR); + + /*! + * @brief Converts upload file response structure into a JSON document. + * + * @note Unspecified values are stores as null into the JSON document. + * + * @return JSON document containing stored data. + */ + QByteArray toJson(void) const; + +private: + QString m_id; /*!< Uploaded file identifier (not necessary from ISDS). */ + ErrorEntry m_error; /*!< Brief error entry. */ + QStringList m_locations; /*!< Where the uploaded file is located in the service. */ +}; + +#endif /* _UPLOAD_FILE_H_ */ diff -Nru datovka-4.8.3/src/records_management/json/upload_hierarchy.cpp datovka-4.9.3/src/records_management/json/upload_hierarchy.cpp --- datovka-4.8.3/src/records_management/json/upload_hierarchy.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/upload_hierarchy.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include + +#include "src/records_management/json/helper.h" +#include "src/records_management/json/upload_hierarchy.h" + +static +const QString keyName("name"); +static +const QString keyId("id"); +static +const QString keyMetadata("metadata"); +static +const QString keySub("sub"); + +UploadHierarchyResp::NodeEntry::NodeEntry(void) + : m_super(Q_NULLPTR), + m_name(), + m_id(), + m_metadata(), + m_sub() +{ +} + +const UploadHierarchyResp::NodeEntry *UploadHierarchyResp::NodeEntry::super(void) const +{ + return m_super; +} + +const QString &UploadHierarchyResp::NodeEntry::name(void) const +{ + return m_name; +} + +const QString &UploadHierarchyResp::NodeEntry::id(void) const +{ + return m_id; +} + +const QStringList &UploadHierarchyResp::NodeEntry::metadata(void) const +{ + return m_metadata; +} + +const QList &UploadHierarchyResp::NodeEntry::sub(void) const +{ + return m_sub; +} + +UploadHierarchyResp::NodeEntry *UploadHierarchyResp::NodeEntry::copyRecursive( + const NodeEntry *root) +{ + if (root == Q_NULLPTR) { + Q_ASSERT(0); + return Q_NULLPTR; + } + + NodeEntry *newRoot = new (std::nothrow) NodeEntry(); + if (newRoot == Q_NULLPTR) { + return Q_NULLPTR; + } + + newRoot->m_name = root->m_name; + newRoot->m_id = root->m_id; + newRoot->m_metadata = root->m_metadata; + + foreach (const NodeEntry *sub, root->m_sub) { + if (sub == Q_NULLPTR) { + Q_ASSERT(0); + deleteRecursive(newRoot); + return Q_NULLPTR; + } + NodeEntry *newSub = copyRecursive(sub); + if (newSub == Q_NULLPTR) { + deleteRecursive(newRoot); + return Q_NULLPTR; + } + + newSub->m_super = newRoot; + newRoot->m_sub.append(newSub); + } + + return newRoot; +} + +void UploadHierarchyResp::NodeEntry::deleteRecursive(NodeEntry *root) +{ + if (root == Q_NULLPTR) { + return; + } + + foreach (NodeEntry *entry, root->m_sub) { + deleteRecursive(entry); + } + + delete root; +} + +UploadHierarchyResp::NodeEntry *UploadHierarchyResp::NodeEntry::fromJsonRecursive( + const QJsonObject *jsonObj, bool &ok, bool acceptNullName) +{ + if (jsonObj == Q_NULLPTR) { + Q_ASSERT(0); + ok = false; + return Q_NULLPTR; + } + + NodeEntry *newEntry = new (std::nothrow) NodeEntry(); + if (newEntry == Q_NULLPTR) { + ok = false; + return Q_NULLPTR; + } + + if (!JsonHelper::readString(*jsonObj, keyName, newEntry->m_name, + acceptNullName)) { + ok = false; + deleteRecursive(newEntry); + return Q_NULLPTR; + } + if (!JsonHelper::readString(*jsonObj, keyId, newEntry->m_id, true)) { + ok = false; + deleteRecursive(newEntry); + return Q_NULLPTR; + } + if (!JsonHelper::readStringList(*jsonObj, keyMetadata, + newEntry->m_metadata, false)) { + ok = false; + deleteRecursive(newEntry); + return Q_NULLPTR; + } + + { + QJsonArray jsonArr; + if (!JsonHelper::readArray(*jsonObj, keySub, jsonArr, false)) { + ok = false; + deleteRecursive(newEntry); + return Q_NULLPTR; + } + + foreach (const QJsonValue &jsonVal, jsonArr) { + if (!jsonVal.isObject()) { + qCritical("%s", + "Sub-node array holds a non-object value."); + ok = false; + deleteRecursive(newEntry); + return Q_NULLPTR; + } + + QJsonObject jsonSubObj(jsonVal.toObject()); + NodeEntry *subNewEntry = + fromJsonRecursive(&jsonSubObj, ok, false); + if (!ok) { + /* ok = false; */ + deleteRecursive(newEntry); + return Q_NULLPTR; + } + Q_ASSERT(subNewEntry != Q_NULLPTR); + + subNewEntry->m_super = newEntry; + newEntry->m_sub.append(subNewEntry); + } + } + + ok = true; + return newEntry; +} + +/*! + * @brief Append a JSON object into sub-nodes. + * + * @param[in,out] jsonNode Not to append a sub-node to. + * @param[in] jsnoSubNode Sub-node to be appended. + * @return True on success, false else. + */ +static +bool jsonHierarchyAppendSub(QJsonObject &jsonNode, + const QJsonObject &jsonSubNode) +{ + QJsonObject::iterator it(jsonNode.find(keySub)); + if (it == jsonNode.end()) { + return false; + } + + QJsonValueRef arrRef(it.value()); + if (!arrRef.isArray()) { + return false; + } + + /* Sub-node must have a name. */ + { + QJsonObject::const_iterator sit(jsonSubNode.constFind(keyName)); + if ((sit == jsonSubNode.constEnd()) || + !sit.value().isString() || + sit.value().toString().isEmpty()) { + return false; + } + } + +#if 0 + /* QJsonArray::operator+() is not available in Qt 5.2. */ + arrRef = arrRef.toArray() + jsonSubNode; +#else + QJsonArray arr(arrRef.toArray()); + arr.append(jsonSubNode); + arrRef = arr; +#endif + return true; +} + +/*! + * @brief Creates a JSON object representing an upload hierarchy node with + * empty sub-node list. + * + * @param[in] name Node name. + * @param[in] id Node identifier. + * @param[in] metadata List of metadata. + * @return JSON object. + */ +static +QJsonObject jsonHierarchyNode(const QString &name, const QString &id, + const QStringList &metadata) +{ + QJsonObject jsonObj; + /* Intentionally using isEmpty() instead of isNull(). */ + jsonObj.insert(keyName, !name.isEmpty() ? name : QJsonValue()); + jsonObj.insert(keyId, !id.isEmpty() ? id : QJsonValue()); + jsonObj.insert(keyMetadata, QJsonArray::fromStringList(metadata)); + jsonObj.insert(keySub, QJsonArray()); + + return jsonObj; +} + +bool UploadHierarchyResp::NodeEntry::toJsonRecursive(QJsonObject *jsonObj, + const QList &uhrList) +{ + if (jsonObj == Q_NULLPTR) { + Q_ASSERT(0); + return false; + } + + foreach (const NodeEntry *entry, uhrList) { + if (entry == Q_NULLPTR) { + Q_ASSERT(0); + return false; + } + QJsonObject jsonSubObj(jsonHierarchyNode(entry->m_name, + entry->m_id, entry->m_metadata)); + if (!toJsonRecursive(&jsonSubObj, entry->m_sub)) { + return false; + } + if (!jsonHierarchyAppendSub(*jsonObj, jsonSubObj)) { + return false; + } + } + + return true; +} + +UploadHierarchyResp::UploadHierarchyResp(void) + : m_root(Q_NULLPTR) +{ +} + +UploadHierarchyResp::UploadHierarchyResp(const UploadHierarchyResp &uhr) + : m_root(Q_NULLPTR) +{ + if (uhr.m_root != Q_NULLPTR) { + m_root = NodeEntry::copyRecursive(uhr.m_root); + } +} + +UploadHierarchyResp::~UploadHierarchyResp(void) +{ + NodeEntry::deleteRecursive(m_root); +} + +const UploadHierarchyResp::NodeEntry *UploadHierarchyResp::root(void) const +{ + return m_root; +} + +bool UploadHierarchyResp::isValid(void) const +{ + return m_root != Q_NULLPTR; +} + +UploadHierarchyResp UploadHierarchyResp::fromJson(const QByteArray &json, + bool *ok) +{ + QJsonObject jsonObj; + if (!JsonHelper::readRootObject(json, jsonObj)) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return UploadHierarchyResp(); + } + + bool intOk = false; + UploadHierarchyResp uhr; + + uhr.m_root = NodeEntry::fromJsonRecursive(&jsonObj, intOk, true); + if (ok != Q_NULLPTR) { + *ok = intOk; + } + Q_ASSERT(uhr.m_root != Q_NULLPTR); + return intOk ? uhr : UploadHierarchyResp(); +} + +QByteArray UploadHierarchyResp::toJson(void) const +{ + if (m_root == Q_NULLPTR) { + Q_ASSERT(0); + return QJsonDocument(QJsonObject()).toJson( + QJsonDocument::Indented); + } + + QJsonObject jsonObj(jsonHierarchyNode(m_root->m_name, + m_root->m_id, m_root->m_metadata)); + + if (!NodeEntry::toJsonRecursive(&jsonObj, m_root->m_sub)) { + return QByteArray(); + } + + return QJsonDocument(jsonObj).toJson(QJsonDocument::Indented); +} + +UploadHierarchyResp &UploadHierarchyResp::operator=( + const UploadHierarchyResp &other) Q_DECL_NOTHROW +{ + NodeEntry *tmpRoot = Q_NULLPTR; + + if (other.m_root != Q_NULLPTR) { + tmpRoot = NodeEntry::copyRecursive(other.m_root); + if (tmpRoot == Q_NULLPTR) { + /* Copying failed. */ + Q_ASSERT(0); + } + } + + NodeEntry::deleteRecursive(m_root); + m_root = tmpRoot; + + return *this; +} diff -Nru datovka-4.8.3/src/records_management/json/upload_hierarchy.h datovka-4.9.3/src/records_management/json/upload_hierarchy.h --- datovka-4.8.3/src/records_management/json/upload_hierarchy.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/json/upload_hierarchy.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _UPLOAD_HIERARCHY_H_ +#define _UPLOAD_HIERARCHY_H_ + +#include +#include +#include +#include + +class QJsonObject; /* Forward declaration. */ + +/*! + * @brief Encapsulates the upload_hierarchy response. + */ +class UploadHierarchyResp { +public: + /*! + * @brief Node entry element. + */ + class NodeEntry { + private: + /*! + * @brief Constructor. + */ + NodeEntry(void); + + public: + /*! + * @brief Return superordinate node, + * + * @return Superordinate node. + */ + const NodeEntry *super(void) const; + + /*! + * @brief Returns node name. + * + * @return Node name. + */ + const QString &name(void) const; + + /*! + * @brief Returns node id. + * + * @return Node id. + */ + const QString &id(void) const; + + /*! + * @brief Returns metadata. + * + * @return Stored metadata. + */ + const QStringList &metadata(void) const; + + /*! + * @brief Returns list of subordinated nodes. + * + * @return List of subordinated nodes. + */ + const QList &sub(void) const; + + private: + /*! + * @brief Performs a recursive (deep) copy. + * + * @param[in] root Non-null tree root. + * @return Copied tree on success, null pointer on error. + */ + static + NodeEntry *copyRecursive(const NodeEntry *root); + + /*! + * @brief Recursively delete the tree of nodes. + * + * @param[in] root Root of the tree to delete. + */ + static + void deleteRecursive(NodeEntry *root); + + /*! + * @brief Recursively constructs a hierarchy. + * + * @param[in] jsonObj Object to be used as root of the hierarchy. + * @param[out] ok Set to true if no error encountered. + * @param[in] acceptNullName True if null values should be accepted. + * @return Parsed hierarchy if \a ok set to true. + */ + static + NodeEntry *fromJsonRecursive(const QJsonObject *jsonObj, + bool &ok, bool acceptNullName); + + /*! + * @brief Recursively constructs a JSON object hierarchy. + * + * @param[in,out] jsonObj JSON object to append sub-nodes to. + * @param[in] uhrList List of sub-nodes to convert to JSON nodes + * from and to add as sub-nodes. + * @return True on success. + */ + static + bool toJsonRecursive(QJsonObject *jsonObj, + const QList &uhrList); + + NodeEntry *m_super; /*!< Superordinate node. */ + QString m_name; /*!< Entry name. Root entry name may be null. */ + QString m_id; /*!< Entry identifier. May be null. */ + QStringList m_metadata; /*!< Metadata. List my be empty. */ + QList m_sub; /*!< Subordinated nodes. */ + + friend class UploadHierarchyResp; + }; + +public: + /*! + * @brief Constructor. Creates an invalid structure. + */ + UploadHierarchyResp(void); + + /*! + * @brief Copy constructor. + * + * @param[in] uhr Upload hierarchy response. + */ + UploadHierarchyResp(const UploadHierarchyResp &uhr); + + /*! + * @brief Destructor. + */ + ~UploadHierarchyResp(void); + + /*! + * @brief Returns root node. + * + * @return Root node. + */ + const NodeEntry *root(void) const; + + /*! + * @brief Check whether content is valid. + * + * @return True if content is valid. + */ + bool isValid(void) const; + + /*! + * @brief Creates a upload hierarchy structure from supplied JSON + * document. + * + * @param[in] json JSON document. + * @param[out] ok Set to true on success. + * @return Invalid structure on error a valid structure else. + */ + static + UploadHierarchyResp fromJson(const QByteArray &json, + bool *ok = Q_NULLPTR); + + /*! + * @brief Converts upload hierarchy structure into a JSON document. + * + * @note Unspecified values are stores as null into the JSON document. + * + * @return JSON document containing stored data. + */ + QByteArray toJson(void) const; + + /*! + * @brief Copy assignment. + * + * @param[in] other Source. + * @return Destination reference. + */ + UploadHierarchyResp &operator=( + const UploadHierarchyResp &other) Q_DECL_NOTHROW; + +#ifdef Q_COMPILER_RVALUE_REFS + /* TODO -- Move assignment. */ +#endif /* Q_COMPILER_RVALUE_REFS */ + +private: + NodeEntry *m_root; /*!< Tree root. */ +}; + +#endif /* _UPLOAD_HIERARCHY_H_ */ diff -Nru datovka-4.8.3/src/records_management/models/upload_hierarchy_model.cpp datovka-4.9.3/src/records_management/models/upload_hierarchy_model.cpp --- datovka-4.8.3/src/records_management/models/upload_hierarchy_model.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/models/upload_hierarchy_model.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include "src/records_management/models/upload_hierarchy_model.h" + +UploadHierarchyModel::UploadHierarchyModel(QObject *parent) + : QAbstractItemModel(parent), + m_hierarchy() +{ +} + +QModelIndex UploadHierarchyModel::index(int row, int column, + const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) { + return QModelIndex(); + } + + quintptr internalId = 0; + + if (!parent.isValid()) { + if (showRootName()) { + /* Root is shown. */ + internalId = (quintptr)m_hierarchy.root(); + } else { + /* Root is not shown. */ + internalId = (quintptr)m_hierarchy.root()->sub().at(row); + } + } else { + const UploadHierarchyResp::NodeEntry *entry = + (UploadHierarchyResp::NodeEntry *)parent.internalId(); + internalId = (quintptr)entry->sub().at(row); + } + + return createIndex(row, column, internalId); +} + +QModelIndex UploadHierarchyModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) { + return QModelIndex(); + } + + const UploadHierarchyResp::NodeEntry *iEntry = + (UploadHierarchyResp::NodeEntry *)index.internalId(); + const UploadHierarchyResp::NodeEntry *pEntry = iEntry->super(); + + if ((pEntry != Q_NULLPTR) && + ((pEntry != m_hierarchy.root()) || showRootName())) { + if (pEntry == m_hierarchy.root()) { + /* Root node is shown and parent is root. */ + return createIndex(0, 0, (quintptr)pEntry); + } else { + const UploadHierarchyResp::NodeEntry *ppEntry = + pEntry->super(); + int row = 0; + /* Find position of parent. */ + for ( ; row < ppEntry->sub().size(); ++row) { + if (pEntry == ppEntry->sub().at(row)) { + break; + } + } + Q_ASSERT(row < ppEntry->sub().size()); + return createIndex(row, 0, (quintptr)pEntry); + } + } else { + return QModelIndex(); + } +} + +int UploadHierarchyModel::rowCount(const QModelIndex &parent) const +{ + if (parent.column() > 0) { + return 0; + } + + if (!parent.isValid()) { + if (!m_hierarchy.isValid()) { + /* Invalid hierarchy. */ + return 0; + } + + /* Root. */ + if (showRootName()) { + return 1; + } else { + return m_hierarchy.root()->sub().size(); + } + } else { + const UploadHierarchyResp::NodeEntry *entry = + (UploadHierarchyResp::NodeEntry *)parent.internalId(); + return entry->sub().size(); + } +} + +int UploadHierarchyModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return 1; +} + +QVariant UploadHierarchyModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + const UploadHierarchyResp::NodeEntry *entry = + (UploadHierarchyResp::NodeEntry *)index.internalId(); + if (entry == Q_NULLPTR) { + Q_ASSERT(0); + return QVariant(); + } + + switch (role) { + case Qt::DisplayRole: + return entry->name(); + break; + case Qt::ToolTipRole: + return filterData(entry).join(QStringLiteral("\n")); + break; + case ROLE_FILTER: + return filterDataRecursive(entry, true); + break; + case ROLE_ID: + return entry->id(); + break; + default: + return QVariant(); + break; + } +} + +QVariant UploadHierarchyModel::headerData(int section, + Qt::Orientation orientation, int role) const +{ + if ((Qt::Horizontal == orientation) && (Qt::DisplayRole == role) && + (0 == section)) { + return tr("Records Management Hierarchy"); + } + + return QVariant(); +} + +Qt::ItemFlags UploadHierarchyModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) { + return Qt::NoItemFlags; + } + + Qt::ItemFlags flags = + QAbstractItemModel::flags(index) & ~Qt::ItemIsEditable; + + const UploadHierarchyResp::NodeEntry *entry = + (UploadHierarchyResp::NodeEntry *)index.internalId(); + if (entry->id().isEmpty()) { + flags &= ~Qt::ItemIsSelectable; + } + + return flags; +} + +void UploadHierarchyModel::setHierarchy(const UploadHierarchyResp &uhr) +{ + beginResetModel(); + m_hierarchy = uhr; + endResetModel(); +} + +bool UploadHierarchyModel::showRootName(void) const +{ + return m_hierarchy.isValid() && !m_hierarchy.root()->name().isEmpty(); +} + +QStringList UploadHierarchyModel::filterData( + const UploadHierarchyResp::NodeEntry *entry) +{ + if (Q_UNLIKELY(entry == Q_NULLPTR)) { + Q_ASSERT(0); + return QStringList(); + } + + return QStringList(entry->name()) + entry->metadata(); +} + +QStringList UploadHierarchyModel::filterDataRecursive( + const UploadHierarchyResp::NodeEntry *entry, bool takeSuper) +{ + if (Q_UNLIKELY(entry == Q_NULLPTR)) { + Q_ASSERT(0); + return QStringList(); + } + + QStringList res(filterData(entry)); + foreach (const UploadHierarchyResp::NodeEntry *sub, entry->sub()) { + res += filterDataRecursive(sub, false); + } + if (takeSuper) { + /* + * Add also filter data from superordinate node. This has the + * effect that all sub-nodes (including those not matching the + * filter) of a node which matches the entered filter are + * going to be also displayed. + */ + const UploadHierarchyResp::NodeEntry *sup = entry->super(); + if (Q_UNLIKELY(sup == Q_NULLPTR)) { + return res; + } + res += filterData(sup); + } + + return res; +} diff -Nru datovka-4.8.3/src/records_management/models/upload_hierarchy_model.h datovka-4.9.3/src/records_management/models/upload_hierarchy_model.h --- datovka-4.8.3/src/records_management/models/upload_hierarchy_model.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/models/upload_hierarchy_model.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _UPLOAD_HIERARCHY_MODEL_H_ +#define _UPLOAD_HIERARCHY_MODEL_H_ + +#include + +#include "src/records_management/json/upload_hierarchy.h" + +/*! + * @brief Upload hierarchy model. + */ +class UploadHierarchyModel : public QAbstractItemModel { + Q_OBJECT +public: + /*! + * @brief Custom roles. + */ + enum CustomRoles { + ROLE_FILTER = (Qt::UserRole + 1), /* Exposes metadata for filtering. */ + ROLE_ID /* Hierarchy entry identifier. */ + }; + + /*! + * @brief Constructor. + * + * @param[in] parent Pointer to parent object. + */ + explicit UploadHierarchyModel(QObject *parent = Q_NULLPTR); + + /*! + * @brief Return index specified by supplied parameters. + * + * @param[in] row Item row. + * @param[in] column Parent column. + * @param[in] parent Parent index. + * @return Index to desired element or invalid index on error. + */ + virtual + QModelIndex index(int row, int column, + const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; + + /*! + * @brief Return parent index of the item with the given index. + * + * @param[in] index Child node index. + * @return Index of the parent node or invalid index on error. + */ + virtual + QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; + + /*! + * @brief Return number of rows under the given parent. + * + * @param[in] parent Parent node index. + * @return Number of rows. + */ + virtual + int rowCount(const QModelIndex &parent = QModelIndex()) const + Q_DECL_OVERRIDE; + + /*! + * @brief Return the number of columns for the children of given parent. + * + * @param[in] parent Parent node index. + * @return Number of columns. + */ + virtual + int columnCount(const QModelIndex &parent = QModelIndex()) const + Q_DECL_OVERRIDE; + + /*! + * @brief Return data stored in given location under given role. + * + * @param[in] index Index specifying the item. + * @param[in] role Data role. + * @return Data from model. + */ + virtual + QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; + + /*! + * @brief Returns header data in given location under given role. + * + * @brief[in] section Header position. + * @brief[in] orientation Header orientation. + * @brief[in] role Data role. + * @return Header data from model. + */ + virtual + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; + + /*! + * @brief Returns item flags for given index. + * + * @brief[in] index Index specifying the item. + * @return Item flags. + */ + virtual + Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; + + /*! + * @brief Set content data. + * + * @param[in] uhr Upload hierarchy response structure. + */ + void setHierarchy(const UploadHierarchyResp &uhr); + +private: + /*! + * @brief Check whether to show root name. + * + * @return True in root node contains a name. + */ + bool showRootName(void) const; + + /*! + * @brief Return all data related to node which can be used for + * filtering. + * + * @param[in] entry Node identifier. + * @return List of strings. + */ + static + QStringList filterData(const UploadHierarchyResp::NodeEntry *entry); + + /*! + * @brief Returns list of all (meta)data (including children). + * + * @param[in] entry Node identifying the root. + * @param[in] takeSuper Set true when data of superordinate node should + * be taken into account. + * @return List of all gathered data according to which can be filtered. + */ + static + QStringList filterDataRecursive( + const UploadHierarchyResp::NodeEntry *entry, bool takeSuper); + + UploadHierarchyResp m_hierarchy; /*!< Upload hierarchy structure. */ +}; + +#endif /* _UPLOAD_HIERARCHY_MODEL_H_ */ diff -Nru datovka-4.8.3/src/records_management/models/upload_hierarchy_proxy_model.cpp datovka-4.9.3/src/records_management/models/upload_hierarchy_proxy_model.cpp --- datovka-4.8.3/src/records_management/models/upload_hierarchy_proxy_model.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/models/upload_hierarchy_proxy_model.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include "src/localisation/localisation.h" +#include "src/records_management/models/upload_hierarchy_proxy_model.h" + +UploadHierarchyProxyModel::UploadHierarchyProxyModel(QObject *parent) + : QSortFilterProxyModel(parent) +{ +} + +bool UploadHierarchyProxyModel::filterAcceptsRow(int sourceRow, + const QModelIndex &sourceParent) const +{ + /* + * Adapted from + * qtbase/src/corelib/itemmodels/qsortfilterproxymodel.cpp . + */ + + if (filterRegExp().isEmpty()) { + return true; + } + + QModelIndex sourceIndex(sourceModel()->index(sourceRow, + filterKeyColumn(), sourceParent)); + return filterAcceptsItem(sourceIndex); +} + +bool UploadHierarchyProxyModel::lessThan(const QModelIndex &sourceLeft, + const QModelIndex &sourceRight) const +{ + QVariant leftData(sourceModel()->data(sourceLeft, filterRole())); + QVariant rightData(sourceModel()->data(sourceRight, filterRole())); + + if (Q_LIKELY(leftData.canConvert())) { + Q_ASSERT(rightData.canConvert()); + return Localisation::stringCollator.compare(leftData.toString(), + rightData.toString()) < 0; + } else { + return QSortFilterProxyModel::lessThan(sourceLeft, sourceRight); + } +} + +bool UploadHierarchyProxyModel::filterAcceptsItem( + const QModelIndex &sourceIdx) const +{ + if (!sourceIdx.isValid()) { + return false; + } + + QStringList filterData; + { + const QVariant data( + sourceModel()->data(sourceIdx, filterRole())); + if (data.canConvert()) { + filterData += data.toString(); + } else if (data.canConvert()) { + filterData += data.toStringList(); + } else { + return false; + } + } + + foreach (const QString &str, filterData) { + if (str.contains(filterRegExp())) { + return true; + } + } + return false; +} diff -Nru datovka-4.8.3/src/records_management/models/upload_hierarchy_proxy_model.h datovka-4.9.3/src/records_management/models/upload_hierarchy_proxy_model.h --- datovka-4.8.3/src/records_management/models/upload_hierarchy_proxy_model.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/models/upload_hierarchy_proxy_model.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _UPLOAD_HIERARCHY_PROXY_MODEL_H_ +#define _UPLOAD_HIERARCHY_PROXY_MODEL_H_ + +#include + +/*! + * @brief Enables filtering according to metadata. + */ +class UploadHierarchyProxyModel : public QSortFilterProxyModel { + Q_OBJECT +public: + /*! + * @brief Constructor. + * + * @param[in] parent Parent object. + */ + explicit UploadHierarchyProxyModel(QObject *parent = Q_NULLPTR); + +protected: + /*! + * @brief Returns true if the item in the row indicated by the + * given source row and source parent should be included in the + * model; otherwise returns false. + * + * @param[in] sourceRow Row number. + * @param[in] sourceParent Parent index. + * @return Whether the row indicated should be included in the model. + */ + virtual + bool filterAcceptsRow(int sourceRow, + const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; + + /*! + * @brief Returns true if the value of the item referred to by the + * given left index is less than the value of the item referred to + * by the given right index, otherwise returns false. + * + * @param[in] sourceLeft Left index. + * @param[in] sourceRight Right index. + * @return Whether the left index precedes the right index. + */ + virtual + bool lessThan(const QModelIndex &sourceLeft, + const QModelIndex &sourceRight) const Q_DECL_OVERRIDE; + +private: + /*! + * @brief Returns true if the item should be included in the model. + * + * @param[in] sourceIdx Source index. + * @return Whether the item meets the criteria. + */ + bool filterAcceptsItem(const QModelIndex &sourceIdx) const; +}; + +#endif /* _UPLOAD_HIERARCHY_PROXY_MODEL_H_ */ diff -Nru datovka-4.8.3/src/records_management/ui/dlg_records_management_stored.ui datovka-4.9.3/src/records_management/ui/dlg_records_management_stored.ui --- datovka-4.8.3/src/records_management/ui/dlg_records_management_stored.ui 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/ui/dlg_records_management_stored.ui 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,123 @@ + + + DlgRecordsManagementStored + + + + 0 + 0 + 400 + 120 + + + + Records Management Stored Messages + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + + + 24 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + DlgRecordsManagementStored + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DlgRecordsManagementStored + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff -Nru datovka-4.8.3/src/records_management/ui/dlg_records_management.ui datovka-4.9.3/src/records_management/ui/dlg_records_management.ui --- datovka-4.8.3/src/records_management/ui/dlg_records_management.ui 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/ui/dlg_records_management.ui 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,175 @@ + + + DlgRecordsManagement + + + + 0 + 0 + 400 + 300 + + + + Records Management Settings + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Service location URL. + + + URL: + + + + + + + + + + Access token into the records management service. + + + Token: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Service Info + + + + + + + Erase + + + + + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Service name: + + + + + + + + + + Token name: + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + SvgView + QGraphicsView +
    src/records_management/widgets/svg_view.h
    +
    +
    + + + + buttonBox + accepted() + DlgRecordsManagement + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DlgRecordsManagement + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
    diff -Nru datovka-4.8.3/src/records_management/ui/dlg_records_management_upload.ui datovka-4.9.3/src/records_management/ui/dlg_records_management_upload.ui --- datovka-4.8.3/src/records_management/ui/dlg_records_management_upload.ui 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/ui/dlg_records_management_upload.ui 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,141 @@ + + + DlgRecordsManagementUpload + + + + 0 + 0 + 400 + 300 + + + + Upload Message into Records Management Service + + + + + + + + + + + + + + + + + + + Appeal + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + Reload + + + + + + + Filter: + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + LoweredTreeView + QTreeView +
    lowered_tree_view.h
    +
    +
    + + + + buttonBox + accepted() + DlgRecordsManagementUpload + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DlgRecordsManagementUpload + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
    diff -Nru datovka-4.8.3/src/records_management/widgets/svg_view.cpp datovka-4.9.3/src/records_management/widgets/svg_view.cpp --- datovka-4.8.3/src/records_management/widgets/svg_view.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/widgets/svg_view.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include + +#include "src/records_management/widgets/svg_view.h" + +/* + * See following for inspiration: + * https://stackoverflow.com/questions/14107144/how-do-i-make-an-image-resize-to-scale-in-qt + * https://stackoverflow.com/questions/8551690/how-to-render-a-scaled-svg-to-a-qimage + * https://stackoverflow.com/questions/37114430/qt-qgraphicssvgitem-scaleing-and-resizeing + * https://stackoverflow.com/questions/16013027/setting-an-image-to-a-label-in-qt + */ + +SvgView::SvgView(QWidget *parent) + : QGraphicsView(parent), + m_svgData() +{ +} + +void SvgView::setSvgData(const QByteArray &svgData) +{ + m_svgData = svgData; + + setUp(); + + if (!m_svgData.isEmpty()) { + displaySvg(m_svgData); + } +} + +/*! + * @brief Resize graphics item to fit graphics view. + * + * @param[in] gv Graphics view. + * @param[in,out] gi Graphics item to be resized. + */ +static +void resizeGraphicsItem(const QGraphicsView *gv, QGraphicsItem *gi) +{ + if ((Q_NULLPTR == gv) || (Q_NULLPTR == gi)) { + Q_ASSERT(0); + return; + } + + qreal wscale = gv->geometry().size().width() / + gi->boundingRect().size().width(); + qreal hscale = gv->geometry().size().height() / + gi->boundingRect().size().height(); + + gi->setScale((wscale < hscale) ? wscale : hscale); +} + +#define SVG_ITEM_NAME QStringLiteral("svgItem") + +void SvgView::resizeEvent(QResizeEvent *event) +{ + QGraphicsView::resizeEvent(event); + + QGraphicsScene *s = this->scene(); + + /* Find SVG item and resize it. */ + QGraphicsSvgItem *svgItem = Q_NULLPTR; + foreach (QGraphicsItem *item, s->items()) { + /* Cannot use qobject_cast() here. */ + svgItem = dynamic_cast(item); + if (svgItem == Q_NULLPTR) { + continue; + } + if (svgItem->objectName() == SVG_ITEM_NAME) { + break; + } + svgItem = Q_NULLPTR; + } + + if (svgItem == Q_NULLPTR) { + return; + } + resizeGraphicsItem(this, svgItem); +} + +void SvgView::setUp(void) +{ + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + setScene(new (std::nothrow) QGraphicsScene(this)); + setTransformationAnchor(QGraphicsView::AnchorUnderMouse); + setDragMode(QGraphicsView::ScrollHandDrag); + setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + + /* Prepare background check-board pattern. */ + QPixmap tilePixmap(64, 64); + tilePixmap.fill(Qt::white); + QPainter tilePainter(&tilePixmap); + QColor color(220, 220, 220); + tilePainter.fillRect(0, 0, 32, 32, color); + tilePainter.fillRect(32, 32, 32, 32, color); + tilePainter.end(); + + setBackgroundBrush(tilePixmap); +} + +void SvgView::displaySvg(const QByteArray &svgData) +{ + if (svgData.isEmpty()) { + return; + } + + QGraphicsScene *s = this->scene(); + + QGraphicsSvgItem *svgItem = new (std::nothrow) QGraphicsSvgItem(); + svgItem->setObjectName(SVG_ITEM_NAME);; + { + QSvgRenderer *svgRenderer = + new (std::nothrow) QSvgRenderer(svgData, this); + svgItem->setSharedRenderer(svgRenderer); + } + + s->clear(); + this->resetTransform(); + + svgItem->setFlags(QGraphicsItem::ItemClipsToShape); + svgItem->setCacheMode(QGraphicsItem::NoCache); + svgItem->setZValue(0); + resizeGraphicsItem(this, svgItem); + +#if 0 + QGraphicsRectItem *backgroundItem = + new (std::nothrow) QGraphicsRectItem(svgItem->boundingRect()); + backgroundItem->setBrush(Qt::white); + backgroundItem->setPen(Qt::NoPen); + backgroundItem->setVisible(false); + backgroundItem->setZValue(-1); + + s->addItem(backgroundItem); +#endif + s->addItem(svgItem); +} diff -Nru datovka-4.8.3/src/records_management/widgets/svg_view.h datovka-4.9.3/src/records_management/widgets/svg_view.h --- datovka-4.8.3/src/records_management/widgets/svg_view.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/records_management/widgets/svg_view.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _SVG_VIEW_H_ +#define _SVG_VIEW_H_ + +#include +#include + +/*! + * @brief Graphics view class dedicated for viewing SVG content. + */ +class SvgView : public QGraphicsView { + Q_OBJECT + +public: + /*! + * @brief Constructor. + * + * @param[in] parent Parent widget. + */ + explicit SvgView(QWidget *parent = Q_NULLPTR); + + /*! + * @brief Set SVG data. + * + * @param[in] svgData SVG data to be painted. + */ + void setSvgData(const QByteArray &svgData); + +protected: + /*! + * @brief Resizes the displayed SVG content. + */ + virtual + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + +private: + /*! + * @brief Configures the graphics view. + */ + void setUp(void); + + /*! + * @brief Displays SVG image. + * + * @param[in] svgData SVG data to be displayed. + */ + void displaySvg(const QByteArray &svgData); + + QByteArray m_svgData; /*!< Brief holds SVG data to be painted. */ +}; + +#endif /* _SVG_VIEW_H_ */ diff -Nru datovka-4.8.3/src/settings/account.cpp datovka-4.9.3/src/settings/account.cpp --- datovka-4.8.3/src/settings/account.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/settings/account.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,501 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/common.h" +#include "src/settings/account.h" +#include "src/settings/preferences.h" + +namespace CredNames { + const QString creds(QLatin1String("credentials")); + + const QString acntName(QLatin1String("name")); + const QString userName(QLatin1String("username")); + const QString lMethod(QLatin1String("login_method")); + const QString pwd(QLatin1String("password")); + const QString testAcnt(QLatin1String("test_account")); + const QString rememberPwd(QLatin1String("remember_password")); + const QString dbDir(QLatin1String("database_dir")); + const QString syncWithAll(QLatin1String("sync_with_all")); + const QString p12File(QLatin1String("p12file")); + const QString lstMsgId(QLatin1String("last_message_id")); + const QString lstSaveAtchPath(QLatin1String("last_save_attach_path")); + const QString lstAddAtchPath(QLatin1String("last_add_attach_path")); + const QString lstCorrspPath(QLatin1String("last_export_corresp_path")); + const QString lstZfoPath(QLatin1String("last_export_zfo_path")); +} + +/* The following are not stored into the configuration file. */ +/* Only set on new accounts. */ +#define _CREATED_FROM_SCRATCH "_created_from_cratch" +#define _PKEY_PASSPHRASE "_pkey_passphrase" +#define _OTP_CODE "_otp_code" +#define _PWD_EXPIR_DLG_SHOWN "_pwd_expir_dlg_shown" + +/*! + * @brief Login method names as stored in configuration file. + */ +namespace MethodNames { + static const QString uNamePwd(QLatin1String("username")); + static const QString uNameCrt(QLatin1String("certificate")); + static const QString uNamePwdCrt(QLatin1String("user_certificate")); + static const QString uNamePwdHotp(QLatin1String("hotp")); + static const QString uNamePwdTotp(QLatin1String("totp")); +} + +/*! + * @brief Converts integer to login method identifier. + * + * @param[in] num Integer number. + * @return Identifier value. + */ +static +enum AcntSettings::LogInMethod methodIntToEnum(int num) +{ + switch (num) { + case AcntSettings::LIM_UNAME_PWD: + return AcntSettings::LIM_UNAME_PWD; + break; + case AcntSettings::LIM_UNAME_CRT: + return AcntSettings::LIM_UNAME_CRT; + break; + case AcntSettings::LIM_UNAME_PWD_CRT: + return AcntSettings::LIM_UNAME_PWD_CRT; + break; + case AcntSettings::LIM_UNAME_PWD_HOTP: + return AcntSettings::LIM_UNAME_PWD_HOTP; + break; + case AcntSettings::LIM_UNAME_PWD_TOTP: + return AcntSettings::LIM_UNAME_PWD_TOTP; + break; + case AcntSettings::LIM_UNKNOWN: + default: + return AcntSettings::LIM_UNKNOWN; + break; + } +} + +/*! + * @brief Converts login method string to identifier. + * + * @param[in] str Identifier string as used in configuration file. + * @return Identifier value. + */ +static +enum AcntSettings::LogInMethod methodStrToEnum(const QString &str) +{ + if (str == MethodNames::uNamePwd) { + return AcntSettings::LIM_UNAME_PWD; + } else if (str == MethodNames::uNameCrt) { + return AcntSettings::LIM_UNAME_CRT; + } else if (str == MethodNames::uNamePwdCrt) { + return AcntSettings::LIM_UNAME_PWD_CRT; + } else if (str == MethodNames::uNamePwdHotp) { + return AcntSettings::LIM_UNAME_PWD_HOTP; + } else if (str == MethodNames::uNamePwdTotp) { + return AcntSettings::LIM_UNAME_PWD_TOTP; + } else { + return AcntSettings::LIM_UNKNOWN; + } +} + +/*! + * @brief Converts login method identifier to string. + * + * @param[in] val Identifier value as used in the programme. + * @return Identifier string as used in configuration file. + */ +static +const QString &methodEnumToStr(enum AcntSettings::LogInMethod val) +{ + static const QString nullStr; + + switch (val) { + case AcntSettings::LIM_UNAME_PWD: + return MethodNames::uNamePwd; + break; + case AcntSettings::LIM_UNAME_CRT: + return MethodNames::uNameCrt; + break; + case AcntSettings::LIM_UNAME_PWD_CRT: + return MethodNames::uNamePwdCrt; + break; + case AcntSettings::LIM_UNAME_PWD_HOTP: + return MethodNames::uNamePwdHotp; + break; + case AcntSettings::LIM_UNAME_PWD_TOTP: + return MethodNames::uNamePwdTotp; + break; + case AcntSettings::LIM_UNKNOWN: + default: + Q_ASSERT(0); + return nullStr; + break; + } +} + +AcntSettings::AcntSettings(void) + : QMap() +{ +} + +AcntSettings::AcntSettings(const QMap &map) + : QMap(map) +{ +} + +bool AcntSettings::isValid(void) const +{ + return !m_parentType::isEmpty() && + !accountName().isEmpty() && !userName().isEmpty(); +} + +QString AcntSettings::accountName(void) const +{ + return m_parentType::operator[](CredNames::acntName).toString(); +} + +void AcntSettings::setAccountName(const QString &name) +{ + m_parentType::operator[](CredNames::acntName) = name; +} + +QString AcntSettings::userName(void) const +{ + return m_parentType::operator[](CredNames::userName).toString(); +} + +void AcntSettings::setUserName(const QString &userName) +{ + m_parentType::operator[](CredNames::userName) = userName; +} + +enum AcntSettings::LogInMethod AcntSettings::loginMethod(void) const +{ + return methodIntToEnum( + m_parentType::value(CredNames::lMethod, LIM_UNKNOWN).toInt()); +} + +void AcntSettings::setLoginMethod(enum LogInMethod method) +{ + if (method != LIM_UNKNOWN) { + m_parentType::insert(CredNames::lMethod, method); + } else { + m_parentType::remove(CredNames::lMethod); + } +} + +QString AcntSettings::password(void) const +{ + return m_parentType::operator[](CredNames::pwd).toString(); +} + +void AcntSettings::setPassword(const QString &pwd) +{ + m_parentType::operator[](CredNames::pwd) = pwd; +} + +bool AcntSettings::isTestAccount(void) const +{ + return m_parentType::operator[](CredNames::testAcnt).toBool(); +} + +void AcntSettings::setTestAccount(bool isTesting) +{ + m_parentType::operator[](CredNames::testAcnt) = isTesting; +} + +bool AcntSettings::rememberPwd(void) const +{ + return m_parentType::operator[](CredNames::rememberPwd).toBool(); +} + +void AcntSettings::setRememberPwd(bool remember) +{ + m_parentType::operator[](CredNames::rememberPwd) = remember; +} + +QString AcntSettings::dbDir(void) const +{ + return m_parentType::operator[](CredNames::dbDir).toString(); +} + +void AcntSettings::setDbDir(const QString &path) +{ + if (path == globPref.confDir()) { + /* Default path is empty. */ + m_parentType::operator[](CredNames::dbDir) = QString(); + } else { + m_parentType::operator[](CredNames::dbDir) = path; + } +} + +bool AcntSettings::syncWithAll(void) const +{ + return m_parentType::operator[](CredNames::syncWithAll).toBool(); +} + +void AcntSettings::setSyncWithAll(bool sync) +{ + m_parentType::operator[](CredNames::syncWithAll) = sync; +} + +QString AcntSettings::p12File(void) const +{ + return m_parentType::operator[](CredNames::p12File).toString(); +} + +void AcntSettings::setP12File(const QString &p12) +{ + m_parentType::operator[](CredNames::p12File) = p12; +} + +qint64 AcntSettings::lastMsg(void) const +{ + return m_parentType::value(CredNames::lstMsgId, -1).toLongLong(); +} + +void AcntSettings::setLastMsg(qint64 dmId) +{ + m_parentType::insert(CredNames::lstMsgId, dmId); +} + +QString AcntSettings::lastAttachSavePath(void) const +{ + return m_parentType::operator[](CredNames::lstSaveAtchPath).toString(); +} + +void AcntSettings::setLastAttachSavePath(const QString &path) +{ + m_parentType::operator[](CredNames::lstSaveAtchPath) = path; +} + +QString AcntSettings::lastAttachAddPath(void) const +{ + return m_parentType::operator[](CredNames::lstAddAtchPath).toString(); +} + +void AcntSettings::setLastAttachAddPath(const QString &path) +{ + m_parentType::operator[](CredNames::lstAddAtchPath) = path; +} + +QString AcntSettings::lastCorrespPath(void) const +{ + return m_parentType::operator[](CredNames::lstCorrspPath).toString(); +} + +void AcntSettings::setLastCorrespPath(const QString &path) +{ + m_parentType::operator[](CredNames::lstCorrspPath) = path; +} + +QString AcntSettings::lastZFOExportPath(void) const +{ + return m_parentType::operator[](CredNames::lstZfoPath).toString(); +} + +void AcntSettings::setLastZFOExportPath(const QString &path) +{ + m_parentType::operator[](CredNames::lstZfoPath) = path; +} + +bool AcntSettings::_createdFromScratch(void) const +{ + return m_parentType::value(_CREATED_FROM_SCRATCH, false).toBool(); +} + +void AcntSettings::_setCreatedFromScratch(bool fromScratch) +{ + m_parentType::insert(_CREATED_FROM_SCRATCH, fromScratch); +} + +QString AcntSettings::_passphrase(void) const +{ + return m_parentType::value(_PKEY_PASSPHRASE, QString()).toString(); +} + +void AcntSettings::_setPassphrase(const QString &passphrase) +{ + if (!passphrase.isNull()) { + m_parentType::insert(_PKEY_PASSPHRASE, passphrase); + } else { + m_parentType::remove(_PKEY_PASSPHRASE); + } +} + +QString AcntSettings::_otp(void) const +{ + return m_parentType::value(_OTP_CODE, QString()).toString(); +} + +void AcntSettings::_setOtp(const QString &otpCode) +{ + if (!otpCode.isNull()) { + m_parentType::insert(_OTP_CODE, otpCode); + } else { + m_parentType::remove(_OTP_CODE); + } +} + +bool AcntSettings::_pwdExpirDlgShown(void) const +{ + return m_parentType::value(_PWD_EXPIR_DLG_SHOWN, false).toBool(); +} + +void AcntSettings::_setPwdExpirDlgShown(bool pwdExpirDlgShown) +{ + m_parentType::insert(_PWD_EXPIR_DLG_SHOWN, pwdExpirDlgShown); +} + +void AcntSettings::loadFromSettings(const QSettings &settings, + const QString &group) +{ + QString prefix; + if (!group.isEmpty()) { + prefix = group + "/"; + } + + /* + * String containing comma character are loaded as a string list. + * + * FIXME -- Any white-space characters trailing the comma are lost. + */ + setAccountName(settings.value(prefix + CredNames::acntName, + "").toStringList().join(", ")); + setUserName(settings.value(prefix + CredNames::userName, + "").toString()); + setLoginMethod(methodStrToEnum( + settings.value(prefix + CredNames::lMethod, "").toString())); + setPassword(fromBase64(settings.value(prefix + CredNames::pwd, + "").toString())); + setTestAccount(settings.value(prefix + CredNames::testAcnt, + "").toBool()); + setRememberPwd(settings.value(prefix + CredNames::rememberPwd, + "").toBool()); + setDbDir(settings.value(prefix + CredNames::dbDir, + "").toString()); + setSyncWithAll(settings.value(prefix + CredNames::syncWithAll, + "").toBool()); + setP12File(settings.value(prefix + CredNames::p12File, + "").toString()); + setLastMsg(settings.value(prefix + CredNames::lstMsgId, + "").toLongLong()); + setLastAttachSavePath(settings.value(prefix + CredNames::lstSaveAtchPath, + "").toString()); + setLastAttachAddPath(settings.value(prefix + CredNames::lstAddAtchPath, + "").toString()); + setLastCorrespPath(settings.value(prefix + CredNames::lstCorrspPath, + "").toString()); + setLastZFOExportPath(settings.value(prefix + CredNames::lstZfoPath, + "").toString()); +} + +void AcntSettings::saveToSettings(QSettings &settings, + const QString &group) const +{ + if (!group.isEmpty()) { + settings.beginGroup(group); + } + + settings.setValue(CredNames::acntName, accountName()); + settings.setValue(CredNames::userName, userName()); + settings.setValue(CredNames::lMethod, methodEnumToStr(loginMethod())); + settings.setValue(CredNames::testAcnt, isTestAccount()); + settings.setValue(CredNames::rememberPwd, rememberPwd()); + if (rememberPwd()) { + if (!password().isEmpty()) { + settings.setValue(CredNames::pwd, toBase64(password())); + } + } + + if (!dbDir().isEmpty()) { + if (QDir(dbDir()) != QDir(globPref.confDir())) { + settings.setValue(CredNames::dbDir, dbDir()); + } + } + if (!p12File().isEmpty()) { + settings.setValue(CredNames::p12File, p12File()); + } + + settings.setValue(CredNames::syncWithAll, syncWithAll()); + + if (0 <= lastMsg()) { + settings.setValue(CredNames::lstMsgId, lastMsg()); + } + + /* Save last attachments save path. */ + if (!lastAttachSavePath().isEmpty()) { + settings.setValue(CredNames::lstSaveAtchPath, + lastAttachSavePath()); + } + + /* Save last attachments add path. */ + if (!lastAttachAddPath().isEmpty()) { + settings.setValue(CredNames::lstAddAtchPath, + lastAttachAddPath()); + } + + /* Save last correspondence export path. */ + if (!lastCorrespPath().isEmpty()) { + settings.setValue(CredNames::lstCorrspPath, lastCorrespPath()); + } + + /* save last ZFO export path */ + if (!lastZFOExportPath().isEmpty()) { + settings.setValue(CredNames::lstZfoPath, lastZFOExportPath()); + } + + if (!group.isEmpty()) { + settings.endGroup(); + } +} + +bool AcntSettings::credentialsLessThan(const QString &s1, const QString &s2) +{ + QRegExp trailingNumRe("(.*[^0-9]+)*([0-9]+)"); + QString a1, a2; + int n1, n2; + int pos; + + pos = trailingNumRe.indexIn(s1); + if (pos > -1) { + a1 = trailingNumRe.cap(1); + n1 = trailingNumRe.cap(2).toInt(); + } else { + a1 = s1; + n1 = -1; + } + + pos = trailingNumRe.indexIn(s2); + if (pos > -1) { + a2 = trailingNumRe.cap(1); + n2 = trailingNumRe.cap(2).toInt(); + } else { + a2 = s2; + n2 = -1; + } + + return (a1 != a2) ? (a1 < a2) : (n1 < n2); +} diff -Nru datovka-4.8.3/src/settings/account.h datovka-4.9.3/src/settings/account.h --- datovka-4.8.3/src/settings/account.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/settings/account.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _ACCOUNT_H_ +#define _ACCOUNT_H_ + +#include +#include +#include +#include + +/*! + * @brief Defines labels used in credentials. + */ +namespace CredNames { + extern const QString creds; + + extern const QString acntName; + extern const QString userName; + extern const QString lMethod; + extern const QString pwd; + extern const QString testAcnt; + extern const QString rememberPwd; + extern const QString dbDir; + extern const QString syncWithAll; + extern const QString p12File; + extern const QString lstMsgId; + extern const QString lstSaveAtchPath; + extern const QString lstAddAtchPath; + extern const QString lstCorrspPath; + extern const QString lstZfoPath; +} + +/*! + * @brief Holds account settings. + */ +class AcntSettings : public QMap { +public: + /*! + * @brief Login method identifier. + */ + enum LogInMethod { + LIM_UNKNOWN, /*!< Unknown method. */ + LIM_UNAME_PWD, /*!< User name and password. */ + LIM_UNAME_CRT, /*!< User name and certificate. */ + LIM_UNAME_PWD_CRT, /*!< User name, password and certificate. */ + LIM_UNAME_PWD_HOTP, /*!< User name, password and HOTP. */ + LIM_UNAME_PWD_TOTP /*!< User name, password and TOTP (SMS). */ + }; + + /*! + * @brief Constructor. + */ + AcntSettings(void); + AcntSettings(const QMap &map); + + bool isValid(void) const; + QString accountName(void) const; + void setAccountName(const QString &name); + QString userName(void) const; + void setUserName(const QString &userName); + enum LogInMethod loginMethod(void) const; + void setLoginMethod(enum LogInMethod method); + QString password(void) const; + void setPassword(const QString &pwd); + bool isTestAccount(void) const; + void setTestAccount(bool isTesting); + bool rememberPwd(void) const; + void setRememberPwd(bool remember); + QString dbDir(void) const; + void setDbDir(const QString &path); + bool syncWithAll(void) const; + void setSyncWithAll(bool sync); + QString p12File(void) const; + void setP12File(const QString &p12); + qint64 lastMsg(void) const; + void setLastMsg(qint64 dmId); + QString lastAttachSavePath(void) const; + void setLastAttachSavePath(const QString &path); + QString lastAttachAddPath(void) const; + void setLastAttachAddPath(const QString &path); + QString lastCorrespPath(void) const; + void setLastCorrespPath(const QString &path); + QString lastZFOExportPath(void) const; + void setLastZFOExportPath(const QString &path); + + bool _createdFromScratch(void) const; + void _setCreatedFromScratch(bool fromScratch); + QString _passphrase(void) const; + void _setPassphrase(const QString &passphrase); + QString _otp(void) const; + void _setOtp(const QString &otpCode); + bool _pwdExpirDlgShown(void) const; + void _setPwdExpirDlgShown(bool pwdExpirDlgShown); + + /*! + * @brief Load content from settings group. + * + * @note Content is not erased before new settings is loaded. + * + * @param[in] settings Settings structure to load data from. + * @param[in] group Name of group to work with. + */ + void loadFromSettings(const QSettings &settings, const QString &group); + + /*! + * @brief Save content to settings. + * + * @param[out] settings Settings structure to write/append data into. + * @param[in] group Name of group to write to, group is create only + * when non-empty string supplied. + */ + void saveToSettings(QSettings &settings, const QString &group) const; + + /*! + * @brief Used for sorting credentials. + * + * @param[in] s1 credentials[0-9]* + * @param[in] s2 credentials[0-9]* + * @return True if s1 comes before s2. + * + * @note The number is taken by its value rather like a string of characters. + * cred < cred1 < cred2 < ... < cred10 < ... < cred100 < ... + */ + static + bool credentialsLessThan(const QString &s1, const QString &s2); + +private: + /* Prohibit these methods in public interface. */ + QVariant operator[](const QString &key); + const QVariant operator[](const QString &key) const; + + typedef QMap m_parentType; +}; + +#endif /* _ACCOUNT_H_ */ diff -Nru datovka-4.8.3/src/settings/accounts.cpp datovka-4.9.3/src/settings/accounts.cpp --- datovka-4.8.3/src/settings/accounts.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/settings/accounts.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,492 +21,9 @@ * the two. */ -#include "src/common.h" #include "src/settings/accounts.h" -#include "src/settings/preferences.h" -namespace CredNames { - const QString creds(QLatin1String("credentials")); - - const QString acntName(QLatin1String("name")); - const QString userName(QLatin1String("username")); - const QString lMethod(QLatin1String("login_method")); - const QString pwd(QLatin1String("password")); - const QString testAcnt(QLatin1String("test_account")); - const QString rememberPwd(QLatin1String("remember_password")); - const QString dbDir(QLatin1String("database_dir")); - const QString syncWithAll(QLatin1String("sync_with_all")); - const QString p12File(QLatin1String("p12file")); - const QString lstMsgId(QLatin1String("last_message_id")); - const QString lstSaveAtchPath(QLatin1String("last_save_attach_path")); - const QString lstAddAtchPath(QLatin1String("last_add_attach_path")); - const QString lstCorrspPath(QLatin1String("last_export_corresp_path")); - const QString lstZfoPath(QLatin1String("last_export_zfo_path")); -} - -/* The following are not stored into the configuration file. */ -/* Only set on new accounts. */ -#define _CREATED_FROM_SCRATCH "_created_from_cratch" -#define _PKEY_PASSPHRASE "_pkey_passphrase" -#define _OTP_CODE "_otp_code" -#define _PWD_EXPIR_DLG_SHOWN "_pwd_expir_dlg_shown" - -/*! - * @brief Login method names as stored in configuration file. - */ -namespace MethodNames { - static const QString uNamePwd(QLatin1String("username")); - static const QString uNameCrt(QLatin1String("certificate")); - static const QString uNamePwdCrt(QLatin1String("user_certificate")); - static const QString uNamePwdHotp(QLatin1String("hotp")); - static const QString uNamePwdTotp(QLatin1String("totp")); - static const QString uMojeId(QLatin1String("mojeid")); -} - -/*! - * @brief Converts integer to login method identifier. - * - * @param[in] num Integer number. - * @return Identifier value. - */ -static -enum AcntSettings::LogInMethod methodIntToEnum(int num) -{ - switch (num) { - case AcntSettings::LIM_UNAME_PWD: - return AcntSettings::LIM_UNAME_PWD; - break; - case AcntSettings::LIM_UNAME_CRT: - return AcntSettings::LIM_UNAME_CRT; - break; - case AcntSettings::LIM_UNAME_PWD_CRT: - return AcntSettings::LIM_UNAME_PWD_CRT; - break; - case AcntSettings::LIM_UNAME_PWD_HOTP: - return AcntSettings::LIM_UNAME_PWD_HOTP; - break; - case AcntSettings::LIM_UNAME_PWD_TOTP: - return AcntSettings::LIM_UNAME_PWD_TOTP; - break; - case AcntSettings::LIM_MOJE_ID: - return AcntSettings::LIM_MOJE_ID; - break; - case AcntSettings::LIM_UNKNOWN: - default: - return AcntSettings::LIM_UNKNOWN; - break; - } -} - -/*! - * @brief Converts login method string to identifier. - * - * @param[in] str Identifier string as used in configuration file. - * @return Identifier value. - */ -static -enum AcntSettings::LogInMethod methodStrToEnum(const QString &str) -{ - if (str == MethodNames::uNamePwd) { - return AcntSettings::LIM_UNAME_PWD; - } else if (str == MethodNames::uNameCrt) { - return AcntSettings::LIM_UNAME_CRT; - } else if (str == MethodNames::uNamePwdCrt) { - return AcntSettings::LIM_UNAME_PWD_CRT; - } else if (str == MethodNames::uNamePwdHotp) { - return AcntSettings::LIM_UNAME_PWD_HOTP; - } else if (str == MethodNames::uNamePwdTotp) { - return AcntSettings::LIM_UNAME_PWD_TOTP; - } else if (str == MethodNames::uMojeId) { - return AcntSettings::LIM_MOJE_ID; - } else { - return AcntSettings::LIM_UNKNOWN; - } -} - - -/*! - * @brief Converts login method identifier to string. - * - * @param[in] val Identifier value as used in the programme. - * @return Identifier string as used in configuration file. - */ -static -const QString &methodEnumToStr(enum AcntSettings::LogInMethod val) -{ - static const QString nullStr; - - switch (val) { - case AcntSettings::LIM_UNAME_PWD: - return MethodNames::uNamePwd; - break; - case AcntSettings::LIM_UNAME_CRT: - return MethodNames::uNameCrt; - break; - case AcntSettings::LIM_UNAME_PWD_CRT: - return MethodNames::uNamePwdCrt; - break; - case AcntSettings::LIM_UNAME_PWD_HOTP: - return MethodNames::uNamePwdHotp; - break; - case AcntSettings::LIM_UNAME_PWD_TOTP: - return MethodNames::uNamePwdTotp; - break; - case AcntSettings::LIM_MOJE_ID: - return MethodNames::uMojeId; - break; - case AcntSettings::LIM_UNKNOWN: - default: - Q_ASSERT(0); - return nullStr; - break; - } -} - -AcntSettings::AcntSettings(void) - : QMap() -{ -} - -AcntSettings::AcntSettings(const QMap &map) - : QMap(map) -{ -} - -bool AcntSettings::isValid(void) const -{ - return !m_parentType::isEmpty() && - !accountName().isEmpty() && !userName().isEmpty(); -} - -QString AcntSettings::accountName(void) const -{ - return m_parentType::operator[](CredNames::acntName).toString(); -} - -void AcntSettings::setAccountName(const QString &name) -{ - m_parentType::operator[](CredNames::acntName) = name; -} - -QString AcntSettings::userName(void) const -{ - return m_parentType::operator[](CredNames::userName).toString(); -} - -void AcntSettings::setUserName(const QString &userName) -{ - m_parentType::operator[](CredNames::userName) = userName; -} - -enum AcntSettings::LogInMethod AcntSettings::loginMethod(void) const -{ - return methodIntToEnum( - m_parentType::value(CredNames::lMethod, LIM_UNKNOWN).toInt()); -} - -void AcntSettings::setLoginMethod(enum LogInMethod method) -{ - if (method != LIM_UNKNOWN) { - m_parentType::insert(CredNames::lMethod, method); - } else { - m_parentType::remove(CredNames::lMethod); - } -} - -QString AcntSettings::password(void) const -{ - return m_parentType::operator[](CredNames::pwd).toString(); -} - -void AcntSettings::setPassword(const QString &pwd) -{ - m_parentType::operator[](CredNames::pwd) = pwd; -} - -bool AcntSettings::isTestAccount(void) const -{ - return m_parentType::operator[](CredNames::testAcnt).toBool(); -} - -void AcntSettings::setTestAccount(bool isTesting) -{ - m_parentType::operator[](CredNames::testAcnt) = isTesting; -} - -bool AcntSettings::rememberPwd(void) const -{ - return m_parentType::operator[](CredNames::rememberPwd).toBool(); -} - -void AcntSettings::setRememberPwd(bool remember) -{ - m_parentType::operator[](CredNames::rememberPwd) = remember; -} - -QString AcntSettings::dbDir(void) const -{ - return m_parentType::operator[](CredNames::dbDir).toString(); -} - -void AcntSettings::setDbDir(const QString &path) -{ - if (path == globPref.confDir()) { - /* Default path is empty. */ - m_parentType::operator[](CredNames::dbDir) = QString(); - } else { - m_parentType::operator[](CredNames::dbDir) = path; - } -} - -bool AcntSettings::syncWithAll(void) const -{ - return m_parentType::operator[](CredNames::syncWithAll).toBool(); -} - -void AcntSettings::setSyncWithAll(bool sync) -{ - m_parentType::operator[](CredNames::syncWithAll) = sync; -} - -QString AcntSettings::p12File(void) const -{ - return m_parentType::operator[](CredNames::p12File).toString(); -} - -void AcntSettings::setP12File(const QString &p12) -{ - m_parentType::operator[](CredNames::p12File) = p12; -} - -qint64 AcntSettings::lastMsg(void) const -{ - return m_parentType::value(CredNames::lstMsgId, -1).toLongLong(); -} - -void AcntSettings::setLastMsg(qint64 dmId) -{ - m_parentType::insert(CredNames::lstMsgId, dmId); -} - -QString AcntSettings::lastAttachSavePath(void) const -{ - return m_parentType::operator[](CredNames::lstSaveAtchPath).toString(); -} - -void AcntSettings::setLastAttachSavePath(const QString &path) -{ - m_parentType::operator[](CredNames::lstSaveAtchPath) = path; -} - -QString AcntSettings::lastAttachAddPath(void) const -{ - return m_parentType::operator[](CredNames::lstAddAtchPath).toString(); -} - -void AcntSettings::setLastAttachAddPath(const QString &path) -{ - m_parentType::operator[](CredNames::lstAddAtchPath) = path; -} - -QString AcntSettings::lastCorrespPath(void) const -{ - return m_parentType::operator[](CredNames::lstCorrspPath).toString(); -} - -void AcntSettings::setLastCorrespPath(const QString &path) -{ - m_parentType::operator[](CredNames::lstCorrspPath) = path; -} - -QString AcntSettings::lastZFOExportPath(void) const -{ - return m_parentType::operator[](CredNames::lstZfoPath).toString(); -} - -void AcntSettings::setLastZFOExportPath(const QString &path) -{ - m_parentType::operator[](CredNames::lstZfoPath) = path; -} - -bool AcntSettings::_createdFromScratch(void) const -{ - return m_parentType::value(_CREATED_FROM_SCRATCH, false).toBool(); -} - -void AcntSettings::_setCreatedFromScratch(bool fromScratch) -{ - m_parentType::insert(_CREATED_FROM_SCRATCH, fromScratch); -} - -QString AcntSettings::_passphrase(void) const -{ - return m_parentType::value(_PKEY_PASSPHRASE, QString()).toString(); -} - -void AcntSettings::_setPassphrase(const QString &passphrase) -{ - if (!passphrase.isNull()) { - m_parentType::insert(_PKEY_PASSPHRASE, passphrase); - } else { - m_parentType::remove(_PKEY_PASSPHRASE); - } -} - -QString AcntSettings::_otp(void) const -{ - return m_parentType::value(_OTP_CODE, QString()).toString(); -} - -void AcntSettings::_setOtp(const QString &otpCode) -{ - if (!otpCode.isNull()) { - m_parentType::insert(_OTP_CODE, otpCode); - } else { - m_parentType::remove(_OTP_CODE); - } -} - -bool AcntSettings::_pwdExpirDlgShown(void) const -{ - return m_parentType::value(_PWD_EXPIR_DLG_SHOWN, false).toBool(); -} - -void AcntSettings::_setPwdExpirDlgShown(bool pwdExpirDlgShown) -{ - m_parentType::insert(_PWD_EXPIR_DLG_SHOWN, pwdExpirDlgShown); -} - -void AcntSettings::loadFromSettings(const QSettings &settings, - const QString &group) -{ - QString prefix; - if (!group.isEmpty()) { - prefix = group + "/"; - } - - /* - * String containing comma character are loaded as a string list. - * - * FIXME -- Any white-space characters trailing the comma are lost. - */ - setAccountName(settings.value(prefix + CredNames::acntName, - "").toStringList().join(", ")); - setUserName(settings.value(prefix + CredNames::userName, - "").toString()); - setLoginMethod(methodStrToEnum( - settings.value(prefix + CredNames::lMethod, "").toString())); - setPassword(fromBase64(settings.value(prefix + CredNames::pwd, - "").toString())); - setTestAccount(settings.value(prefix + CredNames::testAcnt, - "").toBool()); - setRememberPwd(settings.value(prefix + CredNames::rememberPwd, - "").toBool()); - setDbDir(settings.value(prefix + CredNames::dbDir, - "").toString()); - setSyncWithAll(settings.value(prefix + CredNames::syncWithAll, - "").toBool()); - setP12File(settings.value(prefix + CredNames::p12File, - "").toString()); - setLastMsg(settings.value(prefix + CredNames::lstMsgId, - "").toLongLong()); - setLastAttachSavePath(settings.value(prefix + CredNames::lstSaveAtchPath, - "").toString()); - setLastAttachAddPath(settings.value(prefix + CredNames::lstAddAtchPath, - "").toString()); - setLastCorrespPath(settings.value(prefix + CredNames::lstCorrspPath, - "").toString()); - setLastZFOExportPath(settings.value(prefix + CredNames::lstZfoPath, - "").toString()); -} - -void AcntSettings::saveToSettings(QSettings &settings, - const QString &group) const -{ - if (!group.isEmpty()) { - settings.beginGroup(group); - } - - settings.setValue(CredNames::acntName, accountName()); - settings.setValue(CredNames::userName, userName()); - settings.setValue(CredNames::lMethod, methodEnumToStr(loginMethod())); - settings.setValue(CredNames::testAcnt, isTestAccount()); - settings.setValue(CredNames::rememberPwd, rememberPwd()); - if (rememberPwd()) { - if (!password().isEmpty()) { - settings.setValue(CredNames::pwd, toBase64(password())); - } - } - - if (!dbDir().isEmpty()) { - if (dbDir() != globPref.confDir()) { - settings.setValue(CredNames::dbDir, dbDir()); - } - } - if (!p12File().isEmpty()) { - settings.setValue(CredNames::p12File, p12File()); - } - - settings.setValue(CredNames::syncWithAll, syncWithAll()); - - if (0 <= lastMsg()) { - settings.setValue(CredNames::lstMsgId, lastMsg()); - } - - /* Save last attachments save path. */ - if (!lastAttachSavePath().isEmpty()) { - settings.setValue(CredNames::lstSaveAtchPath, - lastAttachSavePath()); - } - - /* Save last attachments add path. */ - if (!lastAttachAddPath().isEmpty()) { - settings.setValue(CredNames::lstAddAtchPath, - lastAttachAddPath()); - } - - /* Save last correspondence export path. */ - if (!lastCorrespPath().isEmpty()) { - settings.setValue(CredNames::lstCorrspPath, lastCorrespPath()); - } - - /* save last ZFO export path */ - if (!lastZFOExportPath().isEmpty()) { - settings.setValue(CredNames::lstZfoPath, lastZFOExportPath()); - } - - if (!group.isEmpty()) { - settings.endGroup(); - } -} - -bool AcntSettings::credentialsLessThan(const QString &s1, const QString &s2) -{ - QRegExp trailingNumRe("(.*[^0-9]+)*([0-9]+)"); - QString a1, a2; - int n1, n2; - int pos; - - pos = trailingNumRe.indexIn(s1); - if (pos > -1) { - a1 = trailingNumRe.cap(1); - n1 = trailingNumRe.cap(2).toInt(); - } else { - a1 = s1; - n1 = -1; - } - - pos = trailingNumRe.indexIn(s2); - if (pos > -1) { - a2 = trailingNumRe.cap(1); - n2 = trailingNumRe.cap(2).toInt(); - } else { - a2 = s2; - n2 = -1; - } - - return (a1 != a2) ? (a1 < a2) : (n1 < n2); -} +AccountsMap globAccounts; void AccountsMap::loadFromSettings(const QSettings &settings) { diff -Nru datovka-4.8.3/src/settings/accounts.h datovka-4.9.3/src/settings/accounts.h --- datovka-4.8.3/src/settings/accounts.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/settings/accounts.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,132 +28,8 @@ #include #include #include -#include -/*! - * @brief Defines labels used in credentials. - */ -namespace CredNames { - extern const QString creds; - - extern const QString acntName; - extern const QString userName; - extern const QString lMethod; - extern const QString pwd; - extern const QString testAcnt; - extern const QString rememberPwd; - extern const QString dbDir; - extern const QString syncWithAll; - extern const QString p12File; - extern const QString lstMsgId; - extern const QString lstSaveAtchPath; - extern const QString lstAddAtchPath; - extern const QString lstCorrspPath; - extern const QString lstZfoPath; -} - -/*! - * @brief Holds account settings. - */ -class AcntSettings : public QMap { -public: - /*! - * @brief Login method identifier. - */ - enum LogInMethod { - LIM_UNKNOWN, /*!< Unknown method. */ - LIM_UNAME_PWD, /*!< User name and password. */ - LIM_UNAME_CRT, /*!< User name and certificate. */ - LIM_UNAME_PWD_CRT, /*!< User name, password and certificate. */ - LIM_UNAME_PWD_HOTP, /*!< User name, password and HOTP. */ - LIM_UNAME_PWD_TOTP, /*!< User name, password and TOTP (SMS). */ - LIM_MOJE_ID /*!< MOJEID. */ - }; - - /*! - * @brief Constructor. - */ - AcntSettings(void); - AcntSettings(const QMap &map); - - bool isValid(void) const; - QString accountName(void) const; - void setAccountName(const QString &name); - QString userName(void) const; - void setUserName(const QString &userName); - enum LogInMethod loginMethod(void) const; - void setLoginMethod(enum LogInMethod method); - QString password(void) const; - void setPassword(const QString &pwd); - bool isTestAccount(void) const; - void setTestAccount(bool isTesting); - bool rememberPwd(void) const; - void setRememberPwd(bool remember); - QString dbDir(void) const; - void setDbDir(const QString &path); - bool syncWithAll(void) const; - void setSyncWithAll(bool sync); - QString p12File(void) const; - void setP12File(const QString &p12); - qint64 lastMsg(void) const; - void setLastMsg(qint64 dmId); - QString lastAttachSavePath(void) const; - void setLastAttachSavePath(const QString &path); - QString lastAttachAddPath(void) const; - void setLastAttachAddPath(const QString &path); - QString lastCorrespPath(void) const; - void setLastCorrespPath(const QString &path); - QString lastZFOExportPath(void) const; - void setLastZFOExportPath(const QString &path); - - bool _createdFromScratch(void) const; - void _setCreatedFromScratch(bool fromScratch); - QString _passphrase(void) const; - void _setPassphrase(const QString &passphrase); - QString _otp(void) const; - void _setOtp(const QString &otpCode); - bool _pwdExpirDlgShown(void) const; - void _setPwdExpirDlgShown(bool pwdExpirDlgShown); - - /*! - * @brief Load content from settings group. - * - * @note Content is not erased before new settings is loaded. - * - * @param[in] settings Settings structure to load data from. - * @param[in] group Name of group to work with. - */ - void loadFromSettings(const QSettings &settings, const QString &group); - - /*! - * @brief Save content to settings. - * - * @param[out] settings Settings structure to write/append data into. - * @param[in] group Name of group to write to, group is create only - * when non-empty string supplied. - */ - void saveToSettings(QSettings &settings, const QString &group) const; - - /*! - * @brief Used for sorting credentials. - * - * @param[in] s1 credentials[0-9]* - * @param[in] s2 credentials[0-9]* - * @return True if s1 comes before s2. - * - * @note The number is taken by its value rather like a string of characters. - * cred < cred1 < cred2 < ... < cred10 < ... < cred100 < ... - */ - static - bool credentialsLessThan(const QString &s1, const QString &s2); - -private: - /* Prohibit these methods in public interface. */ - QVariant operator[](const QString &key); - const QVariant operator[](const QString &key) const; - - typedef QMap m_parentType; -}; +#include "src/settings/account.h" /* Meta object features are not supported for nested classes. */ @@ -161,7 +37,7 @@ * @brief Associative array mapping user name to settings. */ class AccountsMap : public QObject, public QMap { - Q_OBJECT + Q_OBJECT public: /*! @@ -180,4 +56,11 @@ void accountDataChanged(const QString &userName); }; +/*! + * @brief Holds account data related to account. + * + * @note Key is userName. The user name is held by the user name list. + */ +extern AccountsMap globAccounts; + #endif /* _ACCOUNTS_H_ */ diff -Nru datovka-4.8.3/src/settings/preferences.cpp datovka-4.9.3/src/settings/preferences.cpp --- datovka-4.8.3/src/settings/preferences.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/settings/preferences.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,7 +40,7 @@ /*! Account database file name. */ #define ACCOUNT_DB_FILE "messages.shelf.db" #define TAG_DB_FILE "tag.db" -#define TAG_WEBDATOVKA_DB_FILE "mojeid-tag.db" +#define RECORDS_MANAGEMENT_DB_FILE "records_management.db" GlobPreferences::GlobPreferences(void) : confSubdir(DFLT_CONF_SUBDIR), @@ -48,7 +48,7 @@ saveToConf(DFLT_CONF_FILE), accountDbFile(ACCOUNT_DB_FILE), tagDbFile(TAG_DB_FILE), - tagWebDatovkaDbFile(TAG_WEBDATOVKA_DB_FILE), + recordsManagementDbFile(RECORDS_MANAGEMENT_DB_FILE), auto_download_whole_messages(false), default_download_signed(true), //store_passwords_on_disk(false), @@ -91,6 +91,24 @@ { } +bool GlobPreferences::ensureConfPresence(void) +{ + if (!QDir(globPref.confDir()).exists()) { + if (!QDir(globPref.confDir()).mkpath(".")) { + return false; + } + } + if (!QFile(globPref.loadConfPath()).exists()) { + QFile file(globPref.loadConfPath()); + if (!file.open(QIODevice::ReadWrite)) { + return false; + } + file.close(); + } + + return true; +} + void GlobPreferences::loadFromSettings(const QSettings &settings) { int value; @@ -454,7 +472,7 @@ return confDir() + QDir::separator() + tagDbFile; } -QString GlobPreferences::tagWebDatovkaDbPath(void) const +QString GlobPreferences::recordsManagementDbPath(void) const { - return confDir() + QDir::separator() + tagWebDatovkaDbFile; + return confDir() + QDir::separator() + recordsManagementDbFile; } diff -Nru datovka-4.8.3/src/settings/preferences.h datovka-4.9.3/src/settings/preferences.h --- datovka-4.8.3/src/settings/preferences.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/settings/preferences.h 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,12 +58,18 @@ */ ~GlobPreferences(void); + /*! + * @brief Create configuration file if not present. + */ + static + bool ensureConfPresence(void); + QString confSubdir; /*!< Configuration directory. */ QString loadFromConf; /*!< Configuration file to load from. */ QString saveToConf; /*!< Configuration file to save to. */ const QString accountDbFile; /*!< Account db file. */ const QString tagDbFile; /*!< Tag db file. */ - const QString tagWebDatovkaDbFile; /*!< Tag webdatovka db file. */ + const QString recordsManagementDbFile; /*!< Records management db file. */ bool auto_download_whole_messages; bool default_download_signed; /*!< Default downloading method. */ //bool store_passwords_on_disk; @@ -146,11 +152,11 @@ QString tagDbPath(void) const; /*! - * @brief Returns whole webdatovka tag db path. + * @brief Returns whole records management db path. * - * @return Whole path to webdatovka tag database file. + * @return Whole path to records management database file. */ - QString tagWebDatovkaDbPath(void) const; + QString recordsManagementDbPath(void) const; }; /*! diff -Nru datovka-4.8.3/src/settings/records_management.cpp datovka-4.9.3/src/settings/records_management.cpp --- datovka-4.8.3/src/settings/records_management.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/settings/records_management.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/settings/records_management.h" + +#define RM_GROUP QLatin1String("records_management") +#define RM_URL QLatin1String("location_url") +#define RM_TOKEN QLatin1String("access_token") + +RecordsManagementSettings globRecordsManagementSet; + +RecordsManagementSettings::RecordsManagementSettings(void) + : url(), + token() +{ +} + +void RecordsManagementSettings::loadFromSettings(const QSettings &settings) +{ + url = settings.value(RM_GROUP + QLatin1String("/") + RM_URL, + QString()).toString(); + token = QByteArray::fromBase64( + settings.value(RM_GROUP + QLatin1String("/") + RM_TOKEN, + QByteArray()).toString().toUtf8()); + + if (url.isEmpty() || token.isEmpty()) { + url.clear(); + token.clear(); + } +} + +void RecordsManagementSettings::saveToSettings(QSettings &settings) const +{ + if (!url.isEmpty() && !token.isEmpty()) { + settings.beginGroup(RM_GROUP); + + settings.setValue(RM_URL, url); + settings.setValue(RM_TOKEN, QString(token.toUtf8().toBase64())); + + settings.endGroup(); + } +} + +bool RecordsManagementSettings::isSet(void) const +{ + return !url.isEmpty() && !token.isEmpty(); +} diff -Nru datovka-4.8.3/src/settings/records_management.h datovka-4.9.3/src/settings/records_management.h --- datovka-4.8.3/src/settings/records_management.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/settings/records_management.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _RECORDS_MANAGEMENT_H_ +#define _RECORDS_MANAGEMENT_H_ + +#include +#include + +/* + * @brief Encapsulates records management service settings. + */ +class RecordsManagementSettings { +public: + /*! + * @brief Constructor. + */ + RecordsManagementSettings(void); + + /*! + * @brief Load data from supplied settings. + * + * @param[in] settings Settings structure. + */ + void loadFromSettings(const QSettings &settings); + + /*! + * @brief Store data to settings structure. + * + * @param[out] settings Settings structure. + */ + void saveToSettings(QSettings &settings) const; + + /*! + * @brief Test whether records management service is set. + * + * @return True is URL and token are set. + */ + bool isSet(void) const; + + QString url; /*!< Service URL. */ + QString token; /*!< Service access token. */ +}; + +/*! + * @brief Global instance of the structure. + */ +extern RecordsManagementSettings globRecordsManagementSet; + +#endif /* _RECORDS_MANAGEMENT_H_ */ diff -Nru datovka-4.8.3/src/web/json.cpp datovka-4.9.3/src/web/json.cpp --- datovka-4.8.3/src/web/json.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/web/json.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,1321 +0,0 @@ -/* - * Copyright (C) 2014-2016 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/common.h" -#include "src/web/json.h" -#include "src/web/net.h" -#include "src/io/wd_sessions.h" -#include "src/gui/dlg_login_mojeid.h" - -JsonLayer jsonlayer; - -JsonLayer::JsonLayer(QObject *parent) - : QObject(parent) -{ -} - -JsonLayer::~JsonLayer(void) -{ -} - -QNetworkCookie JsonLayer::fakeLoginWebDatovka(void) -{ - QUrl url(QString(WEBDATOVKA_SERVICE_URL) + "desktoplogin"); - QByteArray reply; - QNetworkCookie sessionid; - netmanager.createGetRequestWebDatovka(url, sessionid, reply); - - for (int i = 0; i < cookieList.size(); ++i) { - if (cookieList.at(i).name() == COOKIE_SESSION_ID) { - sessionid = cookieList.at(i); - } - } - - return sessionid; -} - - -bool JsonLayer::startLoginToWebDatovka(QUrl &lastUrl) -{ - QByteArray reply; - QNetworkCookie sessionid; - QByteArray postData; - - // STEP 1: call webdatovka for start login procedure (GET). - // We should obtain url for redirect - // and openconnect parameter list (postdata). - QUrl url(QString(WEBDATOVKA_SERVICE_URL) + "desktoplogin"); - netmanager.createPostRequestWebDatovka(url, sessionid, postData, reply); - lastUrl = url; - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - url.setUrl(jsonObject["url"].toString()); - if (!url.isValid()) { - return false; - } - - // Create formdata string from json - QJsonObject postdata = jsonObject["postdata"].toObject(); - QVariantMap map = postdata.toVariantMap(); - QVariantMap::iterator i; - for (i = map.begin(); i != map.end(); ++i) { - postData.append(i.key()).append("=").append(i.value().toString()).append("&"); - } - - // STEP 2: Call mojeID for starting of login procedure (POST). - // We send openconnect parameter list as postdata. - netmanager.createPostRequestMojeId(url, lastUrl, postData, reply); - lastUrl = url; - - return true; -} - - -bool JsonLayer::loginMethodChanged(int method, QString &lastUrl, QString &token) -{ - QByteArray reply; - QUrl url; - if (method == USER_NAME) { - url.setUrl(MOJEID_URL_PASSWORD); - } else if (method == CERTIFICATE) { - url.setUrl(MOJEID_URL_CERTIFICATE); - } else { - url.setUrl(MOJEID_URL_OTP); - } - - // STEP 3: Call to mojeID on new login endpoint (GET). - // We should obtain html page. From page we must get token. - netmanager.createGetRequestMojeId(url, QUrl(lastUrl), reply); - lastUrl = url.toString(); - - QString html(reply); - QRegularExpression exp("captured(1); - } - - return true; -} - -bool JsonLayer::loginToMojeID(const QString &lastUrl, - const QString &token, const QString &username, - const QString &pwd, const QString &otp, const QString &certPath, - QString &errStr, QNetworkCookie &sessionid) -{ - QByteArray reply; - QUrl lUrl(lastUrl); - QUrl url; - - errStr = tr("Login to mojeID failed. You must choose correct " - "login method and enter correct login data. Try again."); - - // STEP 4: Send credential to mojeID endpoint (POST). - // We send login data, csrfmiddlewaretoken - // and mojeid token as content. OTP or certificate data optionaly. - url.setUrl(MOJEID_URL_CERTIFICATE); - - QString str = "csrfmiddlewaretoken="; - for (int i = 0; i < cookieList.size(); ++i) { - if (cookieList.at(i).name() == COOKIE_CSRFTOKEN) { - str += cookieList.at(i).value(); - } - } - str += "&token=" + token; - str += "&username=" + username; - if (!pwd.isEmpty()) { - url.setUrl(MOJEID_URL_PASSWORD); - str += "&password=" + pwd; - } - if (!otp.isEmpty()) { - url.setUrl(MOJEID_URL_OTP); - str += "&otp_token=" + otp; - } - str += "&allow=prihlasit+se"; - QByteArray data; - data.append(str); - netmanager.createPostRequestMojeId(url, lUrl, data, reply); - lUrl = url; - - if (lUrl.toString() == MOJEID_URL_CERTIFICATE) { - - url.setUrl(MOJEID_URL_SSLLOGIN); - - QFile certFile(certPath); - if (!certFile.open(QIODevice::ReadOnly)) { - errStr = tr("Cannot open client certificate from path '%1'").arg(certPath); - return false; - } - - bool ok; - const QString passPhrase = QInputDialog::getText(0, - tr("Certificate password"), - tr("Enter certificate password:"), - QLineEdit::Password, NULL, &ok); - - QFileInfo finfo(certFile); - QString ext = finfo.suffix().toLower(); - if (ext == "pem") { - QByteArray certData = certFile.readAll(); - QSslCertificate cert(certData, QSsl::Pem); - QSslKey key(certData, QSsl::Rsa, QSsl::Pem, - QSsl::PrivateKey, passPhrase.toUtf8()); - netmanager.createPostRequestMojeIdCert(url, lUrl, - data, cert, key, reply); - } -#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)) - else if (ext == "p12" || ext == "pfx") { - // is PKCS12 format - QSslCertificate cert; - QSslKey key; - QList importedCerts; - if (QSslCertificate::importPkcs12(&certFile, &key, - &cert, &importedCerts, passPhrase.toUtf8())) { - netmanager.createPostRequestMojeIdCert(url, - lUrl, data, cert, key, reply); - } else { - errStr = tr("Cannot parse client certificate from path '%1'").arg(certPath); - return false; - } - } -#else /* < Qt-5.4 */ -#warning "Compiling against version < Qt-5.4 which does not have QSslCertificate::importPkcs12()." -#endif /* >= Qt-5.4 */ - lUrl = url; - } - - // STEP 5: send confiramtion to mojeID endpoint (POST). - // We send new csrfmiddlewaretoken - // and mojeid token and other values as content. - url.setUrl(MOJEID_URL_CONFIRM); - str = "csrfmiddlewaretoken="; - for (int i = 0; i < cookieList.size(); ++i) { - if (cookieList.at(i).name() == COOKIE_CSRFTOKEN) { - str += cookieList.at(i).value(); - } - } - str += "&token=" + token; - str += "&username=" + username; - str += "&first_name=first_name"; - str += "&last_name=last_name"; - str += "&email_default=email_default"; - str += "&allow=OK"; - data.clear(); - data.append(str); - netmanager.createPostRequestMojeId(url, lUrl, data, reply); - lUrl = url; - - /* TODO - repeat login proccess if confirmation failed */ - - for (int i = 0; i < cookieList.size(); ++i) { - if (cookieList.at(i).name() == COOKIE_SESSION_ID) { - sessionid = cookieList.at(i); - } - } - - // STEP 6: redirect mojeID responce to webdatovka (GET). - // We send mojeid parametrs in get url. - url.setUrl(netmanager.newUrl); - netmanager.createGetRequestWebDatovka(url, sessionid, reply); - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - if (!jsonObject["errmsg"].toString().isEmpty()) { - errStr = jsonObject["errmsg"].toString(); - } - } else { - if (!jsonObject["warning"].toString().isEmpty()) { - errStr = jsonObject["warning"].toString(); - } - // Now, you are logged to webdatovka and you have sessionid cookie. - // Next requests/operations only via new sessionid. - for (int i = 0; i < cookieList.size(); ++i) { - if (cookieList.at(i).name() == COOKIE_SESSION_ID) { - sessionid = cookieList.at(i); - } - } - return true; - } - - return false; -} - - -bool JsonLayer::isLoggedToWebDatovka(const QString &userName, - QNetworkCookie &sessionid) -{ - sessionid = wdSessions.sessionCookie(userName); - if (sessionid.value().isEmpty()) { - return false; - } - - return true; -} - - -bool JsonLayer::updateSessionId(const QString &userName) -{ - QNetworkCookie sessionid; - - for (int i = 0; i < cookieList.size(); ++i) { - if (cookieList.at(i).name() == COOKIE_SESSION_ID) { - sessionid = cookieList.at(i); - } - } - - return wdSessions.setSessionCookie(userName, sessionid); -} - - -bool JsonLayer::pingServer(const QString &userName, QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - netmanager.createGetRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "ping"), sessionid, reply); - - updateSessionId(userName); - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - - -bool JsonLayer::createAccount(const QString &userName,const QString &name, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["name"] = name; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "newaccount"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - /* TODO - parse new account data and store to db - * Here is not API implemented yet. - */ - - return true; -} - - -bool JsonLayer::renameAccount(const QString &userName, int accountID, - const QString &newName, QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["account"] = accountID; - rootObj["name"] = newName; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "renameaccount"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - - -bool JsonLayer::deleteAccount(const QString &userName, int accountID, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["account"] = accountID; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "deleteaccount"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - - -bool JsonLayer::getAccountList(const QNetworkCookie &sessionid, int &userId, - QList &accountList, QString &errStr) -{ - QByteArray reply; - - netmanager.createGetRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "accountlist"), sessionid, - reply); - - if (reply.isEmpty()) { - return false; - } - - return parseAccountList(reply, userId, accountList, errStr); -} - - -bool JsonLayer::getMessageList(const QString &userName, int accountID, - int messageType, int limit, int offset, - QList &messageList, QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["account"] = accountID; - rootObj["folder"] = messageType; - rootObj["offset"] = offset; - rootObj["limit"] = limit; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "msgenvelopelist"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - return parseMessageList(reply, messageList, errStr); -} - - -bool JsonLayer::syncAccount(const QString &userName, int accountID, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["account"] = accountID; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "synchronize"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - - -QByteArray JsonLayer::downloadMessage(const QString &userName, int msgId, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return QByteArray(); - } - - netmanager.createGetRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "downloadsigned/" - + QString::number(msgId)), sessionid, reply); - - updateSessionId(userName); - - return reply; -} - - -QByteArray JsonLayer::downloadFile(const QString &userName, int fileId, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return QByteArray(); - } - - netmanager.createGetRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "downloadfile/" - + QString::number(fileId)), sessionid, reply); - - updateSessionId(userName); - - return reply; -} - - -bool JsonLayer::getTagList(const QString &userName, - QList &tagList, QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "listtags"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - return parseTagList(reply, tagList, errStr); -} - - -int JsonLayer::createTag(const QString &userName, const QString &name, - const QString &color, QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["name"] = name; - rootObj["color"] = color; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "newtag"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return -1; - } - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return -1; - } - return jsonObject["id"].toInt(); -} - - -bool JsonLayer::updateTag(const QString &userName, int tagId, const QString &name, - const QString &color, QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["id"] = tagId; - rootObj["name"] = name; - rootObj["color"] = color; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "edittag"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - - -bool JsonLayer::deleteTag(const QString &userName, int tagId, QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["id"] = tagId; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "deletetag"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - - -bool JsonLayer::assignTag(const QString &userName, int tagId, int msgId, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["id"] = tagId; - rootObj["msgid"] = msgId; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "tagmsg/add"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - - -bool JsonLayer::removeTag(const QString &userName, int tagId, int msgId, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["id"] = tagId; - rootObj["msgid"] = msgId; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "tagmsg/remove"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - - -bool JsonLayer::removeAllTags(const QString &userName, int msgId, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["msgid"] = msgId; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "tagmsg/removeall"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - - -bool JsonLayer::searchRecipient(const QString &userName, int accountID, - const QString &word, int position, - QList &resultList, bool &hasMore, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - rootObj["account"] = accountID; - rootObj["needle"] = word; - rootObj["position"] = position; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "searchrecipient"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - return parseSearchRecipient(reply, resultList, hasMore, errStr); -} - - -bool JsonLayer::sendMessage(const QString &userName, int accountID, - const QList &recipientList, - const JsonLayer::Envelope &envelope, - const QList &fileList, - QStringList &resultList, QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonArray recipienList; - foreach (const JsonLayer::Recipient &recipient, recipientList) { - QJsonObject recData; - recData["db_id_recipient"] = recipient.recipientDbId; - recData["name"] = recipient.recipientName; - recData["address"] = recipient.recipientAddress; - recData["dm_to_hands"] = recipient.toHands; - recipienList.append(recData); - } - - QJsonObject msgEnvelope; - msgEnvelope["dm_annotation"] = envelope.dmAnnotation; - if (!envelope.dmRecipientIdent.isEmpty()) { - msgEnvelope["dm_recipient_ident"] = envelope.dmRecipientIdent; - } - if (!envelope.dmRecipientRefNumber.isEmpty()) { - msgEnvelope["dm_recipient_ref_number"] = - envelope.dmRecipientRefNumber; - } - if (!envelope.dmRecipientRefNumber.isEmpty()) { - msgEnvelope["dm_sender_ident"] = envelope.dmSenderIdent; - } - if (!envelope.dmRecipientRefNumber.isEmpty()) { - msgEnvelope["dm_sender_ref_number"] = envelope.dmSenderRefNumber; - } - if (!envelope.dmRecipientRefNumber.isEmpty()) { - msgEnvelope["dm_legal_title_law"] = envelope.dmLegalTitleLaw; - } - if (!envelope.dmRecipientRefNumber.isEmpty()) { - msgEnvelope["dm_legal_title_par"] = envelope.dmLegalTitlePar; - } - if (!envelope.dmRecipientRefNumber.isEmpty()) { - msgEnvelope["dm_legal_title_point"] = envelope.dmLegalTitlePoint; - } - if (!envelope.dmRecipientRefNumber.isEmpty()) { - msgEnvelope["dm_legal_title_sect"] = envelope.dmLegalTitleSect; - } - if (!envelope.dmRecipientRefNumber.isEmpty()) { - msgEnvelope["dm_legal_title_year"] = envelope.dmLegalTitleYear; - } - msgEnvelope["dm_personal_delivery"] = envelope.dmPersonalDelivery; - msgEnvelope["dm_allow_subst_delivery"] = envelope.dmAllowSubstDelivery; - msgEnvelope["dm_publish_own_id"] = envelope.dmPublishOwnID; - msgEnvelope["dm_ovm"] = envelope.dmOVM; - msgEnvelope["account"] = accountID; - msgEnvelope["rcpt"] = recipienList; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "saveenvelope"), sessionid, - QJsonDocument(msgEnvelope).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - int draftId = jsonObject["draft_id"].toInt(); - - /* TODO - check returned bool */ - foreach (const JsonLayer::File &file, fileList) { - netmanager.createPostRequestWebDatovkaSendFile( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "uploadonefile"), - sessionid, draftId, file.fName, - QByteArray::fromBase64(file.fContent), reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - jsonResponse = QJsonDocument::fromJson(reply); - jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - } - - QJsonObject rootObj; - rootObj["draft_id"] = draftId; - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "senddraft"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - jsonResponse = QJsonDocument::fromJson(reply); - jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - QString result; - QJsonArray errorArray = jsonObject["errors"].toArray(); - foreach (const QJsonValue &value, errorArray) { - QJsonObject obj = value.toObject(); - result = obj["dbID"].toString() + "§" + obj["msg"].toString(); - resultList.append(result); - } - - return true; -} - - -bool JsonLayer::deleteMessage(const QString &userName, int msgId, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - QJsonArray array; - array.append(msgId); - rootObj["msg_id"] = array; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "deletemessage"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - - -bool JsonLayer::markMessageAsRead(const QString &userName, int msgId, - QString &errStr) -{ - QByteArray reply; - QNetworkCookie sessionid; - - if (!isLoggedToWebDatovka(userName, sessionid)) { - errStr = tr("User is not logged to mojeID"); - return false; - } - - QJsonObject rootObj; - QJsonArray array; - array.append(msgId); - rootObj["msg_id"] = array; - - netmanager.createPostRequestWebDatovka( - QUrl(QString(WEBDATOVKA_SERVICE_URL) + "markasread"), sessionid, - QJsonDocument(rootObj).toJson(QJsonDocument::Compact), - reply); - - updateSessionId(userName); - - if (reply.isEmpty()) { - errStr = tr("Reply content missing"); - return false; - } - - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - return true; -} - -bool JsonLayer::parseAccountList(const QByteArray &content, int &userId, - QList &accountList, QString &errStr) -{ - QJsonDocument jsonResponse = QJsonDocument::fromJson(content); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - userId = jsonObject["userId"].toInt(); - QJsonArray jsonArray = jsonObject["accountsList"].toArray(); - - foreach (const QJsonValue &value, jsonArray) { - QJsonObject obj = value.toObject(); - JsonLayer::AccountData aData; - aData.userId = userId; - aData.accountId = obj["id"].toInt(); - aData.name = obj["name"].toString(); - QJsonObject owner = obj["owner"].toObject(); - QJsonObject user = obj["user"].toObject(); - - aData.ownerInfo.key = obj["id"].toString(); - aData.ownerInfo.dbID = owner["db_id"].toString(); - aData.ownerInfo.dbType = owner["db_type"].toString(); - aData.ownerInfo.ic = owner["ic_db"].toString().isEmpty() ? - NULL : owner["ic_db"].toString(); - aData.ownerInfo.pnFirstName = - owner["pn_first_name"].toString().isEmpty() ? - NULL : owner["pn_first_name"].toString(); - aData.ownerInfo.pnMiddleName = - owner["pn_middle_name"].toString().isEmpty() ? - NULL : owner["pn_middle_name"].toString(); - aData.ownerInfo.pnLastName = - owner["pn_last_name"].toString().isEmpty() ? - NULL : owner["pn_last_name"].toString(); - aData.ownerInfo.pnLastNameAtBirth = - owner["pn_last_name_at_birth"].toString().isEmpty() ? - NULL : owner["pn_last_name_at_birth"].toString(); - aData.ownerInfo.firmName = - owner["firm_name"].toString().isEmpty() ? - NULL : owner["firm_name"].toString(); - aData.ownerInfo.biDate = - owner["bi_date"].toString().isEmpty() ? - NULL : owner["bi_date"].toString(); - aData.ownerInfo.biCity = - owner["bi_city"].toString().isEmpty() ? - NULL : owner["bi_city"].toString(); - aData.ownerInfo.biCounty = - owner["bi_county"].toString().isEmpty() ? - NULL : owner["bi_county"].toString(); - aData.ownerInfo.biState = - owner["bi_state"].toString().isEmpty() ? - NULL : owner["bi_state"].toString(); - aData.ownerInfo.adCity = - owner["ad_city"].toString().isEmpty() ? - NULL : owner["ad_city"].toString(); - aData.ownerInfo.adStreet = - owner["ad_street"].toString().isEmpty() ? - NULL : owner["ad_street"].toString(); - aData.ownerInfo.adNumberInStreet = - owner["ad_number_in_street"].toString().isEmpty() ? - NULL : owner["ad_number_in_street"].toString(); - aData.ownerInfo.adNumberInMunicipality = - owner["ad_number_in_municipality"].toString().isEmpty() ? - NULL : owner["ad_number_in_municipality"].toString(); - aData.ownerInfo.adZipCode = - owner["ad_zip_code"].toString().isEmpty() ? - NULL : owner["ad_zip_code"].toString(); - aData.ownerInfo.adState = - owner["ad_state"].toString().isEmpty() ? - NULL : owner["ad_state"].toString(); - aData.ownerInfo.nationality = - owner["nationality"].toString().isEmpty() ? - NULL : owner["nationality"].toString(); - aData.ownerInfo.identifier = - owner["identifier"].toString().isEmpty() ? - NULL : owner["identifier"].toString(); - aData.ownerInfo.registryCode = - owner["registry_code"].toString().isEmpty() ? - NULL : owner["registry_code"].toString(); - aData.ownerInfo.dbState = owner["db_state"].toInt(); - aData.ownerInfo.dbEffectiveOVM = - owner["db_effective_ovm"].toBool(); - aData.ownerInfo.dbOpenAddressing = - owner["db_open_addressing"].toBool(); - - aData.userInfo.key = obj["user_id"].toString(); - aData.userInfo.pnFirstName = - user["pn_first_name"].toString().isEmpty() ? - NULL : user["pn_first_name"].toString(); - aData.userInfo.pnMiddleName = - user["pn_middle_name"].toString().isEmpty() ? - NULL : user["pn_middle_name"].toString(); - aData.userInfo.pnLastName = - user["pn_last_name"].toString().isEmpty() ? - NULL : user["pn_last_name"].toString(); - aData.userInfo.pnLastNameAtBirth = - user["pn_last_name_at_birth"].toString().isEmpty() ? - NULL : user["pn_last_name_at_birth"].toString(); - aData.userInfo.adCity = user["ad_city"].toString().isEmpty() ? - NULL : user["ad_city"].toString(); - aData.userInfo.adStreet = - user["ad_street"].toString().isEmpty() ? - NULL : user["ad_street"].toString(); - aData.userInfo.adNumberInStreet = - user["ad_number_in_street"].toString().isEmpty() ? - NULL : user["ad_number_in_street"].toString(); - aData.userInfo.adNumberInMunicipality = - user["ad_number_in_municipality"].toString().isEmpty() ? - NULL : user["ad_number_in_municipality"].toString(); - aData.userInfo.adZipCode = - user["ad_zip_code"].toString().isEmpty() ? - NULL : user["ad_zip_code"].toString(); - aData.userInfo.adState = - user["ad_state"].toString().isEmpty() ? - NULL : user["ad_state"].toString(); - aData.userInfo.biDate = user["bi_date"].toString().isEmpty() ? - NULL : user["bi_date"].toString(); - aData.userInfo.userType = - user["user_type"].toString().isEmpty() ? - NULL : user["user_type"].toString(); - aData.userInfo.userPrivils = user["user_privils"].toInt(); - aData.userInfo.ic = user["ic_db"].toInt(); - aData.userInfo.firmName = - user["firm_name"].toString().isEmpty() ? - NULL : user["firm_name"].toString(); - aData.userInfo.caStreet = - user["ca_street"].toString().isEmpty() ? - NULL : user["ca_street"].toString(); - aData.userInfo.caCity = user["ca_city"].toString().isEmpty() ? - NULL : user["ca_city"].toString(); - aData.userInfo.caZipCode = - user["ca_zip_code"].toString().isEmpty() ? - NULL : user["ca_zip_code"].toString(); - aData.userInfo.caState = - user["ca_state"].toString().isEmpty() ? - NULL : user["ca_state"].toString(); - - accountList.append(aData); - } - - return true; -} - - -bool JsonLayer::parseMessageList(const QByteArray &content, - QList &messageList, QString &errStr) -{ - QJsonDocument jsonResponse = QJsonDocument::fromJson(content); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - QJsonArray messageArray = jsonObject["messages"].toArray(); - - foreach (const QJsonValue &value, messageArray) { - QJsonObject obj = value.toObject(); - Envelope mEvnelope; - mEvnelope._tagList.clear(); - mEvnelope._read = obj["read"].toBool(); - - QJsonObject envel = obj["envelope"].toObject(); - mEvnelope.id = envel["id"].toInt(); - mEvnelope.dmID = envel["dm_id"].toString().toLongLong(); - mEvnelope.dbIDRecipient = envel["db_id_recipient"].toString(); - mEvnelope.dbIDSender = envel["db_id_sender"].toString(); - mEvnelope.dmAcceptanceTime = envel["dm_acceptance_time"].toString(); - mEvnelope.dmAllowSubstDelivery = envel["dm_allow_subst_delivery"].toBool(); - mEvnelope.dmAmbiguousRecipient = envel["dm_ambiguous_recipient"].toBool(); - mEvnelope.dmAnnotation = envel["dm_annotation"].toString(); - mEvnelope.dmAttachmentSize = envel["dm_attachment_size"].toInt(); - mEvnelope.dmDeliveryTime = envel["dm_delivery_time"].toString(); - mEvnelope.dmLegalTitleLaw = envel["dm_legal_title_law"].toString(); - mEvnelope.dmLegalTitlePar = envel["dm_legal_title_par"].toString(); - mEvnelope.dmLegalTitlePoint = envel["dm_legal_title_point"].toString(); - mEvnelope.dmLegalTitleSect = envel["dm_legal_title_sect"].toString(); - mEvnelope.dmLegalTitleYear = envel["dm_legal_title_year"].toString(); - mEvnelope.dmMessageStatus = envel["dm_message_status"].toInt(); - mEvnelope.dmPersonalDelivery = envel["dm_personal_delivery"].toBool(); - mEvnelope.dmRecipient = envel["dm_recipient"].toString(); - mEvnelope.dmRecipientAddress = envel["dm_recipient_address"].toString(); - mEvnelope.dmRecipientIdent = envel["dm_recipient_ident"].toString(); - mEvnelope.dmRecipientOrgUnit = envel["dm_recipient_org_unit"].toString(); - mEvnelope.dmRecipientOrgUnitNum = envel["dm_recipient_org_unit_num"].toString(); - mEvnelope.dmRecipientRefNumber = envel["dm_recipient_ref_number"].toString(); - mEvnelope.dmSender = envel["dm_sender"].toString(); - mEvnelope.dmSenderAddress = envel["dm_sender_address"].toString(); - mEvnelope.dmSenderIdent = envel["dm_sender_ident"].toString(); - mEvnelope.dmSenderOrgUnit = envel["dm_sender_org_unit"].toString(); - mEvnelope.dmSenderOrgUnitNum = envel["dm_sender_org_unit_num"].toString(); - mEvnelope.dmSenderRefNumber = envel["dm_sender_ref_number"].toString(); - mEvnelope.dmSenderType = envel["dm_sender_type"].toInt(); - mEvnelope.dmToHands = envel["dm_to_hands"].toString(); - mEvnelope.dmType = envel["dm_type"].toInt(); - - QJsonArray tagArray = obj["tags"].toArray(); - foreach (const QJsonValue &value, tagArray) { - mEvnelope._tagList.append(value.toInt()); - } - - messageList.append(mEvnelope); - } - - return true; -} - - -bool JsonLayer::parseTagList(const QByteArray &content, - QList &tagList, QString &errStr) -{ - QJsonDocument jsonResponse = QJsonDocument::fromJson(content); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - QJsonArray tagArray = jsonObject["tags"].toArray(); - - foreach (const QJsonValue &value, tagArray) { - QJsonObject obj = value.toObject(); - Tag tag; - tag.id = obj["id"].toInt(); - tag.name = obj["name"].toString(); - tag.color = obj["color"].toString(); - tagList.append(tag); - } - - return true; -} - - -bool JsonLayer::parseSearchRecipient(const QByteArray &content, - QList &resultList, bool &hasMore, - QString &errStr) -{ - QJsonDocument jsonResponse = QJsonDocument::fromJson(content); - QJsonObject jsonObject = jsonResponse.object(); - if (!jsonObject["success"].toBool()) { - errStr = jsonObject["errmsg"].toString(); - return false; - } - - hasMore = jsonObject["hasMore"].toBool(); - - QJsonArray recipientArray = jsonObject["results"].toArray(); - - foreach (const QJsonValue &value, recipientArray) { - QJsonObject obj = value.toObject(); - Recipient rec; - rec.recipientDbId = obj["id"].toString(); - rec.recipientName = obj["name"].toString(); - rec.recipientAddress = obj["address"].toString(); - rec.toHands = ""; - resultList.append(rec); - } - - return true; -} diff -Nru datovka-4.8.3/src/web/json.h datovka-4.9.3/src/web/json.h --- datovka-4.8.3/src/web/json.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/web/json.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,548 +0,0 @@ -/* - * Copyright (C) 2014-2016 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _JSON_H_ -#define _JSON_H_ - -#include -#include -#include -#include - -#include "src/models/accounts_model.h" -#include "src/io/message_db.h" - -class JsonLayer : public QObject { - Q_OBJECT - -public: - - /*! - * @brief Holds information about owner and his databox. - */ - struct OwnerInfo { - public: - QString key; - QString dbID; - QString dbType; - QString ic; - QString pnFirstName; - QString pnMiddleName; - QString pnLastName; - QString pnLastNameAtBirth; - QString firmName; - QString biDate; - QString biCity; - QString biCounty; - QString biState; - QString adCity; - QString adStreet; - QString adNumberInStreet; - QString adNumberInMunicipality; - QString adZipCode; - QString adState; - QString nationality; - QString identifier; - QString registryCode; - int dbState; - bool dbEffectiveOVM; - bool dbOpenAddressing; - }; - - /*! - * @brief Holds information about an user. - */ - struct UserInfo { - public: - QString key; - QString pnFirstName; - QString pnMiddleName; - QString pnLastName; - QString pnLastNameAtBirth; - QString adCity; - QString adStreet; - QString adNumberInStreet; - QString adNumberInMunicipality; - QString adZipCode; - QString adState; - QString biDate; - QString userType; - int userPrivils; - int ic; - QString firmName; - QString caStreet; - QString caCity; - QString caZipCode; - QString caState; - }; - - /*! - * @brief Holds information about an tag properties. - */ - struct Tag { - public: - int id; - QString name; - QString color; - }; - - /*! - * @brief Holds data about recipient - */ - struct Recipient { - public: - QString recipientDbId; - QString recipientName; - QString recipientAddress; - QString toHands; - }; - - /*! - * @brief Holds file data - */ - struct File { - public: - QString fName; - QByteArray fContent; - }; - - /*! - * @brief Holds message envelope data from webdatovka. - */ - class Envelope { - public: - int id; - qint64 dmID; - QString dbIDSender; - QString dmSender; - QString dmSenderAddress; - int dmSenderType; - QString dmRecipient; - QString dmRecipientAddress; - QString dmAmbiguousRecipient; - QString dmSenderOrgUnit; - QString dmSenderOrgUnitNum; - QString dbIDRecipient; - QString dmRecipientOrgUnit; - QString dmRecipientOrgUnitNum; - QString dmToHands; - QString dmAnnotation; - QString dmRecipientRefNumber; - QString dmSenderRefNumber; - QString dmRecipientIdent; - QString dmSenderIdent; - QString dmLegalTitleLaw; - QString dmLegalTitleYear; - QString dmLegalTitleSect; - QString dmLegalTitlePar; - QString dmLegalTitlePoint; - bool dmPersonalDelivery; - bool dmAllowSubstDelivery; - QString dmQTimestamp; - QString dmDeliveryTime; - QString dmAcceptanceTime; - int dmMessageStatus; - int dmAttachmentSize; - QString dmType; - bool dmPublishOwnID; - bool dmOVM; - bool _read; - QList _tagList; - }; - - /*! - * @brief Holds account data and user info from webdatovka. - */ - struct AccountData { - public: - int userId; - int accountId; - QString name; - JsonLayer::OwnerInfo ownerInfo; - JsonLayer::UserInfo userInfo; - }; - - explicit JsonLayer(QObject *parent = 0); - ~JsonLayer(void); - - /*! - * @brief Fake login to Webdatovka - will be removed. - * - * @return sessionid from webdatovka. - */ - QNetworkCookie fakeLoginWebDatovka(void); - - /*! - * @brief First part of login to Webdatovka. - * Call webdatovka to obtain openconnect data. - * - * @param[out] lastUrl - last url of login sequence. - * @return true if first part was successed. - */ - bool startLoginToWebDatovka(QUrl &lastUrl); - - /*! - * @brief Middle part of login to Webdatovka. - * - * @param[in] method - selected login method. - * @param[in/out] lastUrl - last url of login sequence. - * @param[out] token - html security token. - * @return true if middle part was successed. - */ - bool loginMethodChanged(int method, QString &lastUrl, QString &token); - - /*! - * @brief Last part of login to Webdatovka. - * - * @param[in] lastUrl - last url of login sequence. - * @param[in] token - html security token. - * @param[in] username - mojeID username. - * @param[in] pwd - mojeID password. - * @param[in] otp - OTP password (optional). - * @param[in] certPath - path to certificate file. - * @param[out] errStr - contains an error string if unssucces. - * @param[out] sessionid - contains webdatovka sessionid. - * @return true if login success. - */ - bool loginToMojeID(const QString &lastUrl, - const QString &token, const QString &username, - const QString &pwd, const QString &otp, const QString &certPath, - QString &errStr, QNetworkCookie &sessionid); - - /*! - * @brief Ping to Webdatovka. - * - * @param[in] userName - account username. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool pingServer(const QString &userName, QString &errStr); - - /*! - * @brief Add account into Webdatovka. - * - * @param[in] userName - account username. - * @param[in] name - name of account. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool createAccount(const QString &userName, - const QString &name, QString &errStr); - - /*! - * @brief Update account name in Webdatovka. - * - * @param[in] userName - account username. - * @param[in] accountID - webdatovka id of account. - * @param[in] newName - new name of account. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool renameAccount(const QString &userName, - int accountID, const QString &newName, QString &errStr); - - /*! - * @brief Delete account from Webdatovka. - * - * @param[in] userName - account username. - * @param[in] accountID - webdatovka id of account. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool deleteAccount(const QString &userName, - int accountID, QString &errStr); - - /*! - * @brief Download all accounts from Webdatovka for one mojeID identity. - * - * @param[in] sessionid - sessionid cookie of Webdatovka. - * @param[out] userId - mojeID user id. - * @param[out] accountList - list of accounts. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool getAccountList(const QNetworkCookie &sessionid, int &userId, - QList &accountList, - QString &errStr); - - /*! - * @brief Download current message list (envelopes) from Webdatovka. - * - * @param[in] userName - account username. - * @param[in] accountID - webdatovka id of account. - * @param[in] messageType - webadatovka message type (sent = -1, received = 1); - * @param[in] limit - how many records mat be returned. - * @param[in] offset - default is 0. - * @param[out] messageList - list of message envelopes. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool getMessageList(const QString &userName, - int accountID, int messageType, int limit, - int offset, QList &messageList, - QString &errStr); - - /*! - * @brief Synchronize one account with isds via Webdatovka. - * - * @param[in] userName - account username. - * @param[in] accountID - webdatovka id of account. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool syncAccount(const QString &userName, - int accountID, QString &errStr); - - /*! - * @brief Download complete message from Webdatovka. - * - * @param[in] userName - account username. - * @param[in] msgId - webdatovka message id. - * @param[out] errStr - contains an error string if unssucces. - * @return message zfo binary data or NULL. - */ - QByteArray downloadMessage(const QString &userName, - int msgId, QString &errStr); - - /*! - * @brief Download one file of message from Webdatovka. - * - * @param[in] userName - account username. - * @param[in] fileId - webdatovka file id. - * @param[out] errStr - contains an error string if unssucces. - * @return file binary data or NULL. - */ - QByteArray downloadFile(const QString &userName, - int fileId, QString &errStr); - - /*! - * @brief Download tag list from Webdatovka for username. - * - * @param[in] userName - account username. - * @param[out] tagList - list of tag attributes. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool getTagList(const QString &userName, - QList &tagList, QString &errStr); - - /*! - * @brief Create tag in Webdatovka for username. - * - * @param[in] userName - account username. - * @param[in] name - tag name. - * @param[in] color - tag color. - * @param[out] errStr - contains an error string if unssucces. - * @return true webdatovka id of new tag if success else -1. - */ - int createTag(const QString &userName, - const QString &name, const QString &color, QString &errStr); - - /*! - * @brief Update tag data into Webdatovka for username. - * - * @param[in] userName - account username. - * @param[in] tagId - webdatovka tag id. - * @param[in] name - tag name. - * @param[in] color - tag color. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool updateTag(const QString &userName, int tagId, - const QString &name, const QString &color, QString &errStr); - - /*! - * @brief Delete tag from Webdatovka for username. - * - * @param[in] userName - account username. - * @param[in] tagId - webdatovka tag id. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool deleteTag(const QString &userName, - int tagId, QString &errStr); - - /*! - * @brief Assign tag to message in Webdatovka for username. - * - * @param[in] userName - account username. - * @param[in] tagId - webdatovka tag id. - * @param[in] msgId - webdatovka message id. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool assignTag(const QString &userName, - int tagId, int msgId, QString &errStr); - - /*! - * @brief Remove tag assigment from message in Webdatovka for username. - * - * @param[in] userName - account username. - * @param[in] tagId - webdatovka tag id. - * @param[in] msgId - webdatovka message id. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool removeTag(const QString &userName, - int tagId, int msgId, QString &errStr); - - /*! - * @brief Remove all tags from message in Webdatovka for username. - * - * @param[in] userName - account username. - * @param[in] msgId - webdatovka message id. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool removeAllTags(const QString &userName, - int msgId, QString &errStr); - - /*! - * @brief Search recipients via Webdatovka. - * - * @param[in] userName - account username. - * @param[in] accountID - webdatovka id of account. - * @param[in] word - word for search. - * @param[in] position - result list part, firstly is 0. - * @param[out] resultList - list of recipients, where message was sent. - * @param[out] hasMore - another list part of recipents is available. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool searchRecipient(const QString &userName, - int accountID, const QString &word, int position, - QList &resultList, bool &hasMore, - QString &errStr); - - /*! - * @brief Send message to recipients via Webdatovka. - * - * @param[in] userName - account username. - * @param[in] accountID - webdatovka id of account. - * @param[in] recipientList - another recipents are available. - * @param[in] envelope - message envelope data. - * @param[in] fileList - list of files (attachments). - * @param[out] resultList - list of recipients, where message was sent. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool sendMessage(const QString &userName, int accountID, - const QList &recipientList, - const JsonLayer::Envelope &envelope, - const QList &fileList, - QStringList &resultList, QString &errStr); - - /*! - * @brief Delete message from Webdatovka. - * - * @param[in] userName - account username. - * @param[in] msgId - webdatovka message id. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool deleteMessage(const QString &userName, int msgI, QString &errStr); - - /*! - * @brief Mark messages as read in Webdatovka. - * - * @param[in] userName - account username. - * @param[in] msgId - webdatovka message id. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool markMessageAsRead(const QString &userName, int msgId, - QString &errStr); - -private: - - /*! - * @brief Test if user is logged to Webdatovka. - * - * @param[in] userName - account username. - * @param[out] sessionid - sessionid cookie for GET/POST reguests. - * @return true if user is logged. - */ - bool isLoggedToWebDatovka(const QString &userName, - QNetworkCookie &sessionid); - - /*! - * @brief Update sessionid cookie. - * - * @param[in] userName - account username. - * @return true if success. - */ - bool updateSessionId(const QString &userName); - - /*! - * @brief Parse account list. - * - * @param[in] content - reply content. - * @param[out] userId - mojeID user id. - * @param[out] accountList - list of accounts. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool parseAccountList(const QByteArray &content, int &userId, - QList &accountList, - QString &errStr); - - /*! - * @brief Parse message list. - * - * @param[in] content - reply content. - * @param[out] messageList - list of message envelopes. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool parseMessageList(const QByteArray &content, - QList &messageList, QString &errStr); - - /*! - * @brief Parse tag list. - * - * @param[in] content - reply content. - * @param[out] tagList - list of tag attributes. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool parseTagList(const QByteArray &content, - QList &tagList, QString &errStr); - - /*! - * @brief Parse recipient records. - * - * @param[in] content - reply content. - * @param[out] resultList - list of recipients. - * @param[out] hasMore - another recipents are available. - * @param[out] errStr - contains an error string if unssucces. - * @return true if success. - */ - bool parseSearchRecipient(const QByteArray &content, - QList &resultList, bool &hasMore, - QString &errStr); -}; - -/* global jsonlazyer object */ -extern JsonLayer jsonlayer; - -#endif /* _JSON_H_ */ diff -Nru datovka-4.8.3/src/web/net_consts.h datovka-4.9.3/src/web/net_consts.h --- datovka-4.8.3/src/web/net_consts.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/web/net_consts.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2014-2016 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef NET_CONST_H -#define NET_CONST_H - -#define APP_NAME "Datovka" - -/* HTTP request timeout, default 30s */ -#define NET_REQUEST_TIMEOUT 30000 - -/* Cookie names which we use */ -#define COOKIE_SESSION_ID "sessionid" -#define COOKIE_SESSION_MOJEID "mojeidsession" -#define COOKIE_CSRFTOKEN "csrftoken" - -/* URL of endpoints and services */ -#define WEBDATOVKA_SERVICE_URL "https://datovka.labs.nic.cz/development/" -#define MOJEID_URL_PASSWORD "https://mojeid.fred.nic.cz/endpoint/password/" -#define MOJEID_URL_CERTIFICATE "https://mojeid.fred.nic.cz/endpoint/certificate/" -#define MOJEID_URL_OTP "https://mojeid.fred.nic.cz/endpoint/otp/" -#define MOJEID_URL_CONFIRM "https://mojeid.fred.nic.cz/endpoint/confirmation/" -#define MOJEID_URL_SSLLOGIN "https://mojeid.fred.nic.cz/endpoint/ssllogin/" - -#endif // NET_CONST_H diff -Nru datovka-4.8.3/src/web/net.cpp datovka-4.9.3/src/web/net.cpp --- datovka-4.8.3/src/web/net.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/web/net.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,383 +0,0 @@ -/* - * Copyright (C) 2014-2016 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "src/web/net.h" -#include "src/web/json.h" - -QList cookieList; -NetManager netmanager; - -static -void printRequest(QNetworkRequest request, QByteArray requestContent) -{ - qDebug() << ""; - qDebug() << "====================REQUEST========================="; - qDebug() << "URL:" << request.url().toString(); - qDebug() << "--------------------Headers-------------------------"; - QList reqHeaders = request.rawHeaderList(); - foreach (const QByteArray &reqName, reqHeaders) { - QByteArray reqValue = request.rawHeader(reqName); - qDebug() << reqName << ":" << reqValue; - } - qDebug() << "--------------------Content------------------------"; - qDebug() << requestContent; - qDebug() << "==================================================="; - qDebug() << ""; -} - - -NetManager::NetManager(QObject *parent) - : QObject(parent) -{ -} - -NetManager::~NetManager(void) -{ -} - -/* ========================================================================= */ -/* - * Func: Create POST request to WebDatovka. - */ -bool NetManager::createPostRequestWebDatovka(const QUrl &url, - const QNetworkCookie &sessionid, const QByteArray &data, QByteArray &outData) -/* ========================================================================= */ -{ - qDebug("%s()", __func__); - - QByteArray appName(APP_NAME); - QNetworkRequest request(url); - request.setRawHeader("Host", url.host().toUtf8()); - request.setRawHeader("User-Agent", appName); - request.setRawHeader("Accept", "application/json"); - request.setRawHeader("Connection", "keep-alive"); - request.setRawHeader("Content-Type", "application/json"); - request.setRawHeader("Content-Length", QByteArray::number(data.size())); - - if (!sessionid.name().isEmpty()) { - QVariant var; - var.setValue(sessionid); - request.setHeader(QNetworkRequest::CookieHeader, var); - } - - return sendRequest(request, data, outData, true); -} - - -/* ========================================================================= */ -/* - * Func: Create POST request for file sending to WebDatovka. - */ -bool NetManager::createPostRequestWebDatovkaSendFile(const QUrl &url, - const QNetworkCookie &sessionid, int &draftId, const QString &filename, - const QByteArray &filedata, QByteArray &outData) -/* ========================================================================= */ -{ - qDebug("%s()", __func__); - - QByteArray appName(APP_NAME); - QNetworkRequest request(url); - request.setRawHeader("Host", url.host().toUtf8()); - request.setRawHeader("User-Agent", appName); - request.setRawHeader("Accept", "application/json"); - request.setRawHeader("Draft-Id", QByteArray::number(draftId)); - QByteArray dispos; - dispos.append("form-data;"); - dispos.append("filename*=UTF-8''" + QUrl::toPercentEncoding(filename)); - request.setRawHeader("Content-Disposition", dispos); - request.setRawHeader("Connection", "keep-alive"); - request.setRawHeader("Content-type", "application/octet-stream"); - request.setRawHeader("Content-Length", QByteArray::number(filedata.size())); - - if (!sessionid.name().isEmpty()) { - QVariant var; - var.setValue(sessionid); - request.setHeader(QNetworkRequest::CookieHeader, var); - } - - return sendRequest(request, filedata, outData, true); -} - - -/* ========================================================================= */ -/* - * Func: Create GET request to WebDatovka. - */ -bool NetManager::createGetRequestWebDatovka(const QUrl &url, - const QNetworkCookie &sessionid, QByteArray &outData) -/* ========================================================================= */ -{ - qDebug("%s()", __func__); - - QByteArray appName(APP_NAME); - QNetworkRequest request(url); - request.setRawHeader("Host", url.host().toUtf8()); - request.setRawHeader("User-Agent", appName); - request.setRawHeader("Accept", - "text/html,application/xhtml+xml,application/xml"); - request.setRawHeader("Connection", "keep-alive"); - - if (!sessionid.name().isEmpty()) { - QVariant var; - var.setValue(sessionid); - request.setHeader(QNetworkRequest::CookieHeader, var); - } - - return sendRequest(request, QByteArray(), outData, false); -} - - -/* ========================================================================= */ -/* - * Func: Create POST request to MojeID. - */ -bool NetManager::createPostRequestMojeId(const QUrl &url, const QUrl &prevUrl, - const QByteArray &data, QByteArray &outData) -/* ========================================================================= */ -{ - qDebug("%s()", __func__); - - QByteArray appName(APP_NAME); - QNetworkRequest request(url); - request.setRawHeader("Host", url.host().toUtf8()); - request.setRawHeader("User-Agent", appName); - request.setRawHeader("Referer", prevUrl.toString().toUtf8()); - request.setRawHeader("Accept", - "text/html,application/xhtml+xml,application/xml"); - request.setRawHeader("Connection", "keep-alive"); - request.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); - request.setRawHeader("Content-Length", QByteArray::number(data.size())); - - QVariant var; - var.setValue(cookieList); - request.setHeader(QNetworkRequest::CookieHeader, var); - - return sendRequest(request, data, outData, true); -} - - -/* ========================================================================= */ -/* - * Func: Create POST request to MojeID with client certificate. - */ -bool NetManager::createPostRequestMojeIdCert(const QUrl &url, const QUrl &prevUrl, - const QByteArray &data, const QSslCertificate &cert, - const QSslKey &key, QByteArray &outData) -/* ========================================================================= */ -{ - qDebug("%s()", __func__); - - QByteArray appName(APP_NAME); - QNetworkRequest request(url); - request.setRawHeader("Host", url.host().toUtf8()); - request.setRawHeader("User-Agent", appName); - request.setRawHeader("Referer", prevUrl.toString().toUtf8()); - request.setRawHeader("Accept", - "text/html,application/xhtml+xml,application/xml"); - request.setRawHeader("Connection", "keep-alive"); - request.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); - request.setRawHeader("Content-Length", QByteArray::number(data.size())); - - QSslConfiguration sslConf = QSslConfiguration::defaultConfiguration(); - sslConf.setProtocol(QSsl::TlsV1_2); - sslConf.setLocalCertificate(cert); - sslConf.setPrivateKey(key); - request.setSslConfiguration(sslConf); - - QVariant var; - var.setValue(cookieList); - request.setHeader(QNetworkRequest::CookieHeader, var); - - return sendRequest(request, data, outData, true); -} - - -/* ========================================================================= */ -/* - * Func: Create GET request to MojeId. - */ -bool NetManager::createGetRequestMojeId(const QUrl &url, const QUrl &prevUrl, - QByteArray &outData) -/* ========================================================================= */ -{ - qDebug("%s()", __func__); - - QByteArray appName(APP_NAME); - QNetworkRequest request(url); - request.setRawHeader("Host", url.host().toUtf8()); - request.setRawHeader("User-Agent", appName); - request.setRawHeader("Referer", prevUrl.toString().toUtf8()); - request.setRawHeader("Accept", - "text/html,application/xhtml+xml,application/xml"); - request.setRawHeader("Connection", "keep-alive"); - - QVariant var; - for (int i = 0; i < cookieList.size(); ++i) { - if (cookieList.at(i).name() == COOKIE_SESSION_MOJEID) { - var.setValue(cookieList.at(i)); - request.setHeader(QNetworkRequest::CookieHeader, var); - } - } - - return sendRequest(request, QByteArray(), outData, false); -} - - -/* ========================================================================= */ -/* - * Func: Send request. - */ -bool NetManager::sendRequest(QNetworkRequest &request, - const QByteArray &data, QByteArray &outData, bool postRqst) -/* ========================================================================= */ -{ - qDebug("%s()", __func__); - - bool ret = true; - QNetworkReply *reply = NULL; - QNetworkAccessManager *nam = new QNetworkAccessManager; - -#if 1 - printRequest(request, data); -#endif - - if (postRqst) { - reply = nam->post(request, data); - } else { - reply = nam->get(request); - } - - /* TODO - add timer, set timeout from settings, run, - * abort request if timer = timeout - */ - - /* this eventloop makes synchronous soap requests */ - QEventLoop eventLoop; - QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); - eventLoop.exec(); - - ret = getResponse(reply, outData); - - reply->deleteLater(); - nam->deleteLater(); - - return ret; -} - - -/* ========================================================================= */ -/* - * Func: Response. - */ -bool NetManager::getResponse(QNetworkReply *reply, QByteArray &outData) -/* ========================================================================= */ -{ - qDebug("%s()", __func__); - - bool ret = true; - - int statusCode = reply->attribute( - QNetworkRequest::HttpStatusCodeAttribute).toInt(); - const QString url = reply->url().toString(); - const QString error = reply->errorString(); - const QString reason = reply->attribute( - QNetworkRequest::HttpReasonPhraseAttribute).toString(); - -#if 1 - qDebug() << ""; - qDebug() << "====================REPLY==========================="; - qDebug() << "URL:" << url; - qDebug() << "CODE:" << statusCode; - if (reply->error() != QNetworkReply::NoError) { - qDebug() << "ERROR:" << error; - } - qDebug() << "REASON:" << reason; - qDebug() << "--------------------Headers-------------------------"; - QList reqHeaders = reply->rawHeaderList(); - foreach (QByteArray reqName, reqHeaders) { - QByteArray reqValue = reply->rawHeader(reqName); - qDebug() << reqName << ":" << reqValue; - } - qDebug() << "----------------------------------------------------"; -#endif - - /* Process and store cookies */ - QVariant variantCookies = - reply->header(QNetworkRequest::SetCookieHeader); - QList list = - qvariant_cast >(variantCookies); - - bool up = false; - for (int i = 0; i < list.size(); ++i) { - up = false; - for (int j = 0; j < cookieList.count(); ++j) { - if (cookieList.at(j).name() == list.at(i).name()) { - cookieList.removeOne(cookieList.at(j)); - cookieList.append(list.at(i)); - up = true; - break; - } - } - if (!up) { - cookieList.append(list.at(i)); - } - } - - - switch (statusCode) { - case 200: /* HTTP status 200 OK */ - { - outData = reply->readAll(); - } - break; - - case 302: /* HTTP status 302 Found */ - { - outData = reply->readAll(); - QVariant possibleRedirectUrl = - reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - newUrl = possibleRedirectUrl.toString(); - } - break; - - default: /* Any error occurred */ - outData = QByteArray(); - break; - } -#if 0 - qDebug() << outData; -#endif - return ret; -} diff -Nru datovka-4.8.3/src/web/net.h datovka-4.9.3/src/web/net.h --- datovka-4.8.3/src/web/net.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/web/net.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2014-2016 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _NET_H_ -#define _NET_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/web/net_consts.h" - -class NetManager : public QObject { - Q_OBJECT - -public: - explicit NetManager(QObject *parent = 0); - ~NetManager(void); - -public: - - QString newUrl; - - /*! - * @brief Create POST request to WebDatovka. - * - * @param[in] url - url of request. - * @param[in] sessionid - cookie of request. - * @param[in] data - request content data. - * @param[out] outData - reply data. - * @return true if success. - */ - bool createPostRequestWebDatovka(const QUrl &url, - const QNetworkCookie &sessionid, const QByteArray &data, - QByteArray &outData); - - /*! - * @brief Create POST request for file sending to WebDatovka. - * - * @param[in] url - url of request. - * @param[in] sessionid - cookie of request. - * @param[in] draftId - draftId. - * @param[in] filename - file name. - * @param[in] filedata - file content data. - * @param[out] outData - reply data. - * @return true if success. - */ - bool createPostRequestWebDatovkaSendFile(const QUrl &url, - const QNetworkCookie &sessionid, int &draftId, - const QString &filename, const QByteArray &filedata, - QByteArray &outData); - - /*! - * @brief Create GET request to WebDatovka. - * - * @param[in] url - url of request. - * @param[in] sessionid - cookie of request. - * @param[out] outData -reply data. - * @return true if success. - */ - bool createGetRequestWebDatovka(const QUrl &url, - const QNetworkCookie &sessionid, QByteArray &outData); - - /*! - * @brief Create POST request to MojeID. - * - * @param[in] url - current url of request. - * @param[in] prevUrl - previous url. - * @param[in] data - request content data (cookie, credentials). - * @param[out] outData - reply data. - * @return true if success. - */ - bool createPostRequestMojeId(const QUrl &url, const QUrl &prevUrl, - const QByteArray &data, QByteArray &outData); - - /*! - * @brief Create POST request to MojeID with client certificate. - * - * @param[in] url - current url of request. - * @param[in] prevUrl - previous url. - * @param[in] data - request content data (cookie, credentials). - * @param[in] cert - certificate data. - * @param[in] key - private key data. - * @param[out] outData - reply data. - * @return true if success. - */ - bool createPostRequestMojeIdCert(const QUrl &url, const QUrl &prevUrl, - const QByteArray &data, const QSslCertificate &cert, - const QSslKey &key, QByteArray &outData); - - /*! - * @brief Create GET request to MojeID. - * - * @param[in] url - current url of request. - * @param[in] prevUrl - previous url. - * @param[out] outData - reply data. - * @return true if success. - */ - bool createGetRequestMojeId(const QUrl &url, const QUrl &prevUrl, - QByteArray &outData); - -private: - - /*! - * @brief Send request and run eventloop. - * - * @param[in] request - hold request data. - * @param[in] data - hold content data (may be NULL). - * @param[out] outData - reply data. - * @param[in] postRqst - it is POST request (POST = TRUE). - * @return true if success. - */ - bool sendRequest(QNetworkRequest &request, const QByteArray &data, - QByteArray &outData, bool postRqst); - - /*! - * @brief Parse response. - * - * @param[in] reply - pointer on the reply data. - * @param[out] outData - reply data. - * @return true if success. - */ - bool getResponse(QNetworkReply *reply, QByteArray &outData); -}; - -extern QList cookieList; -extern NetManager netmanager; - -#endif /* _NET_H_ */ diff -Nru datovka-4.8.3/src/worker/message_emitter.h datovka-4.9.3/src/worker/message_emitter.h --- datovka-4.8.3/src/worker/message_emitter.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/message_emitter.h 2017-09-06 11:49:23.000000000 +0000 @@ -49,19 +49,6 @@ bool listScheduled); /*! - * @brief Emitted when download message finishes - webdatovka. - * - * @param[in] usrName Account identifier (user login name). - * @param[in] msgId Message identifier. - * @param[in] result Operation outcome - * (enum TaskDownloadMessage::Result). - * @param[in] errDesc Error description string. - * @param[in] listScheduled True if ran from download message list. - */ - void downloadMessageFinishedMojeId(const QString &usrName, qint64 msgId, - int result, const QString &errDesc, bool listScheduled); - - /*! * @brief Emitted when download message finishes. * * @param[in] usrName Account identifier (user login name). @@ -136,21 +123,16 @@ bool isPDZ, qint64 dmId); /*! - * @brief Emitted when mojeid send message finishes. - * - * @param[in] userName Account username. - * @param[in] resultList ResultList from webdatovka. - * @param[in] error Error message from netmanager. - */ - void sendMessageMojeIdFinished(const QString &userName, - const QStringList &resultList, const QString &errStr); - - /*! * @brief This signal is emitted when status bar text is changed * * @param[in] text Status bar text. */ void statusBarChange(const QString &text); + + /*! + * @brief Emitted when records management stored messages task finishes. + */ + void recordsManagementStoredMessagesFinished(const QString &taskId); }; /*! diff -Nru datovka-4.8.3/src/worker/task.cpp datovka-4.9.3/src/worker/task.cpp --- datovka-4.8.3/src/worker/task.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,7 @@ #include "src/io/account_db.h" /* globAccountDbPtr */ #include "src/io/dbs.h" #include "src/io/isds_sessions.h" +#include "src/isds/isds_conversion.h" #include "src/log/log.h" #include "src/settings/preferences.h" #include "src/worker/message_emitter.h" @@ -74,7 +75,7 @@ isds_event *item = (isds_event *) event->data; messageDb->msgsInsertUpdateMessageEvent(dmID, timevalToDbFormat(item->time), - convertEventTypeToString(*item->type), + IsdsConversion::eventTypeToStr(*item->type) + QLatin1String(": "), item->description); event = event->next; } @@ -83,8 +84,7 @@ } qdatovka_error Task::storeEnvelope(enum MessageDirection msgDirect, - MessageDbSet &dbSet, const struct isds_envelope *envel, - QString msgId) + MessageDbSet &dbSet, const struct isds_envelope *envel) { debugFuncCall(); @@ -107,13 +107,9 @@ MessageDb *messageDb = dbSet.accessMessageDb(deliveryTime, true); Q_ASSERT(0 != messageDb); - if (msgId.isEmpty()) { - msgId = "tRecord"; - } - /* insert message envelope in db */ if (messageDb->msgsInsertMessageEnvelope(dmId, - msgId, + "tRecord", envel->dbIDSender, envel->dmSender, envel->dmSenderAddress, @@ -155,7 +151,7 @@ envel->dmAcceptanceTime ? timevalToDbFormat(envel->dmAcceptanceTime) : QString(), envel->dmMessageStatus ? - convertHexToDecIndex(*envel->dmMessageStatus) : 0, + IsdsConversion::msgStatusIsdsToDbRepr(*envel->dmMessageStatus) : 0, envel->dmAttachmentSize ? (int) *envel->dmAttachmentSize : 0, envel->dmType, @@ -172,7 +168,7 @@ qdatovka_error Task::storeMessage(bool signedMsg, enum MessageDirection msgDirect, MessageDbSet &dbSet, - const struct isds_message *msg, const QString &progressLabel, QString msgId) + const struct isds_message *msg, const QString &progressLabel) { debugFuncCall(); @@ -230,7 +226,7 @@ emit globMsgProcEmitter.progressChange(progressLabel, 30); - if (Q_SUCCESS == updateEnvelope(msgDirect, *messageDb, envel, msgId)) { + if (Q_SUCCESS == updateEnvelope(msgDirect, *messageDb, envel)) { logDebugLv0NL("Envelope of message '%" PRId64 "' updated.", dmID); } else { @@ -267,7 +263,8 @@ QByteArray hashValueBase64 = QByteArray((char *) hash->value, hash->length).toBase64(); if (messageDb->msgsInsertUpdateMessageHash(dmID, - hashValueBase64, convertHashAlg(hash->algorithm))) { + hashValueBase64, + IsdsConversion::hashAlgToStr(hash->algorithm))) { logDebugLv0NL("Hash of message '%" PRId64 "' stored.", dmID); } else { @@ -300,7 +297,7 @@ if (messageDb.msgsInsertUpdateMessageFile(dmId, item->dmFileDescr, item->dmUpFileGuid, item->dmFileGuid, item->dmMimeType, item->dmFormat, - convertAttachmentType(item->dmFileMetaType), + IsdsConversion::attachmentTypeToStr(item->dmFileMetaType), dmEncodedContentBase64)) { logDebugLv0NL( "Attachment file '%s' was stored into database.", @@ -316,7 +313,7 @@ } qdatovka_error Task::updateEnvelope(enum MessageDirection msgDirect, - MessageDb &messageDb, const struct isds_envelope *envel, QString msgId) + MessageDb &messageDb, const struct isds_envelope *envel) { debugFuncCall(); @@ -334,13 +331,9 @@ } } - if (msgId.isEmpty()) { - msgId = "tReturnedMessage"; - } - /* Update message envelope in db. */ if (messageDb.msgsUpdateMessageEnvelope(dmId, - msgId, + "tReturnedMessage", envel->dbIDSender, envel->dmSender, envel->dmSenderAddress, @@ -382,7 +375,7 @@ envel->dmAcceptanceTime ? timevalToDbFormat(envel->dmAcceptanceTime) : QString(), envel->dmMessageStatus ? - convertHexToDecIndex(*envel->dmMessageStatus) : 0, + IsdsConversion::msgStatusIsdsToDbRepr(*envel->dmMessageStatus) : 0, envel->dmAttachmentSize ? (int) *envel->dmAttachmentSize : 0, envel->dmType, @@ -397,106 +390,3 @@ return Q_GLOBAL_ERROR; } } - - -qdatovka_error Task::storeEnvelopeWebDatovka(enum MessageDirection msgDirect, - MessageDbSet &dbSet, const JsonLayer::Envelope &envel, bool isNew) -{ - debugFuncCall(); - - QDateTime dTime = fromIsoDatetimetoDateTime(envel.dmDeliveryTime); - - /* Allow invalid delivery time. */ - MessageDb *messageDb = dbSet.accessMessageDb(dTime, true); - Q_ASSERT(0 != messageDb); - - if (isNew) { - /* insert message envelope in db */ - if (messageDb->msgsInsertMessageEnvelope(envel.dmID, - QString::number(envel.id), - envel.dbIDSender, - envel.dmSender, - envel.dmSenderAddress, - envel.dmSenderType, - envel.dmRecipient, - envel.dmRecipientAddress, - envel.dmAmbiguousRecipient, - envel.dmSenderOrgUnit, - envel.dmSenderOrgUnitNum, - envel.dbIDRecipient, - envel.dmRecipientOrgUnit, - envel.dmRecipientOrgUnitNum, - envel.dmToHands, - envel.dmAnnotation, - envel.dmRecipientRefNumber, - envel.dmSenderRefNumber, - envel.dmRecipientIdent, - envel.dmSenderIdent, - envel.dmLegalTitleLaw, - envel.dmLegalTitleYear, - envel.dmLegalTitleSect, - envel.dmLegalTitlePar, - envel.dmLegalTitlePoint, - envel.dmPersonalDelivery, - envel.dmAllowSubstDelivery, - QByteArray(), - fromIsoDatetimetoDbformat(envel.dmDeliveryTime), - fromIsoDatetimetoDbformat(envel.dmAcceptanceTime), - envel.dmMessageStatus, - envel.dmAttachmentSize, - envel.dmType, - msgDirect)) { - logDebugLv0NL("Stored envelope of message '%" PRId64 "' into database.", - envel.dmID); - return Q_SUCCESS; - } else { - logErrorNL("Storing envelope of message '%" PRId64 "' failed.", - envel.dmID); - return Q_GLOBAL_ERROR; - } - } else { - /* Update message envelope in db. */ - if (messageDb->msgsUpdateMessageEnvelope(envel.dmID, - QString::number(envel.id), - envel.dbIDSender, - envel.dmSender, - envel.dmSenderAddress, - envel.dmSenderType, - envel.dmRecipient, - envel.dmRecipientAddress, - envel.dmAmbiguousRecipient, - envel.dmSenderOrgUnit, - envel.dmSenderOrgUnitNum, - envel.dbIDRecipient, - envel.dmRecipientOrgUnit, - envel.dmRecipientOrgUnitNum, - envel.dmToHands, - envel.dmAnnotation, - envel.dmRecipientRefNumber, - envel.dmSenderRefNumber, - envel.dmRecipientIdent, - envel.dmSenderIdent, - envel.dmLegalTitleLaw, - envel.dmLegalTitleYear, - envel.dmLegalTitleSect, - envel.dmLegalTitlePar, - envel.dmLegalTitlePoint, - envel.dmPersonalDelivery, - envel.dmAllowSubstDelivery, - QByteArray(), - fromIsoDatetimetoDbformat(envel.dmDeliveryTime), - fromIsoDatetimetoDbformat(envel.dmAcceptanceTime), - envel.dmMessageStatus, - envel.dmAttachmentSize, - envel.dmType, - msgDirect)) { - logDebugLv0NL("Stored envelope of message '%" PRId64 "' into database.", - envel.dmID); - return Q_SUCCESS; - } else { - logErrorNL("Storing envelope of message '%" PRId64 "' failed.", - envel.dmID); - return Q_GLOBAL_ERROR; - } - } -} diff -Nru datovka-4.8.3/src/worker/task_download_message.cpp datovka-4.9.3/src/worker/task_download_message.cpp --- datovka-4.8.3/src/worker/task_download_message.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_message.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,8 +26,9 @@ #include "src/io/dbs.h" #include "src/io/isds_sessions.h" +#include "src/isds/isds_conversion.h" #include "src/log/log.h" -#include "src/models/accounts_model.h" +#include "src/settings/accounts.h" #include "src/worker/message_emitter.h" #include "src/worker/task_download_message.h" @@ -77,7 +78,7 @@ logDebugLv1NL("%s", "-----------------------------------------------"); logDebugLv1NL("Downloading %s message '%" PRId64 "' for account '%s'.", (MSG_RECEIVED == m_msgDirect) ? "received" : "sent", m_mId.dmId, - AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); + globAccounts[m_userName].accountName().toUtf8().constData()); logDebugLv1NL("%s", "-----------------------------------------------"); m_result = downloadMessage(m_userName, m_mId, true, m_msgDirect, @@ -87,11 +88,11 @@ logDebugLv1NL( "Done downloading message '%" PRId64 "' for account '%s'.", m_mId.dmId, - AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); + globAccounts[m_userName].accountName().toUtf8().constData()); } else { logErrorNL("Downloading message '%" PRId64 "' for account '%s' failed.", m_mId.dmId, - AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); + globAccounts[m_userName].accountName().toUtf8().constData()); } emit globMsgProcEmitter.downloadMessageFinished(m_userName, m_mId.dmId, @@ -253,7 +254,7 @@ /* Store envelope in new location. */ Task::storeEnvelope(msgDirect, dbSet, - message->envelope, NULL); + message->envelope); } /* Update message delivery time. */ mId.deliveryTime = newDeliveryTime; @@ -261,7 +262,7 @@ /* Store the message. */ Task::storeMessage(signedMsg, msgDirect, dbSet, message, - progressLabel, NULL); + progressLabel); emit globMsgProcEmitter.progressChange(progressLabel, 90); @@ -339,7 +340,7 @@ } if (messageDb.updateMessageAuthorInfo(dmId, - convertSenderTypeToString((int) *sender_type), sender_name)) { + IsdsConversion::senderTypeToStr((int) *sender_type), sender_name)) { logDebugLv0NL( "Author information of message '%" PRId64 "' were updated.", dmId); diff -Nru datovka-4.8.3/src/worker/task_download_message_list.cpp datovka-4.9.3/src/worker/task_download_message_list.cpp --- datovka-4.8.3/src/worker/task_download_message_list.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_message_list.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,8 +26,9 @@ #include "src/io/dbs.h" #include "src/io/isds_sessions.h" +#include "src/isds/isds_conversion.h" #include "src/log/log.h" -#include "src/models/accounts_model.h" +#include "src/settings/accounts.h" #include "src/worker/message_emitter.h" #include "src/worker/pool.h" /* List with whole messages. */ #include "src/worker/task_download_message.h" /* List with whole messages. */ @@ -92,7 +93,7 @@ logDebugLv1NL("%s", "-----------------------------------------------"); logDebugLv1NL("Downloading %s message list for account '%s'.", (MSG_RECEIVED == m_msgDirect) ? "received" : "sent", - AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); + globAccounts[m_userName].accountName().toUtf8().constData()); logDebugLv1NL("%s", "-----------------------------------------------"); if (MSG_RECEIVED == m_msgDirect) { @@ -109,10 +110,10 @@ if (DL_SUCCESS == m_result) { logDebugLv1NL("Done downloading message list for account '%s'.", - AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); + globAccounts[m_userName].accountName().toUtf8().constData()); } else { logErrorNL("Downloading message list for account '%s' failed.", - AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); + globAccounts[m_userName].accountName().toUtf8().constData()); } emit globMsgProcEmitter.downloadMessageListFinished(m_userName, @@ -247,7 +248,12 @@ #ifdef USE_TRANSACTIONS if (!usedDbs.contains(messageDb)) { usedDbs.insert(messageDb); - messageDb->beginTransaction(); + if (!messageDb->beginTransaction()) { + logWarningNL( + "Cannot begin transaction for '%s'.", + userName.toUtf8().constData()); +// return DL_DB_INS_ERR; + } } #endif /* USE_TRANSACTIONS */ @@ -257,7 +263,7 @@ /* Message is NOT in db (-1), -> insert */ if (-1 == dmDbMsgStatus) { - Task::storeEnvelope(msgDirect, dbSet, item->envelope, NULL); + Task::storeEnvelope(msgDirect, dbSet, item->envelope); if (downloadWhole) { TaskDownloadMessage *task; task = new (std::nothrow) TaskDownloadMessage( @@ -272,13 +278,13 @@ } else { /* Update message and envelope only if status has changed. */ - const int dmNewMsgStatus = convertHexToDecIndex( + const int dmNewMsgStatus = IsdsConversion::msgStatusIsdsToDbRepr( *item->envelope->dmMessageStatus); if (dmNewMsgStatus != dmDbMsgStatus) { /* Update envelope */ Task::updateEnvelope(msgDirect, *messageDb, - item->envelope, NULL); + item->envelope); /* * Download whole message again if exists in db @@ -431,11 +437,11 @@ * we get proper data from ISDS rather than storing potentially * guessed values. */ - Task::updateEnvelope(msgDirect, *messageDb, envel, NULL); + Task::updateEnvelope(msgDirect, *messageDb, envel); } else if (messageDb->msgsUpdateMessageState(dmID, dmDeliveryTime, dmAcceptanceTime, envel->dmMessageStatus ? - convertHexToDecIndex(*envel->dmMessageStatus) : 0)) { + IsdsConversion::msgStatusIsdsToDbRepr(*envel->dmMessageStatus) : 0)) { /* Updated message envelope delivery info in db. */ logDebugLv0NL( "Delivery information of message '%" PRId64 "' were updated.", @@ -453,7 +459,7 @@ isds_event *item = (isds_event *) event->data; messageDb->msgsInsertUpdateMessageEvent(dmID, timevalToDbFormat(item->time), - convertEventTypeToString(*item->type), + IsdsConversion::eventTypeToStr(*item->type) + QLatin1String(": "), item->description); event = event->next; } diff -Nru datovka-4.8.3/src/worker/task_download_message_list_mojeid.cpp datovka-4.9.3/src/worker/task_download_message_list_mojeid.cpp --- datovka-4.8.3/src/worker/task_download_message_list_mojeid.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_message_list_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,305 +0,0 @@ -/* - * Copyright (C) 2014-2017 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#include -#include - -#include "src/io/dbs.h" -#include "src/log/log.h" -#include "src/worker/pool.h" -#include "src/worker/message_emitter.h" -#include "src/worker/task_download_message_list_mojeid.h" -#include "src/worker/task_download_message_mojeid.h" -#include "src/web/json.h" -#include "src/io/tag_db.h" -#include "src/io/tag_db_container.h" - -TaskDownloadMessageListMojeID::TaskDownloadMessageListMojeID( - const QString &userName, MessageDbSet *dbSet, - enum MessageDirection msgDirect, bool downloadWhole, - int dmLimit, int accountID, int dmOffset) - : m_result(DL_ERR), - m_userName(userName), - m_dbSet(dbSet), - m_msgDirect(msgDirect), - m_downloadWhole(downloadWhole), - m_dmLimit(dmLimit), - m_accountID(accountID), - m_dmOffset(dmOffset) -{ - Q_ASSERT(0 != m_dbSet); -} - -void TaskDownloadMessageListMojeID::run(void) -{ - if (m_userName.isEmpty()) { - Q_ASSERT(0); - return; - } - - if (0 == m_dbSet) { - Q_ASSERT(0); - return; - } - - if ((MSG_RECEIVED != m_msgDirect) && (MSG_SENT != m_msgDirect)) { - Q_ASSERT(0); - return; - } - - logDebugLv0NL("Starting download message list task in thread '%p'", - (void *) QThread::currentThreadId()); - - /* ### Worker task begin. ### */ - - int rt = 0; /*!< Received total. */ - int rn = 0; /*!< Received new. */ - int st = 0; /*!< Sent total. */ - int sn = 0; /*!< Sent new. */ - - logDebugLv1NL("%s", "-----------------------------------------------"); - logDebugLv1NL("Downloading %s message list for account '%s'.", - (MSG_RECEIVED == m_msgDirect) ? "received" : "sent", - AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); - logDebugLv1NL("%s", "-----------------------------------------------"); - - if (MSG_RECEIVED == m_msgDirect) { - m_result = downloadMessageList(m_userName, MSG_RECEIVED, - *m_dbSet, m_downloadWhole, m_error, - PL_DOWNLOAD_RECEIVED_LIST, rt, rn, m_dmLimit, - m_accountID, m_dmOffset); - } else { - m_result = downloadMessageList(m_userName, MSG_SENT, - *m_dbSet, m_downloadWhole, m_error, - PL_DOWNLOAD_SENT_LIST, st, sn, m_dmLimit, - m_accountID, m_dmOffset); - } - - if (DL_SUCCESS == m_result) { - logDebugLv1NL("Done downloading message list for account '%s'.", - AccountModel::globAccounts[m_userName]. - accountName().toUtf8().constData()); - } else { - logErrorNL("Downloading message list for account '%s' failed.", - AccountModel::globAccounts[m_userName]. - accountName().toUtf8().constData()); - } - - emit globMsgProcEmitter.downloadMessageListFinished(m_userName, - m_msgDirect, m_result, m_error, true, rt, rn , st, sn); - - emit globMsgProcEmitter.progressChange(PL_IDLE, 0); - - /* ### Worker task end. ### */ - - logDebugLv0NL("Download message list task finished in thread '%p'", - (void *) QThread::currentThreadId()); -} - -enum TaskDownloadMessageListMojeID::Result -TaskDownloadMessageListMojeID::downloadMessageList( - const QString &userName, enum MessageDirection msgDirect, - MessageDbSet &dbSet, bool downloadWhole, QString &error, - const QString &progressLabel, int &total, int &news, - int dmLimit, int accountID, int dmOffset) -{ - debugFuncCall(); - - #define USE_TRANSACTIONS 1 - - int newcnt = 0; - int allcnt = 0; - qint64 dmID = -1; - - if (userName.isEmpty()) { - Q_ASSERT(0); - return DL_ERR; - } - - emit globMsgProcEmitter.progressChange(progressLabel, 0); - - emit globMsgProcEmitter.progressChange(progressLabel, 10); - - QList messageList; - - /* webdatovka message types */ - int msgType = 1; - if (MSG_SENT == msgDirect) { - msgType = -1; - } - - if (!jsonlayer.getMessageList(userName, accountID, msgType, dmLimit, - dmOffset, messageList, error)) { - if (!error.isEmpty()) { - qDebug("ERROR: %s", error.toUtf8().constData()); - } else { - qDebug("%s", "ERROR: get-mesasge-list fails"); - } - return DL_NET_ERROR; - } - - emit globMsgProcEmitter.progressChange(progressLabel, 20); - - float delta = 0.0; - float diff = 0.0; - allcnt = messageList.count(); - - if (allcnt == 0) { - emit globMsgProcEmitter.progressChange(progressLabel, 50); - } else { - delta = 80.0 / allcnt; - } - - /* Obtain invalid message database if has a separate file. */ - MessageDb *invalidDb = NULL; - { - QString invSecKey(dbSet.secondaryKey(QDateTime())); - QString valSecKey(dbSet.secondaryKey( - QDateTime::currentDateTime())); - if (invSecKey != valSecKey) { - /* Invalid database file may not exist. */ - invalidDb = dbSet.accessMessageDb(QDateTime(), false); - } - } - -#ifdef USE_TRANSACTIONS - QSet usedDbs; -#endif /* USE_TRANSACTIONS */ - - for (int i = 0; i < allcnt; ++i) { - - newcnt++; - diff += delta; - - emit globMsgProcEmitter.progressChange(progressLabel, - (int) (20 + diff)); - - dmID = messageList.at(i).dmID; - - /* - * Time may be invalid (e.g. messages which failed during - * virus scan). - */ - QDateTime deliveryTime = - fromIsoDatetimetoDateTime(messageList.at(i).dmDeliveryTime); - - /* Delivery time may be invalid. */ - if ((0 != invalidDb) && deliveryTime.isValid()) { - /* Try deleting possible invalid entry. */ - invalidDb->msgsDeleteMessageData(dmID); - } - MessageDb *messageDb = dbSet.accessMessageDb(deliveryTime, true); - Q_ASSERT(0 != messageDb); - - -#ifdef USE_TRANSACTIONS - if (!usedDbs.contains(messageDb)) { - usedDbs.insert(messageDb); - messageDb->beginTransaction(); - } -#endif /* USE_TRANSACTIONS */ - - const int dmDbMsgStatus = messageDb->msgsStatusIfExists(dmID); - - /* message is not in db (-1) */ - if (-1 == dmDbMsgStatus) { - - /* download and save complete message */ - if (downloadWhole) { - - TaskDownloadMessageMojeId *task; - task = new (std::nothrow) TaskDownloadMessageMojeId( - userName, &dbSet, msgDirect, - messageList.at(i).id, - messageList.at(i).dmID, - true); - task->setAutoDelete(true); - globWorkPool.assignLo(task, WorkerPool::PREPEND); - - /* store message envelope only */ - } else { - Task::storeEnvelopeWebDatovka(msgDirect, dbSet, - messageList.at(i), true); - } - - newcnt++; - - /* Message is in db (dmDbMsgStatus <> -1). */ - } else { - /* Update envelope if message status has changed. */ - if (messageList.at(i).dmMessageStatus != dmDbMsgStatus) { - Task::storeEnvelopeWebDatovka(msgDirect, - dbSet, messageList.at(i), false); - } - - /* download and save complete message */ - if (downloadWhole && !messageDb->msgsStoredWhole(dmID)) { - - TaskDownloadMessageMojeId *task; - task = new (std::nothrow) TaskDownloadMessageMojeId( - userName, &dbSet, msgDirect, - messageList.at(i).id, - messageList.at(i).dmID, - true); - task->setAutoDelete(true); - globWorkPool.assignLo(task, WorkerPool::PREPEND); - - } - } - - TagDb *tagDb = globWebDatovkaTagDbPtr-> - accessTagDb(getWebDatovkaTagDbPrefix(userName)); - Q_ASSERT(0 != tagDb); - - messageDb->smsgdtSetLocallyRead(dmID, messageList.at(i)._read); - tagDb->removeAllTagsFromMsg(userName, dmID); - - for (int t = 0; t < messageList.at(i)._tagList.count(); ++t) { - tagDb->assignTagToMsg(userName, - messageList.at(i)._tagList.at(t), dmID); - } - } - -#ifdef USE_TRANSACTIONS - /* Commit on all opened databases. */ - foreach (MessageDb *db, usedDbs) { - db->commitTransaction(); - } -#endif /* USE_TRANSACTIONS */ - - emit globMsgProcEmitter.progressChange(progressLabel, 100); - - if (MSG_RECEIVED == msgDirect) { - logDebugLv0NL("#Received total: %d #Received new: %d", - allcnt, newcnt); - } else { - logDebugLv0NL("#Sent total: %d #Sent new: %d", allcnt, newcnt); - } - - total = allcnt; - news = newcnt; - - return DL_SUCCESS; - -#undef USE_TRANSACTIONS -} diff -Nru datovka-4.8.3/src/worker/task_download_message_list_mojeid.h datovka-4.9.3/src/worker/task_download_message_list_mojeid.h --- datovka-4.8.3/src/worker/task_download_message_list_mojeid.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_message_list_mojeid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _TASK_DOWNLOAD_MESSAGE_LIST_MOJEID_H_ -#define _TASK_DOWNLOAD_MESSAGE_LIST_MOJEID_H_ - -#include -#include "src/io/message_db_set.h" -#include "src/worker/task.h" - -/*! - * @brief Task describing download message list. - */ -class TaskDownloadMessageListMojeID : public Task { -public: - /*! - * @brief Return state describing what happened. - */ - enum Result { - DL_SUCCESS, /*!< Operation was successful. */ - DL_NET_ERROR, /*!< Error communicating with webdatovka. */ - DL_DB_INS_ERR, /*!< Error inserting into database. */ - DL_ERR /*!< Other error. */ - }; - - /*! - * @brief Constructor. - * - * @param[in] userName Account identifier (user login name). - * @param[in,out] dbSet Non-null pointer to database container. - * @param[in] msgDirect Received or sent list. - * @param[in] downloadWhole True to plan downloading whole messages. - * @param[in] dmLimit Message list length limit. - * @param[in] accountID Webdatovka account ID. - * @param[in] dmOffset ISDS message offset, default 0. - */ - explicit TaskDownloadMessageListMojeID(const QString &userName, - MessageDbSet *dbSet, enum MessageDirection msgDirect, - bool downloadWhole, int dmLimit, int accountID, int dmOffset); - - /*! - * @brief Performs actual message download. - */ - virtual - void run(void) Q_DECL_OVERRIDE; - - /*! - * @brief Download message list from ISDS for given account. - * - * TODO -- This method ought to be protected. - * - * @param[in] userName Account identifier (user login name). - * @param[in] msgDirect Received or sent message. - * @param[in,out] dbSet Database container. - * @param[in] downloadWhole True to plan downloading whole - * messages. - * @param[out] error Error description. - * @param[in] progressLabel Progress-bar label. - * @param[out] total Total number of messages. - * @param[out] news Number of new messages. - * @param[in] dmLimit Maximum number of message list; - * NULL if you don't care. - * @param[in] accountID Webdatovka account ID. - * @param[in] dmOffset ISDS message offset, default 0. - * @return Error state. - */ - static - enum Result downloadMessageList(const QString &userName, - enum MessageDirection msgDirect, MessageDbSet &dbSet, - bool downloadWhole, QString &error, - const QString &progressLabel, int &total, int &news, - int dmLimit, int accountID, int dmOffset); - - enum Result m_result; /*!< Return state. */ - QString m_error; - -private: - /*! - * Disable copy and assignment. - */ - TaskDownloadMessageListMojeID(const TaskDownloadMessageListMojeID &); - TaskDownloadMessageListMojeID &operator=(const TaskDownloadMessageListMojeID &); - - const QString m_userName; /*!< Account identifier (user login name). */ - MessageDbSet *m_dbSet; /*!< Pointer to database container. */ - enum MessageDirection m_msgDirect; /*!< Sent or received list. */ - const bool m_downloadWhole; /*!< Plan downloading whole messages. */ - int m_dmLimit; /*!< List length limit. */ - int m_accountID; /*!< Webdatovka account ID. */ - int m_dmOffset; /*!< ISDS message offset, default 0 */ -}; - -#endif /* _TASK_DOWNLOAD_MESSAGE_LIST_MOJEID_H_ */ diff -Nru datovka-4.8.3/src/worker/task_download_message_mojeid.cpp datovka-4.9.3/src/worker/task_download_message_mojeid.cpp --- datovka-4.8.3/src/worker/task_download_message_mojeid.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_message_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#include -#include - -#include "src/io/dbs.h" -#include "src/log/log.h" -#include "src/io/isds_sessions.h" -#include "src/worker/message_emitter.h" -#include "src/worker/task_download_message_mojeid.h" -#include "src/gui/dlg_import_zfo.h" /* TODO -- Remove this dependency. */ -#include "src/web/json.h" - -TaskDownloadMessageMojeId::TaskDownloadMessageMojeId(const QString &userName, - MessageDbSet *dbSet, enum MessageDirection msgDirect, int id, - qint64 dmId, bool listScheduled) - : m_result(DM_ERR), - m_error(), - m_id(id), - m_userName(userName), - m_dbSet(dbSet), - m_msgDirect(msgDirect), - m_dmId(dmId), - m_listScheduled(listScheduled) -{ - Q_ASSERT(0 != dbSet); -} - -void TaskDownloadMessageMojeId::run(void) -{ - if (m_userName.isEmpty()) { - Q_ASSERT(0); - return; - } - - if (0 == m_dbSet) { - Q_ASSERT(0); - return; - } - - if ((MSG_RECEIVED != m_msgDirect) && (MSG_SENT != m_msgDirect)) { - Q_ASSERT(0); - return; - } - - logDebugLv0NL("Starting download message task in thread '%p'", - (void *) QThread::currentThreadId()); - - /* ### Worker task begin. ### */ - - logDebugLv1NL("%s", "-----------------------------------------------"); - logDebugLv1NL("Downloading %s message '%" PRId64 "' for account '%s'.", - (MSG_RECEIVED == m_msgDirect) ? "received" : "sent", m_id, - AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); - logDebugLv1NL("%s", "-----------------------------------------------"); - - m_result = downloadMessage(m_id, m_msgDirect, *m_dbSet, - m_error, PL_DOWNLOAD_MESSAGE, m_userName); - - if (DM_SUCCESS == m_result) { - logDebugLv1NL( - "Done downloading message '%" PRId64 "' for account '%s'.", - m_id, AccountModel::globAccounts[m_userName]. - accountName().toUtf8().constData()); - } else { - logErrorNL("Downloading message '%" PRId64 "' for account '%s' failed.", - m_id, AccountModel::globAccounts[m_userName]. - accountName().toUtf8().constData()); - } - - emit globMsgProcEmitter.downloadMessageFinishedMojeId(m_userName, - m_dmId, m_result, m_error, m_listScheduled); - - emit globMsgProcEmitter.progressChange(PL_IDLE, 0); - - /* ### Worker task end. ### */ - - logDebugLv0NL("Download message task finished in thread '%p'", - (void *) QThread::currentThreadId()); -} - -enum TaskDownloadMessageMojeId::Result TaskDownloadMessageMojeId::downloadMessage( - int id, enum MessageDirection msgDirect, MessageDbSet &dbSet, QString &error, - const QString &progressLabel, const QString &userName) -{ - debugFuncCall(); - - logDebugLv0NL("Trying to download complete message '%" PRId64 "'", id); - - emit globMsgProcEmitter.progressChange(progressLabel, 0); - - QByteArray zfoData = jsonlayer.downloadMessage(userName, id, error); - - emit globMsgProcEmitter.progressChange(progressLabel, 30); - - if (zfoData.isEmpty()) { - return DM_ERR; - } - - struct isds_ctx *dummy_session = isds_ctx_create(); - if (NULL == dummy_session) { - logError("%s\n", "Cannot create dummy ISDS session."); - return DM_ERR; - } - - emit globMsgProcEmitter.progressChange(progressLabel, 40); - - struct isds_message *message; - message = loadZfoData(dummy_session, zfoData, - ImportZFODialog::IMPORT_MESSAGE_ZFO); - if (NULL == message) { - logError("%s\n", "Cannot parse message data."); - return DM_ERR; - } - - emit globMsgProcEmitter.progressChange(progressLabel, 60); - - Task::storeEnvelope(msgDirect, dbSet, message->envelope, - QString::number(id)); - emit globMsgProcEmitter.progressChange(progressLabel, 80); - - Task::storeMessage(true, msgDirect, dbSet, message, - progressLabel, QString::number(id)); - - jsonlayer.markMessageAsRead(userName, id, error); - - emit globMsgProcEmitter.progressChange(progressLabel, 100); - - logDebugLv0NL("Done with %s().", __func__); - - return DM_SUCCESS; -} diff -Nru datovka-4.8.3/src/worker/task_download_message_mojeid.h datovka-4.9.3/src/worker/task_download_message_mojeid.h --- datovka-4.8.3/src/worker/task_download_message_mojeid.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_message_mojeid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _TASK_DOWNLOAD_MESSAGE_MOJEID_H_ -#define _TASK_DOWNLOAD_MESSAGE_MOJEID_H_ - -#include -#include - -#include "src/io/message_db.h" -#include "src/io/message_db_set.h" -#include "src/worker/task.h" - -/*! - * @brief Task describing download message. - */ -class TaskDownloadMessageMojeId : public Task { -public: - /*! - * @brief Return state describing what happened. - */ - enum Result { - DM_SUCCESS, /*!< Operation was successful. */ - DM_NET_ERROR, /*!< Error communicating with webdatovka. */ - DM_DB_INS_ERR, /*!< Error inserting into database. */ - DM_ERR /*!< Other error. */ - }; - - /*! - * @brief Constructor. - * - * @param[in] userName Account identifier (user login name). - * @param[in,out] dbSet Non-null pointer to database container. - * @param[in] msgDirect Received or sent list. - * @param[in] id Message webdatovka identifier. - * @param[in] dmId Message isds identifier. - * @param[in] listScheduled True if the task has been scheduled - * from TaskDownloadMessageList. - */ - explicit TaskDownloadMessageMojeId(const QString &userName, - MessageDbSet *dbSet, enum MessageDirection msgDirect, int id, - qint64 dmId, bool listScheduled); - - /*! - * @brief Performs actual message download. - */ - virtual - void run(void) Q_DECL_OVERRIDE; - - /*! - * @brief Download whole message (envelope, attachments, raw). - * - * TODO -- This method ought to be protected. - * - * @param[in] id Message identifier. - * @param[in] msgDirect Received or sent message. - * @param[in,out] dbSet Database container. - * @param[out] error Error description. - * @param[in] progressLabel Progress-bar label. - * @param[in] userName Account identifier (user login name) - * @return Error state. - */ - static - enum Result downloadMessage(int id, - enum MessageDirection msgDirect, MessageDbSet &dbSet, - QString &error, const QString &progressLabel, const QString &userName); - - enum Result m_result; /*!< Return state. */ - QString m_error; /*!< Error description. */ - int m_id; /*!< Message webdatovka identifier. */ - - -private: - /*! - * Disable copy and assignment. - */ - TaskDownloadMessageMojeId(const TaskDownloadMessageMojeId &); - TaskDownloadMessageMojeId &operator=(const TaskDownloadMessageMojeId &); - - const QString m_userName; /*!< Account identifier (user login name). */ - MessageDbSet *m_dbSet; /*!< Pointer to database container. */ - enum MessageDirection m_msgDirect; /*!< Sent or received message. */ - qint64 m_dmId; /*!< Message isds ID. */ - bool m_listScheduled; /*< - * Whether the task has been scheduled from - * download message list task. - */ -}; - -#endif /* _TASK_DOWNLOAD_MESSAGE_MOJEID_H_ */ diff -Nru datovka-4.8.3/src/worker/task_download_owner_info.cpp datovka-4.9.3/src/worker/task_download_owner_info.cpp --- datovka-4.8.3/src/worker/task_download_owner_info.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_owner_info.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #include "src/io/account_db.h" #include "src/io/dbs.h" #include "src/io/isds_sessions.h" +#include "src/isds/isds_conversion.h" #include "src/log/log.h" #include "src/worker/message_emitter.h" #include "src/worker/task_download_owner_info.h" @@ -101,7 +102,7 @@ bool ret = globAccountDbPtr->insertAccountIntoDb( AccountDb::keyFromLogin(userName), ownerInfo->dbID, - convertDbTypeToString(*ownerInfo->dbType), + IsdsConversion::boxTypeToStr(*ownerInfo->dbType), ic, ownerInfo->personName ? ownerInfo->personName->pnFirstName : NULL, diff -Nru datovka-4.8.3/src/worker/task_download_owner_info_mojeid.cpp datovka-4.9.3/src/worker/task_download_owner_info_mojeid.cpp --- datovka-4.8.3/src/worker/task_download_owner_info_mojeid.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_owner_info_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#include - -#include "src/io/account_db.h" -#include "src/log/log.h" -#include "src/worker/message_emitter.h" -#include "src/worker/task_download_owner_info_mojeid.h" -#include "src/web/json.h" - -TaskDownloadOwnerInfoMojeId::TaskDownloadOwnerInfoMojeId(int id) - : m_success(false), - m_isdsError(), - m_id(id) -{ -} - -void TaskDownloadOwnerInfoMojeId::run(void) -{ - - logDebugLv0NL("Starting download owner info task in thread '%p'", - (void *) QThread::currentThreadId()); - - /* ### Worker task begin. ### */ - - m_success = downloadOwnerInfo(m_id, m_isdsError); - - emit globMsgProcEmitter.progressChange(PL_IDLE, 0); - - /* ### Worker task end. ### */ - - logDebugLv0NL("Download owner info task finished in thread '%p'", - (void *) QThread::currentThreadId()); -} - -bool TaskDownloadOwnerInfoMojeId::downloadOwnerInfo(int id, QString &error) -{ - JsonLayer::AccountInfo aInfo; - - emit globMsgProcEmitter.progressChange(PL_IDLE, -1); - - if (jsonlayer.getAccountInfo(id, aInfo, error)) { - return globAccountDbPtr->insertAccountIntoDb( - AccountDb::keyFromLogin(aInfo.key), - aInfo.dbID, - aInfo.dbType, - aInfo.ic.toInt(), - aInfo.pnFirstName, - aInfo.pnMiddleName, - aInfo.pnLastName, - aInfo.pnLastNameAtBirth, - aInfo.firmName, - aInfo.biDate, - aInfo.biCity, - aInfo.biCounty, - aInfo.biState, - aInfo.adCity, - aInfo.adStreet, - aInfo.adNumberInStreet, - aInfo.adNumberInMunicipality, - aInfo.adZipCode, - aInfo.adState, - aInfo.nationality, - aInfo.identifier, - aInfo.registryCode, - aInfo.dbState, - aInfo.dbEffectiveOVM, - aInfo.dbOpenAddressing - ); - } else { - return false; - } -} diff -Nru datovka-4.8.3/src/worker/task_download_owner_info_mojeid.h datovka-4.9.3/src/worker/task_download_owner_info_mojeid.h --- datovka-4.8.3/src/worker/task_download_owner_info_mojeid.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_owner_info_mojeid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _TASK_DOWNLOAD_OWNER_INFO_MOJEID_H_ -#define _TASK_DOWNLOAD_OWNER_INFO_MOJEID_H_ - -#include - -#include "src/worker/task.h" - -/*! - * @brief Task describing download owner information. - */ -class TaskDownloadOwnerInfoMojeId : public Task { -public: - /*! - * @brief Constructor. - * - * @param[in] id Account identifier (account id). - */ - explicit TaskDownloadOwnerInfoMojeId(int id); - - /*! - * @brief Performs action. - */ - virtual - void run(void) Q_DECL_OVERRIDE; - - bool m_success; /*!< True on success. */ - QString m_isdsError; /*!< Error description. */ - -private: - /*! - * Disable copy and assignment. - */ - TaskDownloadOwnerInfoMojeId(const TaskDownloadOwnerInfoMojeId &); - TaskDownloadOwnerInfoMojeId &operator=(const TaskDownloadOwnerInfoMojeId &); - - /*! - * @brief Download owner information. - * - * @param[in] id Account identifier (account id). - * @param[out] error Error description. - * @return True on success. - */ - static - bool downloadOwnerInfo(int id, QString &error); - - int m_id; /*!< Account identifier (account id). */ -}; - -#endif /* _TASK_DOWNLOAD_OWNER_INFO_MOJEID_H_ */ diff -Nru datovka-4.8.3/src/worker/task_download_user_info.cpp datovka-4.9.3/src/worker/task_download_user_info.cpp --- datovka-4.8.3/src/worker/task_download_user_info.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_user_info.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #include "src/io/account_db.h" #include "src/io/dbs.h" #include "src/io/isds_sessions.h" +#include "src/isds/isds_conversion.h" #include "src/log/log.h" #include "src/worker/message_emitter.h" #include "src/worker/task_download_user_info.h" @@ -89,7 +90,7 @@ bool ret = globAccountDbPtr->insertUserIntoDb( AccountDb::keyFromLogin(userName), - convertUserTypeToString(*userInfo->userType), + IsdsConversion::userTypeToStr(*userInfo->userType), (int) *userInfo->userPrivils, userInfo->personName ? userInfo->personName->pnFirstName : NULL, userInfo->personName ? userInfo->personName->pnMiddleName : NULL, diff -Nru datovka-4.8.3/src/worker/task_download_user_info_mojeid.cpp datovka-4.9.3/src/worker/task_download_user_info_mojeid.cpp --- datovka-4.8.3/src/worker/task_download_user_info_mojeid.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_user_info_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#include - -#include "src/io/account_db.h" -#include "src/log/log.h" -#include "src/worker/message_emitter.h" -#include "src/worker/task_download_user_info_mojeid.h" -#include "src/web/json.h" - -TaskDownloadUserInfoMojeId::TaskDownloadUserInfoMojeId(int id) - : m_success(false), - m_isdsError(), - m_id(id) -{ -} - -void TaskDownloadUserInfoMojeId::run(void) -{ - logDebugLv0NL("Starting download user info task in thread '%p'", - (void *) QThread::currentThreadId()); - - /* ### Worker task begin. ### */ - - m_success = downloadUserInfo(m_id, m_isdsError); - - emit globMsgProcEmitter.progressChange(PL_IDLE, 0); - - /* ### Worker task end. ### */ - - logDebugLv0NL("Download user info task finished in thread '%p'", - (void *) QThread::currentThreadId()); -} - -bool TaskDownloadUserInfoMojeId::downloadUserInfo(int id, QString &error) -{ - JsonLayer::UserInfo uInfo; - - emit globMsgProcEmitter.progressChange(PL_IDLE, -1); - - if (jsonlayer.getUserInfo(id, uInfo, error)) { - return globAccountDbPtr->insertUserIntoDb( - AccountDb::keyFromLogin(uInfo.key), - uInfo.userType, - uInfo.userPrivils, - uInfo.pnFirstName, - uInfo.pnMiddleName, - uInfo.pnLastName, - uInfo.pnLastNameAtBirth, - uInfo.adCity, - uInfo.adStreet, - uInfo.adNumberInStreet, - uInfo.adNumberInMunicipality, - uInfo.adZipCode, - uInfo.adState, - uInfo.biDate, - uInfo.ic, - uInfo.firmName, - uInfo.caStreet, - uInfo.caCity, - uInfo.caZipCode, - uInfo.caState - ); - } else { - return false; - } -} diff -Nru datovka-4.8.3/src/worker/task_download_user_info_mojeid.h datovka-4.9.3/src/worker/task_download_user_info_mojeid.h --- datovka-4.8.3/src/worker/task_download_user_info_mojeid.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_download_user_info_mojeid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _TASK_DOWNLOAD_USER_INFO_MOJEID_H_ -#define _TASK_DOWNLOAD_USER_INFO_MOJEID_H_ - -#include - -#include "src/worker/task.h" - -/*! - * @brief Task describing download user information. - */ -class TaskDownloadUserInfoMojeId : public Task { -public: - /*! - * @brief Constructor. - * - * @param[in] id Account identifier (account id). - */ - explicit TaskDownloadUserInfoMojeId(int id); - - /*! - * @brief Performs action. - */ - virtual - void run(void) Q_DECL_OVERRIDE; - - bool m_success; /*!< True on success. */ - QString m_isdsError; /*!< Error description. */ - -private: - /*! - * Disable copy and assignment. - */ - TaskDownloadUserInfoMojeId(const TaskDownloadUserInfoMojeId &); - TaskDownloadUserInfoMojeId &operator=(const TaskDownloadUserInfoMojeId &); - - /*! - * @brief Download user information. - * - * @param[in] id Account identifier (account id). - * @param[out] error Error description. - * @return True on success. - */ - static - bool downloadUserInfo(int id, QString &error); - - int m_id; /*!< Account identifier (account id). */ -}; - - -#endif /* _TASK_DOWNLOAD_USER_INFO_MOJEID_H_ */ diff -Nru datovka-4.8.3/src/worker/task_get_account_list_mojeid.cpp datovka-4.9.3/src/worker/task_get_account_list_mojeid.cpp --- datovka-4.8.3/src/worker/task_get_account_list_mojeid.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_get_account_list_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#include - -#include "src/io/account_db.h" -#include "src/models/accounts_model.h" -#include "src/log/log.h" -#include "src/worker/message_emitter.h" -#include "src/worker/task_get_account_list_mojeid.h" -#include "src/web/json.h" -#include "src/io/wd_sessions.h" - -TaskGetAccountListMojeId::TaskGetAccountListMojeId(const QString &userName, - const QNetworkCookie &sessionid, bool syncWithAll, - AccountModel *accountModel, QStringList &deletedAccounts) - : m_return(ACNTLIST_SUCCESS), - m_error(), - m_userName(userName), - m_sessionid(sessionid), - m_syncWithAll(syncWithAll), - m_accountModel(accountModel), - m_deletedAccounts(deletedAccounts) -{ -} - -void TaskGetAccountListMojeId::run(void) -{ - - logDebugLv0NL("Starting download account list task in thread '%p'", - (void *) QThread::currentThreadId()); - - /* ### Worker task begin. ### */ - - m_return = getAccountList(m_userName, m_sessionid, m_syncWithAll, - m_accountModel, m_error, m_deletedAccounts); - - emit globMsgProcEmitter.progressChange(PL_IDLE, 0); - - /* ### Worker task end. ### */ - - logDebugLv0NL("Download account list task finished in thread '%p'", - (void *) QThread::currentThreadId()); -} - -enum TaskGetAccountListMojeId::Result TaskGetAccountListMojeId::getAccountList( - const QString &userName, const QNetworkCookie &sessionid, - bool syncWithAll, AccountModel *accountModel, QString &error, - QStringList &deletedAccounts) -{ - int newUserId = 0; - int userId = 0; - QString localUserName = userName; - QList accountList; - QModelIndex index; - - emit globMsgProcEmitter.progressChange(PL_GET_ACCOUNT_LIST, -1); - - if (!jsonlayer.getAccountList(sessionid, newUserId, accountList, error)) { - return ACNTLIST_WEBDAT_ERR; - } - - /* test, if we are logged for relevant userId (account) */ - if (!localUserName.isEmpty()) { - userId = getWebDatovkaUserId(localUserName); - if (userId != newUserId) { - if (accountList.isEmpty()) { - return ACNTLIST_WRONGUSER; - } else { - return ACNTLIST_WU_HAS_ACNT; - } - } - deletedAccounts.clear(); - - /* how many accounts are relevant to given userId */ - AccountsMap::iterator i; - for (i = accountModel->globAccounts.begin(); - i != accountModel->globAccounts.end(); ++i) { - if (isWebDatovkaAccount(i->userName())) { - if (newUserId == getWebDatovkaUserId(i->userName())) { - deletedAccounts.append(i->userName()); - } - } - } - } - - /* if account list is empty, do nothing */ - if (accountList.isEmpty()) { - return ACNTLIST_NONEXIST; - } - - /* do action with account list (add/update account) */ - for (int i = 0; i < accountList.count(); ++i) { - localUserName = getWebDatovkaUsername( - QString::number(accountList.at(i).userId), - QString::number(accountList.at(i).accountId)); - if (!accountModel->globAccounts.contains(localUserName)) { - AcntSettings aSet; - aSet.setUserName(localUserName); - aSet.setAccountName(accountList.at(i).name); - aSet.setLoginMethod(AcntSettings::LIM_MOJE_ID); - aSet.setSyncWithAll(syncWithAll); - accountModel->addAccount(aSet, &index); - } else { - deletedAccounts.removeOne(localUserName); - accountModel->globAccounts[localUserName].setAccountName( - accountList.at(i).name); - } - - updateMojeIdAccountData(localUserName, accountList.at(i)); - - wdSessions.createCleanSession(localUserName); - wdSessions.setSessionCookie(localUserName, sessionid); - emit globMsgProcEmitter.refreshAccountList(localUserName); - } - - /* if relevantAccounts are not empty - * so any account(s) was/were removed from Webdatovka. - */ - if (!deletedAccounts.isEmpty()) { - return ACNTLIST_DELETE_ACNT; - } - - return ACNTLIST_SUCCESS; -} - -bool TaskGetAccountListMojeId::updateMojeIdAccountData(const QString &userName, - const JsonLayer::AccountData &aData) -{ - const QString acntDbKey(AccountDb::keyFromLogin(userName)); - - bool ret = globAccountDbPtr->insertAccountIntoDb( - acntDbKey, - aData.ownerInfo.dbID, - aData.ownerInfo.dbType, - aData.ownerInfo.ic.toInt(), - aData.ownerInfo.pnFirstName, - aData.ownerInfo.pnMiddleName, - aData.ownerInfo.pnLastName, - aData.ownerInfo.pnLastNameAtBirth, - aData.ownerInfo.firmName, - aData.ownerInfo.biDate, - aData.ownerInfo.biCity, - aData.ownerInfo.biCounty, - aData.ownerInfo.biState, - aData.ownerInfo.adCity, - aData.ownerInfo.adStreet, - aData.ownerInfo.adNumberInStreet, - aData.ownerInfo.adNumberInMunicipality, - aData.ownerInfo.adZipCode, - aData.ownerInfo.adState, - aData.ownerInfo.nationality, - aData.ownerInfo.identifier, - aData.ownerInfo.registryCode, - aData.ownerInfo.dbState, - aData.ownerInfo.dbEffectiveOVM, - aData.ownerInfo.dbOpenAddressing - ); - - ret = globAccountDbPtr->insertUserIntoDb( - acntDbKey, - aData.userInfo.userType, - aData.userInfo.userPrivils, - aData.userInfo.pnFirstName, - aData.userInfo.pnMiddleName, - aData.userInfo.pnLastName, - aData.userInfo.pnLastNameAtBirth, - aData.userInfo.adCity, - aData.userInfo.adStreet, - aData.userInfo.adNumberInStreet, - aData.userInfo.adNumberInMunicipality, - aData.userInfo.adZipCode, - aData.userInfo.adState, - aData.userInfo.biDate, - aData.userInfo.ic, - aData.userInfo.firmName, - aData.userInfo.caStreet, - aData.userInfo.caCity, - aData.userInfo.caZipCode, - aData.userInfo.caState - ); - - return ret; -} diff -Nru datovka-4.8.3/src/worker/task_get_account_list_mojeid.h datovka-4.9.3/src/worker/task_get_account_list_mojeid.h --- datovka-4.8.3/src/worker/task_get_account_list_mojeid.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_get_account_list_mojeid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _TASK_GET_ACCOUNT_LIST_H_ -#define _TASK_GET_ACCOUNT_LIST_H_ - -#include - -#include "src/worker/task.h" - -/*! - * @brief Task describing download account list and its information data. - */ -class TaskGetAccountListMojeId : public Task { -public: - - /*! - * @Brief Return state describing what happened. - */ - enum Result { - ACNTLIST_SUCCESS, /*!< Action was successful. */ - ACNTLIST_NONEXIST, /*!< There aren't any accounts for mojeID. */ - ACNTLIST_WRONGUSER, /*!< UserID is not match with exists account userId. */ - ACNTLIST_WU_HAS_ACNT, /*!< UserID is not match with exists userId but new userId has any account */ - ACNTLIST_WEBDAT_ERR, /*!< Other webdatovka error. */ - ACNTLIST_DELETE_ACNT /*!< Any account was deleted in webdatovka. */ - }; - - /*! - * @brief Constructor. - * - * @param[in] userName Username of account. - * @param[in] sessionid Session cookie from mojeid. - * @param[in] syncWithAll If will be synchronized with all accounts. - * @param[in] accountModel Pointer to account model. - * @param[out] deletedAccounts Deleted account usernames. - */ - explicit TaskGetAccountListMojeId(const QString &userName, - const QNetworkCookie &sessionid, bool syncWithAll, - AccountModel *accountModel, QStringList &deletedAccounts); - - /*! - * @brief Performs action. - */ - virtual - void run(void) Q_DECL_OVERRIDE; - - enum Result m_return; /*!< Retrun error code. */ - QString m_error; /*!< Error description. */ - QString m_userName; /*!< Account username or NULL. */ - const QNetworkCookie m_sessionid;/*!< Session cookie from mojeid. */ - bool m_syncWithAll; /*!< If will be synchronized with all accounts. */ - AccountModel *m_accountModel; /*!< Pointer to account model. */ - QStringList m_deletedAccounts; /*!< List of deleted accounts */ - -private: - /*! - * Disable copy and assignment. - */ - TaskGetAccountListMojeId(const TaskGetAccountListMojeId &); - TaskGetAccountListMojeId &operator=(const TaskGetAccountListMojeId &); - - /*! - * @brief Download account list, - * - * @param[in] userName Username of account. - * @param[in] sessionid Session cookie from mojeid. - * @param[in] syncWithAll If will be synchronized with all accounts. - * @param[in] accountModel Pointer to account model. - * @param[out] error Error description. - * @param[out] deletedAccounts Deleted account usernames. - * @return Action result. - */ - static - enum Result getAccountList(const QString &userName, - const QNetworkCookie &sessionid, bool syncWithAll, - AccountModel *accountModel, QString &error, - QStringList &deletedAccounts); - - /*! - * @brief Insert/update owner and user information. - * - * @param[in] userName Account username. - * @param[in] aData Account data. - * @return True on success. - */ - static - bool updateMojeIdAccountData(const QString &userName, - const JsonLayer::AccountData &aData); -}; - -#endif /* _TASK_GET_ACCOUNT_LIST_H_ */ diff -Nru datovka-4.8.3/src/worker/task.h datovka-4.9.3/src/worker/task.h --- datovka-4.8.3/src/worker/task.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task.h 2017-09-06 11:49:23.000000000 +0000 @@ -30,7 +30,6 @@ #include "src/common.h" // qdatovka_error, enum MessageDirection #include "src/io/message_db.h" // MessageDb::MsgId #include "src/io/message_db_set.h" -#include "src/web/json.h" /*! * @brief Maximum length of message list to be downloaded. @@ -114,13 +113,11 @@ * @param[in] msgDirect Received or sent message. * @param[in,out] dbSet Database container. * @param[in] envel Message envelope. - * @param[in] msgId Message webdatovka id or NULL. * @return Error state. */ static qdatovka_error storeEnvelope(enum MessageDirection msgDirect, - MessageDbSet &dbSet, const struct isds_envelope *envel, - QString msgId); + MessageDbSet &dbSet, const struct isds_envelope *envel); /*! * @brief Store message into database. @@ -137,7 +134,7 @@ qdatovka_error storeMessage(bool signedMsg, enum MessageDirection msgDirect, MessageDbSet &dbSet, const struct isds_message *msg, - const QString &progressLabel, QString msgId); + const QString &progressLabel); /*! * @brief Store attachments into database. @@ -157,26 +154,11 @@ * @param[in] msgDirect Received or sent message. * @param[in,out] messageDb Database. * @param[in] envel Message envelope. - * @param[in] msgId Message webdatovka id or NULL. * @return True on success. */ static qdatovka_error updateEnvelope(enum MessageDirection msgDirect, - MessageDb &messageDb, const struct isds_envelope *envel, - QString msgId); - - /*! - * @brief Store envelope into database. - * - * @param[in] msgDirect Received or sent message. - * @param[in,out] dbSet Database container. - * @param[in] envel Message envelope. - * @param[in] isNew true = insert into db, false = update in db. - * @return Error state. - */ - static - qdatovka_error storeEnvelopeWebDatovka(enum MessageDirection msgDirect, - MessageDbSet &dbSet, const JsonLayer::Envelope &envel, bool isNew); + MessageDb &messageDb, const struct isds_envelope *envel); private: // /*! diff -Nru datovka-4.8.3/src/worker/task_import_zfo.cpp datovka-4.9.3/src/worker/task_import_zfo.cpp --- datovka-4.8.3/src/worker/task_import_zfo.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_import_zfo.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -31,7 +31,7 @@ #include "src/io/dbs.h" #include "src/io/isds_sessions.h" #include "src/log/log.h" -#include "src/models/accounts_model.h" +#include "src/settings/accounts.h" #include "src/worker/message_emitter.h" #include "src/worker/task_authenticate_message.h" #include "src/worker/task_import_zfo.h" @@ -115,12 +115,12 @@ } struct isds_message *message = loadZfoFile(dummySession, fileName, - ImportZFODialog::IMPORT_MESSAGE_ZFO); + Imports::IMPORT_MESSAGE); if (NULL != message) { zfoType = ZT_MESSAGE; } else { message = loadZfoFile(dummySession, fileName, - ImportZFODialog::IMPORT_DELIVERY_ZFO); + Imports::IMPORT_DELIVERY); if(NULL != message) { zfoType = ZT_DELIVERY_INFO; } else { @@ -144,11 +144,11 @@ */ static enum TaskImportZfo::Result loadZfo(const QString &fileName, - enum ImportZFODialog::ZFOtype zfoType, struct isds_message **msgPtr) + enum Imports::Type zfoType, struct isds_message **msgPtr) { Q_ASSERT((NULL != msgPtr) && (NULL == *msgPtr)); - Q_ASSERT((ImportZFODialog::IMPORT_MESSAGE_ZFO == zfoType) || - (ImportZFODialog::IMPORT_DELIVERY_ZFO == zfoType)); + Q_ASSERT((Imports::IMPORT_MESSAGE == zfoType) || + (Imports::IMPORT_DELIVERY == zfoType)); struct isds_message *message = NULL; @@ -220,8 +220,7 @@ "database file could not be accessed or created."); return TaskImportZfo::IMP_ERR; } - const QString accountName( - AccountModel::globAccounts[acnt.userName].accountName()); + const QString accountName(globAccounts[acnt.userName].accountName()); if (-1 != messageDb->msgsStatusIfExists(dmId)) { resultDesc = QObject::tr("Message '%1' already exists in " "the local database, account '%2'."). @@ -256,9 +255,9 @@ /* Store envelope and message. */ if ((Q_SUCCESS != Task::storeEnvelope(direct, *(acnt.messageDbSet), - message->envelope, NULL)) || + message->envelope)) || (Q_SUCCESS != Task::storeMessage(true, direct, *(acnt.messageDbSet), - message, "", NULL))) { + message, ""))) { resultDesc = QObject::tr("File has not been imported because " "an error was detected during insertion process."); return TaskImportZfo::IMP_DB_INS_ERR; @@ -279,7 +278,7 @@ { enum TaskImportZfo::Result res = loadZfo(fileName, - ImportZFODialog::IMPORT_MESSAGE_ZFO, &message); + Imports::IMPORT_MESSAGE, &message); if (IMP_SUCCESS != res) { Q_ASSERT(NULL == message); resultDesc = QObject::tr("Wrong ZFO format. This file " @@ -369,8 +368,7 @@ MessageDb *messageDb = acnt.messageDbSet->accessMessageDb(deliveryTime, false); - const QString accountName( - AccountModel::globAccounts[acnt.userName].accountName()); + const QString accountName(globAccounts[acnt.userName].accountName()); if ((NULL == messageDb) || (-1 == messageDb->msgsStatusIfExists(dmId))) { /* Corresponding message does not exist in database. */ @@ -436,7 +434,7 @@ { enum TaskImportZfo::Result res = loadZfo(fileName, - ImportZFODialog::IMPORT_DELIVERY_ZFO, &message); + Imports::IMPORT_DELIVERY, &message); if (IMP_SUCCESS != res) { Q_ASSERT(NULL == message); resultDesc = QObject::tr("Wrong ZFO format. This file " diff -Nru datovka-4.8.3/src/worker/task_records_management_stored_messages.cpp datovka-4.9.3/src/worker/task_records_management_stored_messages.cpp --- datovka-4.8.3/src/worker/task_records_management_stored_messages.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/worker/task_records_management_stored_messages.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include +#include + +#include "src/io/records_management_db.h" +#include "src/log/log.h" +#include "src/records_management/io/records_management_connection.h" +#include "src/records_management/json/entry_error.h" +#include "src/records_management/json/stored_files.h" +#include "src/worker/message_emitter.h" +#include "src/worker/task_records_management_stored_messages.h" + +TaskRecordsManagementStoredMessages::TaskRecordsManagementStoredMessages( + const QString &urlStr, const QString &tokenStr, enum Operation operation, + const MessageDbSet *dbSet, const QList &exludedDmIds) + : m_result(DS_DSM_ERR), + m_id(QString::number(QDateTime::currentMSecsSinceEpoch()) + + QStringLiteral(":") + QString::number((quint64)this)), + m_url(urlStr), + m_token(tokenStr), + m_operation(operation), + m_dbSet(dbSet), + m_exludedDmIds(exludedDmIds) +{ + Q_ASSERT(!m_url.isEmpty() && !m_token.isEmpty()); + Q_ASSERT((RM_UPDATE_STORED == operation) || (Q_NULLPTR != m_dbSet)); +} + +void TaskRecordsManagementStoredMessages::run(void) +{ + if ((RM_DOWNLOAD_ALL == m_operation) && (Q_NULLPTR == m_dbSet)) { + Q_ASSERT(0); + return; + } + + if (m_url.isEmpty() || m_token.isEmpty()) { + Q_ASSERT(0); + return; + } + + logDebugLv0NL( + "Starting download stored messages from records management service task '%s' in thread '%p'.", + m_id.toUtf8().constData(), (void *) QThread::currentThreadId()); + + /* ### Worker task begin. ### */ + + m_result = downloadStoredMessages(m_url, m_token, m_operation, m_dbSet, + m_exludedDmIds); + + emit globMsgProcEmitter.progressChange(PL_IDLE, 0); + + /* ### Worker task end. ### */ + + logDebugLv0NL("Download stored messages from records management service task '%s' finished in thread '%p'.", + m_id.toUtf8().constData(), (void *) QThread::currentThreadId()); + + emit globMsgProcEmitter.recordsManagementStoredMessagesFinished(m_id); +} + +const QString &TaskRecordsManagementStoredMessages::id(void) const +{ + return m_id; +} + +/*! + * @brief Obtains all message identifiers from message database. + * + * @param[in] dbSet Database set to be used to obtain message identifiers. + * @patam[in] exludedDmIds Message identifiers that should not be queried. + * @return List of message identifiers. + */ +static +QList obtainDbSetDmIds(const MessageDbSet *dbSet, + const QList &exludedDmIds) +{ + if (Q_NULLPTR == dbSet) { + Q_ASSERT(0); + return QList(); + } + + QSet dmIdSet; + + foreach (const MessageDb::MsgId &msgId, dbSet->getAllMessageIDsFromDB()) { + dmIdSet.insert(msgId.dmId); + } + + dmIdSet -= exludedDmIds.toSet(); + return dmIdSet.toList(); +} + +/*! + * @brief Obtains all message identifiers held in records management database. + * + * @patam[in] exludedDmIds Message identifiers that should not be queried. + * @return List of message identifiers. + */ +static +QList obtainHeldDmIds(const QList &exludedDmIds) +{ + if (Q_NULLPTR == globRecordsManagementDbPtr) { + Q_ASSERT(0); + return QList(); + } + + QSet dmIdSet = globRecordsManagementDbPtr->getAllDmIds().toSet(); + + dmIdSet -= exludedDmIds.toSet(); + return dmIdSet.toList(); +} + +/*! + * @brief Checks whether response contains all requested entries. + * + * @param[in] sfRes Stored files response structure + * @param[in] sentDmIds Set identifiers. + * @return True if response contains requested entries. + */ +static +bool receivedRequestedContent(const StoredFilesResp &sfRes, + const QList &sentDmIds) +{ + QSet sentDmIdSet(sentDmIds.toSet()); + + foreach (const DmEntry &entry, sfRes.dms()) { + if (!sentDmIdSet.remove(entry.dmId())) { + logErrorNL( + "Obtained response for message '%" PRId64 "'that has not been requested.", + entry.dmId()); + return false; + } + } + + if (!sentDmIdSet.isEmpty()) { + logErrorNL("%s", "Did not obtain all requested message entries."); + return false; + } + + return true; +} + +/*! + * @brief Store response into database. + * + * @param[in] sfRes Stored files response structure. + * @param[in] clear If true then all messages not held within the service will + * be explicitly removed. + * @return True on success, false on error. + */ +static +bool storeStoredFilesResponseContent(const StoredFilesResp &sfRes, bool clear) +{ + /* Process only messages. */ + + if (Q_NULLPTR == globRecordsManagementDbPtr) { + return false; + } + + if (!globRecordsManagementDbPtr->beginTransaction()) { + return false; + } + + foreach (const DmEntry &entry, sfRes.dms()) { + if (entry.locations().isEmpty()) { + /* Not held within the records management service. */ + if (clear) { + globRecordsManagementDbPtr->deleteStoredMsg( + entry.dmId()); + } else { + continue; + } + } + + if (!globRecordsManagementDbPtr->updateStoredMsg(entry.dmId(), + entry.locations())) { + logErrorNL( + "Could not update information about message '%" PRId64 "'.", + entry.dmId()); + goto fail; + } + } + + if (!globRecordsManagementDbPtr->commitTransaction()) { + goto fail; + } + return true; + +fail: + globRecordsManagementDbPtr->rollbackTransaction(); + return false; +} + +/*! + * @brief Process response. + * + * @param[in] clear If true then all messages not held within the service will + * be explicitly removed. + * @param[in] sfRes Stored files response structure. + * @param[in] sentDmIds Set identifiers. + * @param[out] limit Obtained limit. + * @return Number of processed responses, negative value on error. + */ +static +int processStoredFilesResponse(bool clear, const StoredFilesResp &sfRes, + const QList &sentDmIds, int &limit) +{ + /* Limit should always be received. */ + if (sfRes.limit() <= 0) { + Q_ASSERT(0); + return -1; + } + limit = sfRes.limit(); + + switch (sfRes.error().code()) { + case ErrorEntry::ERR_NO_ERROR: + break; + case ErrorEntry::ERR_LIMIT_EXCEEDED: + return 0; /* Nothing was processed. Should ask again. */ + break; + default: + logErrorNL("Received error '%s'.", + sfRes.error().trVerbose().toUtf8().constData()); + return -1; + break; + } + + if (!receivedRequestedContent(sfRes, sentDmIds)) { + return -1; + } + + if (!storeStoredFilesResponseContent(sfRes, clear)) { + return -1; + } + + return sfRes.dms().size(); +} + +/*! + * @brief Call records management service and process response. + * + * @param[in] clear If true then all messages not held within the service will + * be explicitly removed. + * @param[in] rmc Records management service connection. + * @param[in] dmIds Message identifiers. + * @param[out] limit Obtained limit. + * @return Number of processed responses, negative value on error. + */ +static +int callStoredFiles(bool clear, RecordsManagementConnection &rmc, + const QList &dmIds, int &limit) +{ + if (dmIds.isEmpty()) { + Q_ASSERT(0); + return -1; + } + + StoredFilesReq sfReq(dmIds, QList()); + if (!sfReq.isValid()) { + logErrorNL("%s", "Could not create stored_files request."); + return -1; + } + + QByteArray response; + + if (rmc.communicate(RecordsManagementConnection::SRVC_STORED_FILES, + sfReq.toJson(), response)) { + if (!response.isEmpty()) { + bool ok = false; + StoredFilesResp sfRes(StoredFilesResp::fromJson(response, &ok)); + if (!ok || !sfRes.isValid()) { + logErrorNL("%s", + "Communication error. Received invalid response to stored_files service."); + logErrorNL("Invalid response '%s'.", response.constData()); + return -1; + } + + return processStoredFilesResponse(clear, sfRes, dmIds, + limit); + } else { + logErrorNL("%s", + "Communication error. Received empty response to stored_files service."); + return -1; + } + } else { + logErrorNL("%s", + "Communication error when attempting to access stored_files service."); + return -1; + } +} + +/*! + * @brief Calls stored files service for all supplied message identifiers. + * + * @param[in] urlStr Records management URL. + * @param[in] tokenStr Records management access token. + * @param[in] dmIds Message identifiers. + * @param[in] clear If true then all messages not held within the service will + * be explicitly removed. + * @return Processing state. + */ +static +enum TaskRecordsManagementStoredMessages::Result updateMessages( + const QString &urlStr, const QString &tokenStr, const QList &dmIds, + bool clear) +{ + if (dmIds.isEmpty()) { + return TaskRecordsManagementStoredMessages::DS_DSM_SUCCESS; + } + + RecordsManagementConnection rmc( + RecordsManagementConnection::ignoreSslErrorsDflt); + rmc.setConnection(urlStr, tokenStr); + + int pos = 0; /* Position. */ + int currentLimit = 1; /* Start with smallest query to obtain maximal size. */ + int nextLimit = 0; + + /* While list is not processed. */ + while ((pos >= 0) && (pos < dmIds.size())) { + QList queryList(dmIds.mid(pos, currentLimit)); + + int ret = callStoredFiles(clear, rmc, queryList, nextLimit); + if (ret < 0) { + return TaskRecordsManagementStoredMessages::DS_DSM_ERR; + } + pos += ret; + currentLimit = nextLimit; /* Update limit. */ + } + + return TaskRecordsManagementStoredMessages::DS_DSM_ERR; +} + +enum TaskRecordsManagementStoredMessages::Result +TaskRecordsManagementStoredMessages::downloadStoredMessages( + const QString &urlStr, const QString &tokenStr, enum Operation operation, + const MessageDbSet *dbSet, const QList &exludedDmIds) +{ + if ((RM_DOWNLOAD_ALL == operation) && (Q_NULLPTR == dbSet)) { + Q_ASSERT(0); + return DS_DSM_ERR; + } + + if (Q_NULLPTR == globRecordsManagementDbPtr) { + return DS_DSM_DB_INS_ERR; + } + + QList dmIds; + if (RM_DOWNLOAD_ALL == operation) { + dmIds = obtainDbSetDmIds(dbSet, exludedDmIds); + } else { + dmIds = obtainHeldDmIds(exludedDmIds); + } + return updateMessages(urlStr, tokenStr, dmIds, + RM_UPDATE_STORED == operation); +} diff -Nru datovka-4.8.3/src/worker/task_records_management_stored_messages.h datovka-4.9.3/src/worker/task_records_management_stored_messages.h --- datovka-4.8.3/src/worker/task_records_management_stored_messages.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/src/worker/task_records_management_stored_messages.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _TASK_RECORDS_MANAGEMENT_STORED_MESSAGES_H_ +#define _TASK_RECORDS_MANAGEMENT_STORED_MESSAGES_H_ + +#include +#include + +#include "src/io/message_db_set.h" +#include "src/worker/task.h" + +/*! + * @brief Task describing downloading information about stored messages. + */ +class TaskRecordsManagementStoredMessages : public Task { +public: + /*! + * @brief Return state describing what happened. + */ + enum Result { + DS_DSM_SUCCESS, /*!< Operation was successful. */ + DS_DSM_COM_ERROR, /*!< Error communicating with ISDS. */ + DS_DSM_DB_INS_ERR, /*!< Error inserting into database. */ + DS_DSM_ERR /*!< Other error. */ + }; + + /*! + * @brief Operation to be performed. + */ + enum Operation { + RM_UPDATE_STORED, /*!< Update only messages in records management database. */ + RM_DOWNLOAD_ALL /*!< Download all messages that are held in database set. */ + }; + + /*! + * @brief Constructor. + * + * @param[in] urlStr Records management URL. + * @param[in] tokenStr Records management access token. + * @param[in] operation Actual action to be performed. + * @param[in] dbSet Database set to be used to obtain message identifiers. + * @patam[in] exludedDmIds Message identifiers that should not be queried. + */ + explicit TaskRecordsManagementStoredMessages( + const QString &urlStr, const QString &tokenStr, + enum Operation operation, const MessageDbSet *dbSet, + const QList &exludedDmIds = QList()); + + /*! + * @brief Performs actual message download. + */ + virtual + void run(void) Q_DECL_OVERRIDE; + + /*! + * @brief Returns task identifier. + * + * @return Task identifier string. + */ + const QString &id(void) const; + + enum Result m_result; /*!< Return state. */ + +private: + /*! + * @brief Download stored files information and save to records + * management database. + * + * @param[in] urlStr Records management URL. + * @param[in] tokenStr Records management access token. + * @param[in] operation Actual action to be performed. + * @param[in] dbSet Database set to be used to obtain message identifiers. + * @patam[in] exludedDmIds Message identifiers that should not be queried. + * @return Return state. + */ + static + enum Result downloadStoredMessages(const QString &urlStr, + const QString &tokenStr, enum Operation operation, + const MessageDbSet *dbSet, const QList &exludedDmIds); + + const QString m_id; /*!< Task identifier. */ + + const QString m_url; /*!< String containing records management URL. */ + const QString m_token; /*!< Records management access token. */ + + const enum Operation m_operation; /*!< Operation to be performed. */ + + const MessageDbSet *m_dbSet; /*!< Pointer to database container. */ + const QList m_exludedDmIds; /*!< + * List of messages that should + * not be queried. + */ +}; + +#endif /* _TASK_RECORDS_MANAGEMENT_STORED_MESSAGES_H_ */ diff -Nru datovka-4.8.3/src/worker/task_send_message.cpp datovka-4.9.3/src/worker/task_send_message.cpp --- datovka-4.8.3/src/worker/task_send_message.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_send_message.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +30,7 @@ #include "src/io/dbs.h" #include "src/io/isds_sessions.h" #include "src/log/log.h" -#include "src/models/accounts_model.h" +#include "src/settings/accounts.h" #include "src/worker/message_emitter.h" #include "src/worker/task_send_message.h" @@ -403,7 +403,7 @@ struct isds_message *message = libisdsMessage(m_message); if (NULL == message) { logErrorNL("Could not create isds_message for account '%s'.", - AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); + globAccounts[m_userName].accountName().toUtf8().constData()); return; } diff -Nru datovka-4.8.3/src/worker/task_send_message_mojeid.cpp datovka-4.9.3/src/worker/task_send_message_mojeid.cpp --- datovka-4.8.3/src/worker/task_send_message_mojeid.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_send_message_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#include - -#include "src/log/log.h" -#include "src/worker/message_emitter.h" -#include "src/worker/task_send_message_mojeid.h" - - -TaskSendMessageMojeId::TaskSendMessageMojeId(const QString &userName, - int accountID, const QList &recipientList, - const JsonLayer::Envelope &envelope, const QList &fileList) - : - m_userName(userName), - m_accountID(accountID), - m_recipientList(recipientList), - m_envelope(envelope), - m_fileList(fileList), - m_resultList(QStringList()), - m_error(QString()) -{ -} - - -void TaskSendMessageMojeId::run(void) -{ - logDebugLv0NL("Starting send message task in thread '%p'", - (void *) QThread::currentThreadId()); - - /* ### Worker task begin. ### */ - - sendMessage(m_userName, m_accountID, m_recipientList, m_envelope, - m_fileList, PL_SEND_MESSAGE, m_resultList, m_error); - - emit globMsgProcEmitter.sendMessageMojeIdFinished(m_userName, - m_resultList, m_error); - - emit globMsgProcEmitter.progressChange(PL_IDLE, 0); - - /* ### Worker task end. ### */ - - logDebugLv0NL("Send message task finished in thread '%p'", - (void *) QThread::currentThreadId()); -} - -enum TaskSendMessageMojeId::Result TaskSendMessageMojeId::sendMessage( - const QString &userName, - int accountID, const QList &recipientList, - const JsonLayer::Envelope &envelope, const QList &fileList, - const QString &progressLabel, QStringList &resultList, - QString &errStr) -{ - emit globMsgProcEmitter.progressChange(progressLabel, -1); - - jsonlayer.sendMessage(userName, accountID, recipientList, envelope, - fileList, resultList, errStr); - - emit globMsgProcEmitter.progressChange(progressLabel, 100); - - return SM_SUCCESS; -} diff -Nru datovka-4.8.3/src/worker/task_send_message_mojeid.h datovka-4.9.3/src/worker/task_send_message_mojeid.h --- datovka-4.8.3/src/worker/task_send_message_mojeid.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_send_message_mojeid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _TASK_SEND_MESSAGE_MOJEID_H_ -#define _TASK_SEND_MESSAGE_MOJEID_H_ - -#include -#include - -#include "src/worker/task.h" -#include "src/web/json.h" - -/*! - * @brief Task describing sending message. - */ -class TaskSendMessageMojeId : public Task { -public: - /*! - * @brief Return state describing what happened. - */ - enum Result { - SM_SUCCESS, /*!< Operation was successful. */ - SM_NET_ERROR, /*!< Error communicating with webdatovka. */ - SM_ERR /*!< Other error. */ - }; - - /*! - * @brief Constructor. - * - * @param[in] userName Account identifier (user login name). - * @param[in] accountID Account ID of webdatovka. - * @param[in] recipientList List of recipients. - * @param[in] envelope Envelope data. - * @param[in] fileList List of attachments. - */ - explicit TaskSendMessageMojeId(const QString &userName, - int accountID, const QList &recipientList, - const JsonLayer::Envelope &envelope, - const QList &fileList); - - /*! - * @brief Performs actual message sending. - */ - virtual - void run(void) Q_DECL_OVERRIDE; - -private: - /*! - * Disable copy and assignment. - */ - TaskSendMessageMojeId(const TaskSendMessageMojeId &); - TaskSendMessageMojeId &operator=(const TaskSendMessageMojeId &); - - /*! - * @brief Sends a single message to ISDS fro given account. - * - * @param[in] userName Account identifier (user login name). - * @param[in] accountID Account ID of webdatovka. - * @param[in] recipientList List of recipients. - * @param[in] envelope Envelope data. - * @param[in] fileList List of attachments. - * @param[in] progressLabel Progress-bar label. - * @param[out] resultList ResultList. - * @param[out] error Error message. - * @return Error state. - */ - static - enum Result sendMessage(const QString &userName, - int accountID, const QList &recipientList, - const JsonLayer::Envelope &envelope, - const QList &fileList, - const QString &progressLabel, - QStringList &resultList, - QString &error); - - const QString m_userName; /*!< Account identifier (user login name). */ - const int m_accountID; /*!< Account id of webdatovka. */ - const QList m_recipientList; /*!< List of recipients. */ - const JsonLayer::Envelope m_envelope; /*!< Envelope data. */ - const QList m_fileList; /*!< List of attachments. */ - QStringList m_resultList; /*!< ResultList. */ - QString m_error; -}; - -#endif /* _TASK_SEND_MESSAGE_MOJEID_H_ */ diff -Nru datovka-4.8.3/src/worker/task_sync_mojeid.cpp datovka-4.9.3/src/worker/task_sync_mojeid.cpp --- datovka-4.8.3/src/worker/task_sync_mojeid.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_sync_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#include - -#include "src/io/account_db.h" -#include "src/io/dbs.h" -#include "src/log/log.h" -#include "src/worker/message_emitter.h" -#include "src/worker/task_sync_mojeid.h" -#include "src/web/json.h" - -TaskSyncAccount::TaskSyncAccount(const QString &userName, int id) - : m_success(false), - m_isdsError(), - m_userName(userName), - m_id(id) -{ -} - -void TaskSyncAccount::run(void) -{ - logDebugLv0NL("Starting account sync in thread '%p'", - (void *) QThread::currentThreadId()); - - /* ### Worker task begin. ### */ - - m_success = syncAccount(m_userName, m_id, m_isdsError); - - emit globMsgProcEmitter.progressChange(PL_IDLE, 0); - - /* ### Worker task end. ### */ - - logDebugLv0NL("Account sync task finished in thread '%p'", - (void *) QThread::currentThreadId()); -} - -bool TaskSyncAccount::syncAccount(const QString &userName, int id, - QString &error) -{ - emit globMsgProcEmitter.progressChange(PL_SYNC_ACCOUNT, -1); - - return jsonlayer.syncAccount(userName, id, error); -} diff -Nru datovka-4.8.3/src/worker/task_sync_mojeid.h datovka-4.9.3/src/worker/task_sync_mojeid.h --- datovka-4.8.3/src/worker/task_sync_mojeid.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_sync_mojeid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _TASK_SYNC_MOJEID_H_ -#define _TASK_SYNC_MOJEID_H_ - -#include - -#include "src/worker/task.h" - -/*! - * @brief Task describing sync account information. - */ -class TaskSyncAccount : public Task { -public: - /*! - * @brief Constructor. - * - * @param[in] userName Account identifier (user login name) - * @param[in] id Account identifier. - */ - explicit TaskSyncAccount(const QString &userName, int id); - - /*! - * @brief Performs action. - */ - virtual - void run(void) Q_DECL_OVERRIDE; - - bool m_success; /*!< True on success. */ - QString m_isdsError; /*!< Error description. */ - -private: - /*! - * Disable copy and assignment. - */ - TaskSyncAccount(const TaskSyncAccount &); - TaskSyncAccount &operator=(const TaskSyncAccount &); - - /*! - * @brief Sync account. - * - * @param[in] userName Account identifier (user login name) - * @param[in] id Account identifier. - * @param[out] error Error description. - * @return True on success. - */ - static - bool syncAccount(const QString &userName, int id, QString &error); - - const QString m_userName; /*!< Account identifier (user login name). */ - int m_id; /*!< Account identifier. */ -}; - -#endif /* _TASK_SYNC_MOJEID_H_ */ diff -Nru datovka-4.8.3/src/worker/task_tag_sync_mojeid.cpp datovka-4.9.3/src/worker/task_tag_sync_mojeid.cpp --- datovka-4.8.3/src/worker/task_tag_sync_mojeid.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_tag_sync_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#include - -#include "src/log/log.h" -#include "src/worker/message_emitter.h" -#include "src/worker/task_tag_sync_mojeid.h" -#include "src/io/tag_db_container.h" -#include "src/web/json.h" - -TaskTagSyncAccount::TaskTagSyncAccount(const QString &userName) - : m_success(false), - m_error(), - m_userName(userName) -{ -} - -void TaskTagSyncAccount::run(void) -{ - logDebugLv0NL("Starting tag sync in thread '%p'", - (void *) QThread::currentThreadId()); - - /* ### Worker task begin. ### */ - - m_success = syncTagList(m_userName, m_error); - - emit globMsgProcEmitter.progressChange(PL_IDLE, 0); - - /* ### Worker task end. ### */ - - logDebugLv0NL("Tag sync task finished in thread '%p'", - (void *) QThread::currentThreadId()); -} - -bool TaskTagSyncAccount::syncTagList(const QString &userName, QString &error) -{ - emit globMsgProcEmitter.progressChange(PL_SYNC_ACCOUNT, -1); - - QList tagList; - - if (jsonlayer.getTagList(userName, tagList, error)) { - globWebDatovkaTagDbPtr->accessTagDb( - getWebDatovkaTagDbPrefix(userName))->deleteAllTags(); - foreach (const JsonLayer::Tag &tag, tagList) { - globWebDatovkaTagDbPtr->accessTagDb( - getWebDatovkaTagDbPrefix(userName))-> - insertUpdateWebDatovkaTag(tag.id, tag.name, - tag.color); - } - } - - return true; -} diff -Nru datovka-4.8.3/src/worker/task_tag_sync_mojeid.h datovka-4.9.3/src/worker/task_tag_sync_mojeid.h --- datovka-4.8.3/src/worker/task_tag_sync_mojeid.h 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_tag_sync_mojeid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _TASK_TAG_SYNC_MOJEID_H_ -#define _TASK_TAG_SYNC_MOJEID_H_ - -#include - -#include "src/worker/task.h" - -/*! - * @brief Task describing sync account information. - */ -class TaskTagSyncAccount : public Task { -public: - /*! - * @brief Constructor. - * - * @param[in] userName Account identifier (user login name) - */ - explicit TaskTagSyncAccount(const QString &userName); - - /*! - * @brief Performs action. - */ - virtual - void run(void) Q_DECL_OVERRIDE; - - bool m_success; /*!< True on success. */ - QString m_error; /*!< Error description. */ - -private: - /*! - * Disable copy and assignment. - */ - TaskTagSyncAccount(const TaskTagSyncAccount &); - TaskTagSyncAccount &operator=(const TaskTagSyncAccount &); - - /*! - * @brief Sync account. - * - * @param[in] userName Account identifier (user login name) - * @param[out] error Error description. - * @return True on success. - */ - static - bool syncTagList(const QString &userName, QString &error); - - const QString m_userName; /*!< Account identifier (user login name). */ -}; - -#endif /* _TASK_TAG_SYNC_MOJEID_H_ */ diff -Nru datovka-4.8.3/src/worker/task_verify_message.cpp datovka-4.9.3/src/worker/task_verify_message.cpp --- datovka-4.8.3/src/worker/task_verify_message.cpp 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/src/worker/task_verify_message.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2017 CZ.NIC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +28,7 @@ #include "src/io/isds_sessions.h" #include "src/io/message_db.h" +#include "src/isds/isds_conversion.h" #include "src/log/log.h" #include "src/worker/message_emitter.h" #include "src/worker/task_verify_message.h" @@ -114,7 +115,7 @@ QByteArray rawHash = QByteArray::fromBase64(hashLocaldata.valueBase64); hashLocal->length = (size_t) rawHash.size(); - hashLocal->algorithm = (isds_hash_algorithm) convertHashAlg2( + hashLocal->algorithm = (isds_hash_algorithm) IsdsConversion::hashAlgStrToInt( hashLocaldata.alg); hashLocal->value = malloc(hashLocal->length); if (NULL == hashLocal->value) { diff -Nru datovka-4.8.3/tests/cli/getmsg.sh datovka-4.9.3/tests/cli/getmsg.sh --- datovka-4.8.3/tests/cli/getmsg.sh 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/tests/cli/getmsg.sh 2017-09-06 11:49:23.000000000 +0000 @@ -386,6 +386,42 @@ fi done +echo "***********************************************************************" +echo "* GET MSG ID LIST FROM DB:: Get all received message IDs (via all accounts)." +echo "***********************************************************************" +for login in $USERNAMES; do + "${SCRIPTPATH}/${APP_BINARY_NAME}" ${CMDARGS} \ + --login "username='$login'" \ + --get-msg-ids "dmType='received'" \ + 2>/dev/null + if [ 0 != $? ]; then + echo "GetMsgIDs-received: $login - ERROR" + echo "" + exit + else + echo "GetMsgIDs-received: $login - OK" + echo "" + fi +done + +echo "***********************************************************************" +echo "* GET MSG ID LIST FROM DB:: Get all sent message IDs (via all accounts)." +echo "***********************************************************************" +for login in $USERNAMES; do + "${SCRIPTPATH}/${APP_BINARY_NAME}" ${CMDARGS} \ + --login "username='$login'" \ + --get-msg-ids "dmType='sent'" \ + 2>/dev/null + if [ 0 != $? ]; then + echo "GetMsgIDs-sent: $login - ERROR" + echo "" + exit + else + echo "GetMsgIDs-sent: $login - OK" + echo "" + fi +done + echo "" echo "" echo "------------------------------------------------------------------------" diff -Nru datovka-4.8.3/tests/records_management_app/build_rm_test_app.bat datovka-4.9.3/tests/records_management_app/build_rm_test_app.bat --- datovka-4.8.3/tests/records_management_app/build_rm_test_app.bat 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/build_rm_test_app.bat 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,26 @@ + +REM Ensure that path to Qt (C:\Qt\5.9.1\mingw53_32\bin) is set. +REM Ensure that path to MinGW tools bundled with Qt (C:\Qt\Tools\mingw530_32\bin) is set. + +SET APP_DIR="rm_test_app" + +SET QMAKE="qmake.exe" +SET MINGW_PATH="C:\Qt\Tools\mingw530_32" +SET MAKE="mingw32-make.exe" +SET DEPLOYQT="windeployqt.exe" + +rmdir /S /Q debug +rmdir /S /Q release +rmdir /S /Q %APP_DIR% + +SET CONF="release" + +%QMAKE% CONFIG+=%CONF% rm_test_app.pro +%MAKE% -j 4 + +mkdir "%APP_DIR%" +copy "%CONF%\rm_test_app.exe" "%APP_DIR%" +copy "%MINGW_PATH%\opt\bin\libeay32.dll" "%APP_DIR%" +copy "%MINGW_PATH%\opt\bin\ssleay32.dll" "%APP_DIR%" +copy rm_test_app.bat "%APP_DIR%" +%DEPLOYQT% --dir "%APP_DIR%" --%CONF% "%APP_DIR%\rm_test_app.exe" diff -Nru datovka-4.8.3/tests/records_management_app/gui/app.cpp datovka-4.9.3/tests/records_management_app/gui/app.cpp --- datovka-4.8.3/tests/records_management_app/gui/app.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/gui/app.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include +#include +#include +#include // qVersion + +#include "src/records_management/json/helper.h" +#include "src/records_management/json/service_info.h" +#include "src/records_management/json/stored_files.h" +#include "src/records_management/json/upload_file.h" +#include "tests/records_management_app/json/documents.h" +#include "tests/records_management_app/gui/app.h" +#include "tests/records_management_app/gui/dialogue_service_info.h" +#include "tests/records_management_app/gui/dialogue_stored_files.h" + +#define SVG_PATH "datovka.svg" + +const QString blankFilterEditStyle("QLineEdit{background: white;}"); +const QString foundFilterEditStyle("QLineEdit{background: #afffaf;}"); +const QString notFoundFilterEditStyle("QLineEdit{background: #ffafaf;}"); + +/*! + * @brief Return . + */ +static +const QPalette &disableEditPalette(void) +{ + static QPalette palette; + static bool prepared = false; + if (!prepared) { + palette.setColor(QPalette::Base, Qt::lightGray); + palette.setColor(QPalette::Text, Qt::darkGray); + prepared = true; + } + return palette; +} + +MainWindow::MainWindow(const QString &baseUrl, const QString &token, + const QString &caCertPath, bool ignoreSslErrors) + : QMainWindow(), + m_uploadModel(this), + m_uploadProxyModel(this), + m_rmc(ignoreSslErrors, this) +{ + setupUi(this); + + ui_baseUrlLine->setText(baseUrl); + ui_baseUrlLine->setReadOnly(true); + ui_baseUrlLine->setPalette(disableEditPalette()); + ui_tokenLine->setText(token); + ui_tokenLine->setReadOnly(true); + ui_tokenLine->setPalette(disableEditPalette()); + + ui_filterLine->setClearButtonEnabled(true); + connect(ui_filterLine, SIGNAL(textChanged(QString)), + this, SLOT(filterHierarchy(QString))); + + ui_treeView->setModel(&m_uploadProxyModel); + m_uploadProxyModel.setSourceModel(&m_uploadModel); + connect(ui_treeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(uploadHierarchySelectionChanged(QItemSelection, QItemSelection))); + + ui_treeView->sortByColumn(0, Qt::AscendingOrder); + ui_treeView->setSortingEnabled(true); + + ui_vSplitter->setCollapsible(0, false); + ui_vSplitter->setCollapsible(1, false); + + ui_textEdit->setReadOnly(true); + + connectTopMenuBarActions(); + initialiseActions(); + + m_rmc.setConnection(ui_baseUrlLine->text(), ui_tokenLine->text()); + + connect(&m_rmc, SIGNAL(connectionError(QString)), + this, SLOT(writeMessage(QString))); + + /* Add CA certificate. */ + if (!caCertPath.isEmpty()) { + RecordsManagementConnection::addTrustedCertificate(caCertPath); + } +} + +void MainWindow::filterHierarchy(const QString &text) +{ + m_uploadProxyModel.setFilterRole(UploadHierarchyModel::ROLE_FILTER); + + m_uploadProxyModel.setFilterRegExp(QRegExp(text, + Qt::CaseInsensitive, QRegExp::FixedString)); + + m_uploadProxyModel.setFilterKeyColumn(0); + + ui_treeView->expandAll(); + + if (text.isEmpty()) { + ui_filterLine->setStyleSheet(blankFilterEditStyle); + } else if (m_uploadProxyModel.rowCount() != 0) { + ui_filterLine->setStyleSheet(foundFilterEditStyle); + } else { + ui_filterLine->setStyleSheet(notFoundFilterEditStyle); + } +} + +void MainWindow::callSrvcServiceInfo(void) +{ + ui_textEdit->clear(); + + QByteArray response; + if (m_rmc.communicate(RecordsManagementConnection::SRVC_SERVICE_INFO, + QByteArray(), response)) { + if (!response.isEmpty()) { + bool ok = false; + ServiceInfoResp siRes( + ServiceInfoResp::fromJson(response, &ok)); + ui_textEdit->append(JsonHelper::toIndentedString(response)); + if (!ok || !siRes.isValid()) { + QMessageBox::critical(this, + tr("Communication Error"), + tr("Received invalid response.")); + return; + } + + /* Show dialogue. */ + DialogueServiceInfo dlg(siRes, qobject_cast(this)); + dlg.exec(); + } else { + ui_textEdit->append(QStringLiteral("Empty response.")); + QMessageBox::critical(this, tr("Communication Error"), + tr("Received empty response.")); + return; + } + } else { + ui_textEdit->append(QStringLiteral("Service call failed.")); + QMessageBox::critical(this, tr("Communication Error"), + tr("Service failed.")); + return; + } +} + +void MainWindow::callSrvcUploadHierarchy(void) +{ + ui_textEdit->clear(); + m_uploadModel.setHierarchy(UploadHierarchyResp()); + + if (ui_baseUrlLine->text().isEmpty()) { + /* No service URL available. */ + QMessageBox::warning(this, tr("No URL Available"), + tr("Using dummy response.")); + bool ok = false; + UploadHierarchyResp uhRes( + UploadHierarchyResp::fromJson(uhResDoc, &ok)); + ui_textEdit->append(JsonHelper::toIndentedString(uhResDoc)); + if (!ok || !uhRes.isValid()) { + QMessageBox::critical(this, tr("Communication Error"), + tr("Invalid dummy response.")); + return; + } + + m_uploadModel.setHierarchy(uhRes); + ui_treeView->expandAll(); + return; + } + + QByteArray response; + if (m_rmc.communicate(RecordsManagementConnection::SRVC_UPLOAD_HIERARCHY, + QByteArray(), response)) { + if (!response.isEmpty()) { + bool ok = false; + UploadHierarchyResp uhRes( + UploadHierarchyResp::fromJson(response, &ok)); + ui_textEdit->append(JsonHelper::toIndentedString(response)); + if (!ok || !uhRes.isValid()) { + QMessageBox::critical(this, + tr("Communication Error"), + tr("Received invalid response.")); + return; + } + + m_uploadModel.setHierarchy(uhRes); + ui_treeView->expandAll(); + } else { + ui_textEdit->append(QStringLiteral("Empty response.")); + QMessageBox::critical(this, tr("Communication Error"), + tr("Received empty response.")); + return; + } + } else { + ui_textEdit->append(QStringLiteral("Service call failed.")); + QMessageBox::critical(this, tr("Communication Error"), + tr("Service failed.")); + return; + } +} + +/*! + * @brief Read file content. + * + * @param[in] path File path. + * @param[out] name File name. + * @param[out] data File content. + * @return True if file could be read. + */ +static +bool readFileContent(const QString &path, QString &name, QByteArray &data) +{ + if (path.isEmpty()) { + return false; + } + + { + QFile file(path); + if (!file.open(QIODevice::ReadOnly)) { + return false; + } + + data = file.readAll(); + file.close(); + } + + name = QFileInfo(path).fileName(); + + return true; +} + +void MainWindow::callSrvcUploadFile(void) +{ + ui_textEdit->clear(); + + /* Create upload file request. */ + QStringList idList; + foreach (const QModelIndex &index, ui_treeView->selectionModel()->selectedIndexes()) { + const QString idStr(index.data(UploadHierarchyModel::ROLE_ID).toString()); + if (!idStr.isEmpty()) { + idList.append(idStr); + } else { + Q_ASSERT(0); + } + } + + if (idList.isEmpty()) { + ui_textEdit->append(QStringLiteral("No valid places are selected.")); + return; + } + + QString filePath(QFileDialog::getOpenFileName(this, + QStringLiteral("Open File"), QString(), + QStringLiteral("ZFO file (*.zfo)"))); + if (filePath.isEmpty()) { + return; + } + + QString fileName; + QByteArray fileContent; + if (!readFileContent(filePath, fileName, fileContent)) { + ui_textEdit->append(QStringLiteral("Could not read file content.")); + return; + } + + UploadFileReq ufreq(idList, fileName, fileContent); + if (!ufreq.isValid()) { + ui_textEdit->append(QStringLiteral("Could not create upload file request.")); + return; + } + + ui_textEdit->append(ufreq.toJson()); + + QByteArray response; + if (m_rmc.communicate(RecordsManagementConnection::SRVC_UPLOAD_FILE, + ufreq.toJson(), response)) { + if (!response.isEmpty()) { + bool ok = false; + UploadFileResp ufRes( + UploadFileResp::fromJson(response, &ok)); + ui_textEdit->append(JsonHelper::toIndentedString(response)); + if (!ok || !ufRes.isValid()) { + QMessageBox::critical(this, + tr("Communication Error"), + tr("Received invalid response.")); + return; + } + + } else { + ui_textEdit->append(QStringLiteral("Empty response.")); + QMessageBox::critical(this, tr("Communication Error"), + tr("Received empty response.")); + return; + } + } else { + ui_textEdit->append(QStringLiteral("Service call failed.")); + QMessageBox::critical(this, tr("Communication Error"), + tr("Service failed.")); + return; + } +} + +void MainWindow::callSrvcStoredFiles(void) +{ + ui_textEdit->clear(); + + DialogueStoredFiles::Values ids(DialogueStoredFiles::getIdentifiers()); + if (ids.dmIds.isEmpty() && ids.diIds.isEmpty()) { + ui_textEdit->append(QStringLiteral("No input.")); + return; + } + + StoredFilesReq sfreq(ids.dmIds, ids.diIds); + if (!sfreq.isValid()) { + ui_textEdit->append( + QStringLiteral("Could not create stored files request.")); + return; + } + + ui_textEdit->append(sfreq.toJson()); + + QByteArray response; + if (m_rmc.communicate(RecordsManagementConnection::SRVC_STORED_FILES, + sfreq.toJson(), response)) { + if (!response.isEmpty()) { + bool ok = false; + StoredFilesResp sfRes( + StoredFilesResp::fromJson(response, &ok)); + ui_textEdit->append(JsonHelper::toIndentedString(response)); + if (!ok || !sfRes.isValid()) { + QMessageBox::critical(this, + tr("Communication Error"), + tr("Received invalid response.")); + return; + } + + } else { + ui_textEdit->append(QStringLiteral("Empty response.")); + QMessageBox::critical(this, tr("Communication Error"), + tr("Received empty response.")); + return; + } + } else { + ui_textEdit->append(QStringLiteral("Service call failed.")); + QMessageBox::critical(this, tr("Communication Error"), + tr("Service failed.")); + return; + } +} + +void MainWindow::callAbout(void) +{ + QMessageBox::about(this, QStringLiteral("About Application"), + QStringLiteral("Testing Application") + QStringLiteral("\n") + + QStringLiteral("App Version") + QStringLiteral(": ") + VERSION + + QStringLiteral("\n") + + QStringLiteral("Qt Version") + QStringLiteral(": ") + qVersion() + + QStringLiteral("\n") + + QStringLiteral("Copyright CZ.NIC, z. s. p. o.")); +} + +void MainWindow::uploadHierarchySelectionChanged(const QItemSelection &selected, + const QItemSelection &deselected) +{ + Q_UNUSED(selected) + Q_UNUSED(deselected) + + const QModelIndexList indexes(ui_treeView->selectionModel()->selectedIndexes()); + + ui_actionUploadFile->setEnabled(!indexes.isEmpty()); + + /* Entries with empty identifiers should not be able to be selected. */ + foreach (const QModelIndex &index, indexes) { + if (index.data(UploadHierarchyModel::ROLE_ID).toString().isEmpty()) { + Q_ASSERT(0); + } + } +} + +void MainWindow::writeMessage(const QString &message) +{ + ui_textEdit->append(QStringLiteral("Network error: ") + message); +} + +void MainWindow::connectTopMenuBarActions(void) +{ + /* File menu. */ + connect(ui_actionQuit, SIGNAL(triggered()), this, SLOT(close())); + + /* Service menu. */ + connect(ui_actionServiceInfo, SIGNAL(triggered()), + this, SLOT(callSrvcServiceInfo())); + connect(ui_actionUploadHierarchy, SIGNAL(triggered()), + this, SLOT(callSrvcUploadHierarchy())); + connect(ui_actionUploadFile, SIGNAL(triggered()), + this, SLOT(callSrvcUploadFile())); + connect(ui_actionStoredFiles, SIGNAL(triggered()), + this, SLOT(callSrvcStoredFiles())); + + /* Help menu. */ + connect(ui_actionAbout, SIGNAL(triggered()), this, SLOT(callAbout())); +} + +void MainWindow::initialiseActions(void) +{ + ui_actionServiceInfo->setEnabled(true); + ui_actionUploadHierarchy->setEnabled(true); + ui_actionUploadFile->setEnabled(false); + ui_actionStoredFiles->setEnabled(true); +} diff -Nru datovka-4.8.3/tests/records_management_app/gui/app.h datovka-4.9.3/tests/records_management_app/gui/app.h --- datovka-4.8.3/tests/records_management_app/gui/app.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/gui/app.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#pragma once + +#include +#include + +#include "src/records_management/io/records_management_connection.h" +#include "src/records_management/models/upload_hierarchy_model.h" +#include "src/records_management/models/upload_hierarchy_proxy_model.h" +#include "ui_app.h" + +/*! + * @brief Main window for testing. + */ +class MainWindow : public QMainWindow, public Ui::MainWindow { + Q_OBJECT +public: + MainWindow(const QString &baseUrl, const QString &token, + const QString &caCertPath, bool ignoreSslErrors); + +private slots: + void filterHierarchy(const QString &text); + + void callSrvcServiceInfo(void); + + void callSrvcUploadHierarchy(void); + + void callSrvcUploadFile(void); + + void callSrvcStoredFiles(void); + + void callAbout(void); + + /*! + * @brief Enables upload file operation. + */ + void uploadHierarchySelectionChanged(const QItemSelection &selected, + const QItemSelection &deselected); + + /*! + * @brief Adds message into text output field. + */ + void writeMessage(const QString &message); + +private: + /*! + * @brief Connect top menu entries to appropriate actions. + */ + void connectTopMenuBarActions(void); + + /*! + * @brief Initialises actions. + */ + void initialiseActions(void); + + UploadHierarchyModel m_uploadModel; + UploadHierarchyProxyModel m_uploadProxyModel; + + RecordsManagementConnection m_rmc; /*!< Connection to records management service. */ +}; diff -Nru datovka-4.8.3/tests/records_management_app/gui/dialogue_service_info.cpp datovka-4.9.3/tests/records_management_app/gui/dialogue_service_info.cpp --- datovka-4.8.3/tests/records_management_app/gui/dialogue_service_info.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/gui/dialogue_service_info.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +//#include +#include + +#include "tests/records_management_app/gui/dialogue_service_info.h" +#include "ui_dialogue_service_info.h" + +DialogueServiceInfo::DialogueServiceInfo(const ServiceInfoResp &sir, + QWidget *parent) + : QDialog(parent), + m_ui(new Ui::DialogueServiceInfo) +{ + m_ui->setupUi(this); + + setWindowTitle("Service Info Response"); + + m_ui->graphicsView->resize(100, m_ui->graphicsView->height()); + + m_ui->nameLine->setText(sir.name()); + m_ui->nameLine->setReadOnly(true); + m_ui->tokenNameLine->setText(sir.tokenName()); + m_ui->tokenNameLine->setReadOnly(true); + + setupGraphicsView(); + loadSvg(sir.logoSvg()); +} + +DialogueServiceInfo::~DialogueServiceInfo(void) +{ + delete m_ui; +} + +void DialogueServiceInfo::setupGraphicsView(void) +{ + QGraphicsView *gv = m_ui->graphicsView; + + gv->setScene(new (std::nothrow) QGraphicsScene(this)); + gv->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); + gv->setDragMode(QGraphicsView::ScrollHandDrag); + gv->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + + // Prepare background check-board pattern + QPixmap tilePixmap(64, 64); + tilePixmap.fill(Qt::white); + QPainter tilePainter(&tilePixmap); + QColor color(220, 220, 220); + tilePainter.fillRect(0, 0, 32, 32, color); + tilePainter.fillRect(32, 32, 32, 32, color); + tilePainter.end(); + + gv->setBackgroundBrush(tilePixmap); +} + +void DialogueServiceInfo::loadSvg(const QByteArray &svgData) +{ + if (svgData.isEmpty()) { + return; + } + + QGraphicsView *gv = m_ui->graphicsView; + QGraphicsScene *s = m_ui->graphicsView->scene(); + + QGraphicsSvgItem *svgItem = new (std::nothrow) QGraphicsSvgItem(); + { + QSvgRenderer *svgRenderer = new (std::nothrow) QSvgRenderer(svgData, this); + svgItem->setSharedRenderer(svgRenderer); + } + + s->clear(); + gv->resetTransform(); + + svgItem->setFlags(QGraphicsItem::ItemClipsToShape); + svgItem->setCacheMode(QGraphicsItem::NoCache); + svgItem->setZValue(0); + + QGraphicsRectItem *backgroundItem = new (std::nothrow) QGraphicsRectItem(svgItem->boundingRect()); + backgroundItem->setBrush(Qt::white); + backgroundItem->setPen(Qt::NoPen); + backgroundItem->setVisible(false); + backgroundItem->setZValue(-1); + + s->addItem(backgroundItem); + s->addItem(svgItem); +} diff -Nru datovka-4.8.3/tests/records_management_app/gui/dialogue_service_info.h datovka-4.9.3/tests/records_management_app/gui/dialogue_service_info.h --- datovka-4.8.3/tests/records_management_app/gui/dialogue_service_info.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/gui/dialogue_service_info.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#pragma once + +#include + +#include "src/records_management/json/service_info.h" + +namespace Ui { + class DialogueServiceInfo; +} + +class DialogueServiceInfo : public QDialog { + Q_OBJECT + +public: + /*! + * @brief Dialogue constructor. + */ + explicit DialogueServiceInfo(const ServiceInfoResp &sir, + QWidget *parent = Q_NULLPTR); + + ~DialogueServiceInfo(void); + +private: + void setupGraphicsView(void); + + void loadSvg(const QByteArray &svgData); + + Ui::DialogueServiceInfo *m_ui; +}; diff -Nru datovka-4.8.3/tests/records_management_app/gui/dialogue_stored_files.cpp datovka-4.9.3/tests/records_management_app/gui/dialogue_stored_files.cpp --- datovka-4.8.3/tests/records_management_app/gui/dialogue_stored_files.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/gui/dialogue_stored_files.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include // std::numeric_limits +#include +#include +#include // qrand +#include + +#include "src/records_management/conversion.h" +#include "tests/records_management_app/gui/dialogue_stored_files.h" +#include "ui_dialogue_stored_files.h" + +DialogueStoredFiles::DialogueStoredFiles(QWidget *parent) + : QDialog(parent), + m_ui(new Ui::DialogueStoredFiles) +{ + m_ui->setupUi(this); + + setWindowTitle("Stored Files Request"); + + connect(m_ui->dmButton, SIGNAL(clicked(bool)), + this, SLOT(generateDmIds())); + connect(m_ui->diButton, SIGNAL(clicked(bool)), + this, SLOT(generateDiIds())); +} + +DialogueStoredFiles::~DialogueStoredFiles(void) +{ + delete m_ui; +} + +/*! + * @brief Split string and convert to integers. + * + * @param[in] str String to be split. + * @param[in] sep Separator to be used for splitting. + * @param[out] ok Set to true, if all values have been converted. + * @return Empty list on error, list of numbers else. + */ +static +QList readIdentifiers(const QString &str, QChar sep, bool *ok) +{ + if (str.isEmpty()) { + if (ok != Q_NULLPTR) { + *ok = true; + } + return QList(); + } + + QStringList strIds(str.split(sep)); + QList ids(createIdList(strIds, Q_NULLPTR)); + if (ids.size() != strIds.size()) { + if (ok != Q_NULLPTR) { + *ok = false; + } + return QList(); + } + + if (ok != Q_NULLPTR) { + *ok = true; + } + return ids; +} + +#define SEPARATOR ',' + +DialogueStoredFiles::Values DialogueStoredFiles::getIdentifiers(void) +{ + Values retVal; + + DialogueStoredFiles dlg; + int ret = dlg.exec(); + if (ret == QDialog::Rejected) { + return Values(); + } + + /* Read dialogue content. */ + bool ok = false; + retVal.dmIds = readIdentifiers(dlg.m_ui->dmLine->text(), SEPARATOR, &ok); + if (!ok) { + QMessageBox::warning(&dlg, QStringLiteral("Conversion Error"), + QStringLiteral("Could not convert all data message identifiers to non-negative numbers.")); + return Values(); + } + retVal.diIds = readIdentifiers(dlg.m_ui->diLine->text(), SEPARATOR, &ok); + if (!ok) { + QMessageBox::warning(&dlg, QStringLiteral("Conversion Error"), + QStringLiteral("Could not convert all delivery info identifiers to non-negative numbers.")); + return Values(); + } + + return retVal; +} + +/*! + * @brief Asks the user for a number. + * + * @param[in] parent Parent widget. + * @return Non-negative integer, or negative integer on error. + */ +static +int askNumberOfIdentifiers(QWidget *parent) +{ + return QInputDialog::getInt(parent, + QStringLiteral("Number of Identifiers"), + QStringLiteral("Enter number of identifiers that should be generated:"), + 0, 0, std::numeric_limits::max(), 1); +} + +/*! + * @brief Fill random identifiers into line edit. + * + * @param[in] parent Parent widget. + * @param[out] lineEdit Line edit to be filled. + */ +static +void generateIdentifiers(QWidget *parent, QLineEdit &lineEdit) +{ + int num = askNumberOfIdentifiers(parent); + if (num < 0) { + Q_ASSERT(0); + return; + } + + qsrand((uint)QTime::currentTime().msec()); + QStringList strIds; + for (int i = 0; i < num; ++i) { + strIds.append(QString::number(qrand())); + } + + lineEdit.setText(strIds.join(SEPARATOR)); +} + +void DialogueStoredFiles::generateDmIds(void) +{ + generateIdentifiers(this, *m_ui->dmLine); +} + +void DialogueStoredFiles::generateDiIds(void) +{ + generateIdentifiers(this, *m_ui->diLine); +} diff -Nru datovka-4.8.3/tests/records_management_app/gui/dialogue_stored_files.h datovka-4.9.3/tests/records_management_app/gui/dialogue_stored_files.h --- datovka-4.8.3/tests/records_management_app/gui/dialogue_stored_files.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/gui/dialogue_stored_files.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#pragma once + +#include + +class QLineEdit; /*!< Forward declaration. */ + +namespace Ui { + class DialogueStoredFiles; +} + +class DialogueStoredFiles : public QDialog { + Q_OBJECT + +public: + /*! + * @brief Dialogue return value. + */ + class Values { + public: + Values(void) : dmIds(), diIds() + { + } + + QList dmIds; /*!< Message identifiers. */ + QList diIds; /*!< Delivery info identifiers. */ + }; + +private: + /*! + * @brief Dialogue constructor. + */ + explicit DialogueStoredFiles(QWidget *parent = Q_NULLPTR); + + ~DialogueStoredFiles(void); + +public: + /*! + * @brief Invokes the dialogue. + */ + static + Values getIdentifiers(void); + +private slots: + void generateDmIds(void); + + void generateDiIds(void); + +private: + Ui::DialogueStoredFiles *m_ui; +}; diff -Nru datovka-4.8.3/tests/records_management_app/json/documents.cpp datovka-4.9.3/tests/records_management_app/json/documents.cpp --- datovka-4.8.3/tests/records_management_app/json/documents.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/json/documents.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include "tests/records_management_app/json/documents.h" + +const QByteArray uhResDoc( +"{ \"name\": null, \"id\": null, \"metadata\": [\"root\"], \"sub\":" +" [" +" { \"name\": \"NIX.CZ\", \"id\": null, \"metadata\": [\"Neutral Internet eXchange\", \"propojení sítí\", \"peeringový uzel\"], \"sub\":" +" [" +" { \"name\": \"obecné\", \"id\": \"af51ef52yx\", \"metadata\": [\"povšechné záležitosti\"], \"sub\": [] }," +" { \"name\": \"FENIX\", \"id\": \"af51ef52yz\", \"metadata\": [\"reakce na DoS\"], \"sub\": [] }" +" ]" +" }," +" { \"name\": \"CZ.NIC\", \"id\": null, \"metadata\": [\"Network Information Centre\", \"Domain Name Registry\", \"provozovatel domény .cz\"], \"sub\":" +" [" +" { \"name\": \"obecné\", \"id\": \"aabbccddee\", \"metadata\": [\"povšechné záležitosti\"], \"sub\": [] }," +" { \"name\": \"Datovka\", \"id\": \"aabbccddef\", \"metadata\": [\"datové schránky\", \"ISDS\"], \"sub\": [] }," +" { \"name\": \"Tablexia\", \"id\": \"aabbccddf0\", \"metadata\": [\"hry\", \"dyslexie\"], \"sub\": [] }," +" { \"name\": \"Knot DNS\", \"id\": \"aabbccddf1\", \"metadata\": [\"authoritative name server\"], \"sub\": [] }," +" { \"name\": \"Knot Resolver\", \"id\": \"aabbccddf2\", \"metadata\": [\"recursive name server\"], \"sub\": [] }" +" ]" +" }" +" ]" +"}" +); diff -Nru datovka-4.8.3/tests/records_management_app/json/documents.h datovka-4.9.3/tests/records_management_app/json/documents.h --- datovka-4.8.3/tests/records_management_app/json/documents.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/json/documents.h 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +/*! Upload hierarchy response JSON document. */ +extern const QByteArray uhResDoc; diff -Nru datovka-4.8.3/tests/records_management_app/main.cpp datovka-4.9.3/tests/records_management_app/main.cpp --- datovka-4.8.3/tests/records_management_app/main.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/main.cpp 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2014-2017 CZ.NIC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include + +#include "tests/records_management_app/gui/app.h" + +#define BASE_URL_OPT "base-url" +#define TOKEN_OPT "token" +#define CA_CERT_OPT "ca-cert" +#define IGNORE_SSL_ERRORS "ignore-ssl-errors" + +static +int setupCmdLineParser(QCommandLineParser &parser) +{ + parser.setApplicationDescription(QObject::tr("Experimental application")); + parser.addHelpOption(); + parser.addVersionOption(); + + if (!parser.addOption(QCommandLineOption(BASE_URL_OPT, + "Use for service base URL.", "url"))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(TOKEN_OPT, + "Use to use to connect to service.", "token-string"))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(CA_CERT_OPT, + "Use as trusted certificate to validate SSL connection.", "cert-file"))) { + return -1; + } + if (!parser.addOption(QCommandLineOption(IGNORE_SSL_ERRORS, + "Set this option to ignore SSL connection errors."))) { + return -1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QCoreApplication::setApplicationName("ds_test_app"); + QCoreApplication::setApplicationVersion(VERSION); + + QCommandLineParser parser; + if (0 != setupCmdLineParser(parser)) { + qCritical("%s", "Cannot set up command-line parser."); + return EXIT_FAILURE; + } + + /* Process command-line arguments. */ + parser.process(app); + + MainWindow mainWin( + parser.isSet(BASE_URL_OPT) ? parser.value(BASE_URL_OPT) : QString(), + parser.isSet(TOKEN_OPT) ? parser.value(TOKEN_OPT) : QString(), + parser.isSet(CA_CERT_OPT) ? parser.value(CA_CERT_OPT) : QString(), + parser.isSet(IGNORE_SSL_ERRORS)); + mainWin.show(); + return app.exec(); +} diff -Nru datovka-4.8.3/tests/records_management_app/rm_test_app.bat datovka-4.9.3/tests/records_management_app/rm_test_app.bat --- datovka-4.8.3/tests/records_management_app/rm_test_app.bat 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/rm_test_app.bat 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,6 @@ + +SET BINARY="rm_test_app.exe" +SET URL="" +SET TOKEN="" + +"%BINARY%" --base-url "%URL%" --token "%TOKEN%" diff -Nru datovka-4.8.3/tests/records_management_app/rm_test_app.pro datovka-4.9.3/tests/records_management_app/rm_test_app.pro --- datovka-4.8.3/tests/records_management_app/rm_test_app.pro 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/rm_test_app.pro 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,69 @@ + +QT += core network +QT += gui svg widgets + +top_srcdir = ../.. + +TEMPLATE = app +APP_NAME = ds_test_app + +include($${top_srcdir}/pri/version.pri) +include($${top_srcdir}/pri/check_qt_version.pri) + +sufficientQtVersion(5, 2, 3, 2) + +DEFINES += \ + DEBUG=1 \ + VERSION=\\\"$${VERSION}\\\" + +QMAKE_CXXFLAGS = \ + -g -O0 -std=c++11 \ + -Wall -Wextra -pedantic \ + -Wdate-time -Wformat -Werror=format-security + +INCLUDEPATH += \ + $${top_srcdir} + +SOURCES += \ + $${top_srcdir}/src/localisation/localisation.cpp \ + $${top_srcdir}/src/records_management/conversion.cpp \ + $${top_srcdir}/src/records_management/io/records_management_connection.cpp \ + $${top_srcdir}/src/records_management/json/entry_error.cpp \ + $${top_srcdir}/src/records_management/json/helper.cpp \ + $${top_srcdir}/src/records_management/json/service_info.cpp \ + $${top_srcdir}/src/records_management/json/stored_files.cpp \ + $${top_srcdir}/src/records_management/json/upload_file.cpp \ + $${top_srcdir}/src/records_management/json/upload_hierarchy.cpp \ + $${top_srcdir}/src/records_management/models/upload_hierarchy_model.cpp \ + $${top_srcdir}/src/records_management/models/upload_hierarchy_proxy_model.cpp \ + $${top_srcdir}/tests/records_management_app/gui/app.cpp \ + $${top_srcdir}/tests/records_management_app/gui/dialogue_service_info.cpp \ + $${top_srcdir}/tests/records_management_app/gui/dialogue_stored_files.cpp \ + $${top_srcdir}/tests/records_management_app/json/documents.cpp \ + main.cpp + +HEADERS += \ + $${top_srcdir}/src/localisation/localisation.h \ + $${top_srcdir}/src/records_management/conversion.h \ + $${top_srcdir}/src/records_management/io/records_management_connection.h \ + $${top_srcdir}/src/records_management/json/entry_error.h \ + $${top_srcdir}/src/records_management/json/helper.h \ + $${top_srcdir}/src/records_management/json/service_info.h \ + $${top_srcdir}/src/records_management/json/stored_files.h \ + $${top_srcdir}/src/records_management/json/upload_file.h \ + $${top_srcdir}/src/records_management/json/upload_hierarchy.h \ + $${top_srcdir}/src/records_management/models/upload_hierarchy_model.h \ + $${top_srcdir}/src/records_management/models/upload_hierarchy_proxy_model.h \ + $${top_srcdir}/tests/records_management_app/gui/app.h \ + $${top_srcdir}/tests/records_management_app/gui/dialogue_service_info.h \ + $${top_srcdir}/tests/records_management_app/gui/dialogue_stored_files.h \ + $${top_srcdir}/tests/records_management_app/json/documents.h + +FORMS += \ + $${top_srcdir}/tests/records_management_app/ui/app.ui \ + $${top_srcdir}/tests/records_management_app/ui/dialogue_service_info.ui \ + $${top_srcdir}/tests/records_management_app/ui/dialogue_stored_files.ui + +RESOURCES += +TRANSLATIONS += +OTHER_FILES += diff -Nru datovka-4.8.3/tests/records_management_app/rm_test_app.sh datovka-4.9.3/tests/records_management_app/rm_test_app.sh --- datovka-4.8.3/tests/records_management_app/rm_test_app.sh 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/rm_test_app.sh 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,10 @@ +#!/usr/bin/env sh + +SCRIPT=$(readlink -f "$0") +SCRIPTPATH=$(dirname "${SCRIPT}") + +BINARY="rm_test_app" +URL="" +TOKEN="" + +"${SCRIPTPATH}/${BINARY}" --base-url "${URL}" --token "${TOKEN}" --ignore-ssl-errors diff -Nru datovka-4.8.3/tests/records_management_app/ui/app.ui datovka-4.9.3/tests/records_management_app/ui/app.ui --- datovka-4.8.3/tests/records_management_app/ui/app.ui 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/ui/app.ui 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,156 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + + + + Qt::Vertical + + + + + + + + + Base URL: + + + + + + + + + + Token: + + + + + + + + + + + + + + Filter: + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 800 + 20 + + + + + File + + + + + + Service + + + + + + + + + Help + + + + + + + + + + + Quit + + + Quit the application + + + Ctrl+Q + + + + + Get All Clients + + + + + Service Info + + + + + Upload Hierarchy + + + + + Upload File + + + + + Stored Files + + + + + About + + + + + + diff -Nru datovka-4.8.3/tests/records_management_app/ui/dialogue_service_info.ui datovka-4.9.3/tests/records_management_app/ui/dialogue_service_info.ui --- datovka-4.8.3/tests/records_management_app/ui/dialogue_service_info.ui 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/ui/dialogue_service_info.ui 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,95 @@ + + + DialogueServiceInfo + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + + + + + + + + Name: + + + + + + + Token Name: + + + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel + + + + + + + + + buttonBox + accepted() + DialogueServiceInfo + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DialogueServiceInfo + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff -Nru datovka-4.8.3/tests/records_management_app/ui/dialogue_stored_files.ui datovka-4.9.3/tests/records_management_app/ui/dialogue_stored_files.ui --- datovka-4.8.3/tests/records_management_app/ui/dialogue_stored_files.ui 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.9.3/tests/records_management_app/ui/dialogue_stored_files.ui 2017-09-06 11:49:23.000000000 +0000 @@ -0,0 +1,109 @@ + + + DialogueStoredFiles + + + + 0 + 0 + 400 + 170 + + + + Dialog + + + + + + Enter comma-separated values (positive integers): + + + + + + + + + Data message identifiers: + + + + + + + + + + + + + Delivery info identifiers: + + + + + + + Generate + + + + + + + Generate + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + DialogueStoredFiles + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DialogueStoredFiles + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff -Nru datovka-4.8.3/tests/test_db_container.pri datovka-4.9.3/tests/test_db_container.pri --- datovka-4.8.3/tests/test_db_container.pri 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/tests/test_db_container.pri 2017-09-06 11:49:23.000000000 +0000 @@ -1,4 +1,5 @@ +QT += svg QT += sql QT += widgets @@ -16,15 +17,19 @@ $${top_srcdir}src/crypto/crypto.c \ $${top_srcdir}src/delegates/tag_item.cpp \ $${top_srcdir}src/dimensions/dimensions.cpp \ + $${top_srcdir}src/graphics/graphics.cpp \ $${top_srcdir}src/io/db_tables.cpp \ $${top_srcdir}src/io/dbs.cpp \ $${top_srcdir}src/io/filesystem.cpp \ $${top_srcdir}src/io/message_db.cpp \ $${top_srcdir}src/io/message_db_set.cpp \ $${top_srcdir}src/io/message_db_set_container.cpp \ + $${top_srcdir}src/io/records_management_db.cpp \ $${top_srcdir}src/io/sqlite/db.cpp \ $${top_srcdir}src/io/sqlite/table.cpp \ $${top_srcdir}src/io/tag_db.cpp \ + $${top_srcdir}src/isds/isds_conversion.cpp \ + $${top_srcdir}src/localisation/localisation.cpp \ $${top_srcdir}src/models/files_model.cpp \ $${top_srcdir}src/models/messages_model.cpp \ $${top_srcdir}src/models/table_model.cpp \ @@ -37,15 +42,19 @@ $${top_srcdir}src/crypto/crypto_funcs.h \ $${top_srcdir}src/delegates/tag_item.h \ $${top_srcdir}src/dimensions/dimensions.h \ + $${top_srcdir}src/graphics/graphics.h \ $${top_srcdir}src/io/db_tables.h \ $${top_srcdir}src/io/dbs.h \ $${top_srcdir}src/io/filesystem.h \ $${top_srcdir}src/io/message_db.h \ $${top_srcdir}src/io/message_db_set.h \ $${top_srcdir}src/io/message_db_set_container.h \ + $${top_srcdir}src/io/records_management_db.h \ $${top_srcdir}src/io/sqlite/db.h \ $${top_srcdir}src/io/sqlite/table.h \ $${top_srcdir}src/io/tag_db.h \ + $${top_srcdir}src/isds/isds_conversion.h \ + $${top_srcdir}src/localisation/localisation.h \ $${top_srcdir}src/models/files_model.h \ $${top_srcdir}src/models/messages_model.h \ $${top_srcdir}src/models/table_model.h \ diff -Nru datovka-4.8.3/tests/test_isds_login.pri datovka-4.9.3/tests/test_isds_login.pri --- datovka-4.8.3/tests/test_isds_login.pri 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/tests/test_isds_login.pri 2017-09-06 11:49:23.000000000 +0000 @@ -1,5 +1,6 @@ # TODO -- Modify the co de so that widgets are not heeded. +QT += sql QT += widgets DEFINES += \ @@ -18,6 +19,7 @@ $${top_srcdir}src/io/filesystem.cpp \ $${top_srcdir}src/io/isds_login.cpp \ $${top_srcdir}src/io/isds_sessions.cpp \ + $${top_srcdir}src/settings/account.cpp \ $${top_srcdir}src/settings/accounts.cpp \ $${top_srcdir}src/settings/preferences.cpp \ $${top_srcdir}tests/test_isds_login.cpp @@ -29,6 +31,7 @@ $${top_srcdir}src/io/filesystem.h \ $${top_srcdir}src/io/isds_login.h \ $${top_srcdir}src/io/isds_sessions.h \ + $${top_srcdir}src/settings/account.h \ $${top_srcdir}src/settings/accounts.h \ $${top_srcdir}src/settings/preferences.h \ $${top_srcdir}tests/test_isds_login.h diff -Nru datovka-4.8.3/tests/test_message_db_set.pri datovka-4.9.3/tests/test_message_db_set.pri --- datovka-4.8.3/tests/test_message_db_set.pri 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/tests/test_message_db_set.pri 2017-09-06 11:49:23.000000000 +0000 @@ -1,4 +1,5 @@ +QT += svg QT += sql QT += widgets @@ -16,14 +17,18 @@ $${top_srcdir}src/crypto/crypto.c \ $${top_srcdir}src/delegates/tag_item.cpp \ $${top_srcdir}src/dimensions/dimensions.cpp \ + $${top_srcdir}src/graphics/graphics.cpp \ $${top_srcdir}src/io/db_tables.cpp \ $${top_srcdir}src/io/dbs.cpp \ $${top_srcdir}src/io/filesystem.cpp \ $${top_srcdir}src/io/message_db.cpp \ $${top_srcdir}src/io/message_db_set.cpp \ + $${top_srcdir}src/io/records_management_db.cpp \ $${top_srcdir}src/io/sqlite/db.cpp \ $${top_srcdir}src/io/sqlite/table.cpp \ $${top_srcdir}src/io/tag_db.cpp \ + $${top_srcdir}src/isds/isds_conversion.cpp \ + $${top_srcdir}src/localisation/localisation.cpp \ $${top_srcdir}src/models/files_model.cpp \ $${top_srcdir}src/models/messages_model.cpp \ $${top_srcdir}src/models/table_model.cpp \ @@ -36,14 +41,18 @@ $${top_srcdir}src/crypto/crypto_funcs.h \ $${top_srcdir}src/delegates/tag_item.h \ $${top_srcdir}src/dimensions/dimensions.h \ + $${top_srcdir}src/graphics/graphics.h \ $${top_srcdir}src/io/db_tables.h \ $${top_srcdir}src/io/dbs.h \ $${top_srcdir}src/io/filesystem.h \ $${top_srcdir}src/io/message_db.h \ $${top_srcdir}src/io/message_db_set.h \ + $${top_srcdir}src/io/records_management_db.h \ $${top_srcdir}src/io/sqlite/db.h \ $${top_srcdir}src/io/sqlite/table.h \ $${top_srcdir}src/io/tag_db.h \ + $${top_srcdir}src/isds/isds_conversion.h \ + $${top_srcdir}src/localisation/localisation.h \ $${top_srcdir}src/models/files_model.h \ $${top_srcdir}src/models/messages_model.h \ $${top_srcdir}src/models/table_model.h \ diff -Nru datovka-4.8.3/tests/tests.pro datovka-4.9.3/tests/tests.pro --- datovka-4.8.3/tests/tests.pro 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/tests/tests.pro 2017-09-06 11:49:23.000000000 +0000 @@ -4,17 +4,21 @@ QT += network QT += testlib +top_srcdir = ../ + TEMPLATE = app TARGET = tests -top_srcdir = ../ +include($${top_srcdir}pri/version.pri) DEFINES += \ - DEBUG=1 + DEBUG=1 \ + VERSION=\\\"$${VERSION}\\\" QMAKE_CXXFLAGS = \ -g -O0 -std=c++11 \ - -Wall -Wextra -pedantic + -Wall -Wextra -pedantic \ + -Wdate-time -Wformat -Werror=format-security INCLUDEPATH += \ $${top_srcdir} diff -Nru datovka-4.8.3/tests/test_task_downloads.pri datovka-4.9.3/tests/test_task_downloads.pri --- datovka-4.8.3/tests/test_task_downloads.pri 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/tests/test_task_downloads.pri 2017-09-06 11:49:23.000000000 +0000 @@ -1,4 +1,5 @@ +QT += svg QT += sql QT += widgets @@ -17,6 +18,7 @@ $${top_srcdir}src/crypto/crypto.c \ $${top_srcdir}src/delegates/tag_item.cpp \ $${top_srcdir}src/dimensions/dimensions.cpp \ + $${top_srcdir}src/graphics/graphics.cpp \ $${top_srcdir}src/io/account_db.cpp \ $${top_srcdir}src/io/db_tables.cpp \ $${top_srcdir}src/io/dbs.cpp \ @@ -25,13 +27,17 @@ $${top_srcdir}src/io/message_db.cpp \ $${top_srcdir}src/io/message_db_set.cpp \ $${top_srcdir}src/io/message_db_set_delegated.cpp \ + $${top_srcdir}src/io/records_management_db.cpp \ $${top_srcdir}src/io/sqlite/db.cpp \ $${top_srcdir}src/io/sqlite/table.cpp \ $${top_srcdir}src/io/tag_db.cpp \ + $${top_srcdir}src/isds/isds_conversion.cpp \ + $${top_srcdir}src/localisation/localisation.cpp \ $${top_srcdir}src/models/accounts_model.cpp \ $${top_srcdir}src/models/files_model.cpp \ $${top_srcdir}src/models/messages_model.cpp \ $${top_srcdir}src/models/table_model.cpp \ + $${top_srcdir}src/settings/account.cpp \ $${top_srcdir}src/settings/accounts.cpp \ $${top_srcdir}src/settings/preferences.cpp \ $${top_srcdir}src/worker/message_emitter.cpp \ @@ -47,6 +53,7 @@ $${top_srcdir}src/crypto/crypto_funcs.h \ $${top_srcdir}src/delegates/tag_item.h \ $${top_srcdir}src/dimensions/dimensions.h \ + $${top_srcdir}src/graphics/graphics.h \ $${top_srcdir}src/io/account_db.h \ $${top_srcdir}src/io/db_tables.h \ $${top_srcdir}src/io/dbs.h \ @@ -54,13 +61,17 @@ $${top_srcdir}src/io/isds_sessions.h \ $${top_srcdir}src/io/message_db.h \ $${top_srcdir}src/io/message_db_set.h \ + $${top_srcdir}src/io/records_management_db.h \ $${top_srcdir}src/io/sqlite/db.h \ $${top_srcdir}src/io/sqlite/table.h \ $${top_srcdir}src/io/tag_db.h \ + $${top_srcdir}src/isds/isds_conversion.h \ + $${top_srcdir}src/localisation/localisation.h \ $${top_srcdir}src/models/accounts_model.h \ $${top_srcdir}src/models/files_model.h \ $${top_srcdir}src/models/messages_model.h \ $${top_srcdir}src/models/table_model.h \ + $${top_srcdir}src/settings/account.h \ $${top_srcdir}src/settings/accounts.h \ $${top_srcdir}src/settings/preferences.h \ $${top_srcdir}src/worker/message_emitter.h \ diff -Nru datovka-4.8.3/tests/test_task_send_message.pri datovka-4.9.3/tests/test_task_send_message.pri --- datovka-4.8.3/tests/test_task_send_message.pri 2017-06-13 11:30:32.000000000 +0000 +++ datovka-4.9.3/tests/test_task_send_message.pri 2017-09-06 11:49:23.000000000 +0000 @@ -1,4 +1,5 @@ +QT += svg QT += sql QT += widgets @@ -17,6 +18,7 @@ $${top_srcdir}src/crypto/crypto.c \ $${top_srcdir}src/delegates/tag_item.cpp \ $${top_srcdir}src/dimensions/dimensions.cpp \ + $${top_srcdir}src/graphics/graphics.cpp \ $${top_srcdir}src/io/account_db.cpp \ $${top_srcdir}src/io/db_tables.cpp \ $${top_srcdir}src/io/dbs.cpp \ @@ -24,13 +26,17 @@ $${top_srcdir}src/io/isds_sessions.cpp \ $${top_srcdir}src/io/message_db.cpp \ $${top_srcdir}src/io/message_db_set.cpp \ + $${top_srcdir}src/io/records_management_db.cpp \ $${top_srcdir}src/io/sqlite/db.cpp \ $${top_srcdir}src/io/sqlite/table.cpp \ $${top_srcdir}src/io/tag_db.cpp \ + $${top_srcdir}src/isds/isds_conversion.cpp \ + $${top_srcdir}src/localisation/localisation.cpp \ $${top_srcdir}src/models/accounts_model.cpp \ $${top_srcdir}src/models/files_model.cpp \ $${top_srcdir}src/models/messages_model.cpp \ $${top_srcdir}src/models/table_model.cpp \ + $${top_srcdir}src/settings/account.cpp \ $${top_srcdir}src/settings/accounts.cpp \ $${top_srcdir}src/settings/preferences.cpp \ $${top_srcdir}src/worker/message_emitter.cpp \ @@ -44,6 +50,7 @@ $${top_srcdir}src/crypto/crypto_funcs.h \ $${top_srcdir}src/delegates/tag_item.h \ $${top_srcdir}src/dimensions/dimensions.h \ + $${top_srcdir}src/graphics/graphics.h \ $${top_srcdir}src/io/account_db.h \ $${top_srcdir}src/io/db_tables.h \ $${top_srcdir}src/io/dbs.h \ @@ -51,13 +58,17 @@ $${top_srcdir}src/io/isds_sessions.h \ $${top_srcdir}src/io/message_db.h \ $${top_srcdir}src/io/message_db_set.h \ + $${top_srcdir}src/io/records_management_db.h \ $${top_srcdir}src/io/sqlite/db.h \ $${top_srcdir}src/io/sqlite/table.h \ $${top_srcdir}src/io/tag_db.h \ + $${top_srcdir}src/isds/isds_conversion.h \ + $${top_srcdir}src/localisation/localisation.h \ $${top_srcdir}src/models/accounts_model.h \ $${top_srcdir}src/models/files_model.h \ $${top_srcdir}src/models/messages_model.h \ $${top_srcdir}src/models/table_model.h \ + $${top_srcdir}src/settings/account.h \ $${top_srcdir}src/settings/accounts.h \ $${top_srcdir}src/settings/preferences.h \ $${top_srcdir}src/worker/message_emitter.h \