diff options
Diffstat (limited to 'src')
197 files changed, 3796 insertions, 8428 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c416e681..28f30f13 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,6 +23,7 @@ # # SPDX-License-Identifier: GPL-3.0-or-later +# if(APPLE) add_compile_definitions("_GNU_SOURCE") endif() @@ -31,480 +32,562 @@ endif() find_package(Gpgme REQUIRED) # Introduce OpenSSL -if (APPLE) - # Define possible OpenSSL directories - set(OPENSSL_DIR_CANDIDATES - /usr/local/opt/openssl@3 - /opt/homebrew/opt/openssl@3 - ) - - # Find the valid OpenSSL directory - foreach(DIR IN LISTS OPENSSL_DIR_CANDIDATES) - if(IS_DIRECTORY "${DIR}" OR EXISTS "${DIR}") - set(OPENSSL_ROOT_DIR "${DIR}") - break() # Stop loop once a valid directory is found - endif() - endforeach() - - # If not found, throw an error or warning - if(NOT OPENSSL_ROOT_DIR) - message(FATAL_ERROR "OpenSSL not found in the standard directories. Please install it or set OPENSSL_ROOT_DIR manually.") +if(APPLE) + # Define possible OpenSSL directories + set(OPENSSL_DIR_CANDIDATES + /usr/local/opt/openssl@3 + /opt/homebrew/opt/openssl@3 + ) + + # Find the valid OpenSSL directory + foreach(DIR IN LISTS OPENSSL_DIR_CANDIDATES) + if(IS_DIRECTORY "${DIR}" OR EXISTS "${DIR}") + set(OPENSSL_ROOT_DIR "${DIR}") + break() # Stop loop once a valid directory is found endif() + endforeach() + + # If not found, throw an error or warning + if(NOT OPENSSL_ROOT_DIR) + message(FATAL_ERROR "OpenSSL not found in the standard directories. Please install it or set OPENSSL_ROOT_DIR manually.") + endif() endif() find_package(OpenSSL REQUIRED) +# mimalloc +if(NOT APPLE) + find_package(mimalloc REQUIRED) +endif() + # Set Build Information configure_file(${CMAKE_SOURCE_DIR}/src/GpgFrontend.h.in ${CMAKE_SOURCE_DIR}/src/GpgFrontend.h @ONLY) configure_file(${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInfo.h.in ${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInfo.h @ONLY) configure_file(${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInstallInfo.h.in ${CMAKE_SOURCE_DIR}/src/GpgFrontendBuildInstallInfo.h @ONLY) -configure_file(${CMAKE_SOURCE_DIR}/src/module/sdk/GFSDKBuildInfo.h.in ${CMAKE_SOURCE_DIR}/src/module/sdk/GFSDKBuildInfo.h @ONLY) -if (APPLE) - configure_file(${CMAKE_SOURCE_DIR}/resource/plist/ExportOptions.plist.in ${CMAKE_BINARY_DIR}/ExportOptions.plist @ONLY) -endif () +configure_file(${CMAKE_SOURCE_DIR}/src/sdk/GFSDKBuildInfo.h.in ${CMAKE_SOURCE_DIR}/src/sdk/GFSDKBuildInfo.h @ONLY) + +if(APPLE) + configure_file(${CMAKE_SOURCE_DIR}/resource/plist/ExportOptions.plist.in ${CMAKE_BINARY_DIR}/ExportOptions.plist @ONLY) +endif() # Set Runtime Output Directory -if (NOT XCODE_BUILD) - # Set Binary Output Path - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts) -else () - # Set Binary Output Path - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}) -endif () +if(NOT XCODE_BUILD) + # Set Binary Output Path + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts) +else() + # Set Binary Output Path + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}) +endif() -# configure for output path and resources -if (BUILD_APPLICATION) - aux_source_directory(. BASE_SOURCE) - set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_SOURCE_DIR}/gpgfrontend.rc") - set_property(SOURCE gpgfrontend.rc APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_SOURCE_DIR}/gpgfrontend.ico) -endif () - -if (BUILD_CORE) - # core depends pinentry - message("[+] Build Pinentry") - add_subdirectory(pinentry) - - message("[+] Build Core") - add_subdirectory(core) -endif () - -if (BUILD_UI) - message("[+] Build UI") - add_subdirectory(ui) -endif () - -if (BUILD_MODULE) - message("[+] Build Module") - add_subdirectory(module) -endif () +# Print modules +if(BUILD_CORE) + message("[+] Build Core") + add_subdirectory(core) +endif() + +if(BUILD_UI) + message("[+] Build UI") + add_subdirectory(ui) +endif() + +if(BUILD_SDK) + message("[+] Build SDK") + add_subdirectory(sdk) +endif() # build to test gpgfrontend core -if (BUILD_TEST) - include(CTest) - enable_testing() - add_subdirectory(test) -endif () - -if (BUILD_APPLICATION) - # Set Resource Output Path - if (${CMAKE_BUILD_TYPE} STREQUAL "Release") - if (APPLE) - set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Resources) - elseif (LINUX AND NOT LINUX_INSTALL_SOFTWARE) - file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir) - file(COPY ${CMAKE_SOURCE_DIR}/resource/lfs/hicolor DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share/icons) - file(COPY ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.metainfo.xml DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share/metainfo FOLLOW_SYMLINK_CHAIN) - file(COPY ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.desktop DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share/applications FOLLOW_SYMLINK_CHAIN) - file(COPY ${CMAKE_SOURCE_DIR}/resource/lfs/pixmaps/com.bktus.gpgfrontend.png DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir FOLLOW_SYMLINK_CHAIN) - set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share) - else () - set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - endif () - else () - set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) - endif () -endif () - -if (BUILD_APPLICATION) - if (${CMAKE_BUILD_TYPE} STREQUAL "Release") - if (APPLE) - set(GPGFRONTEND_MACOS_ICON ${CMAKE_SOURCE_DIR}/gpgfrontend.icns) - set_source_files_properties(${GPGFRONTEND_MACOS_ICON} PROPERTIES - MACOSX_PACKAGE_LOCATION "Resources") - elseif (LINUX AND NOT LINUX_INSTALL_SOFTWARE) - file(REMOVE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/bin/${AppName}) - endif () - endif () -endif () - -if (BUILD_APPLICATION) - # Copy Utils Files - if (MINGW) - message(STATUS "Copying Dependent DLL For Windows Runtime Env") - - set(ALL_RUNTIME_DEP_PATH_LIST "") - - # get mingw bin path - find_file(_libGccDllPath NAMES libgcc_s_seh-1.dll NO_CACHE REQUIRED) - cmake_path(GET _libGccDllPath PARENT_PATH _libDllBinPath) - - # find libicu*.dll - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libicu[a-z]*[0-9][0-9].dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libassuan*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libbz*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libcrypto-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libexpat-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libfreetype-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libgcc_s_seh-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libglib-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libgpg-error*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libgpgme*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libgraphite2.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libharfbuzz-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libiconv-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libintl-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/liblz4.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/liblzma-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libpcre-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libpcre2-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libpng*-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libstdc++-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libwinpthread-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/zlib*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libb2-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - # openssl - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libssl-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libcrypto-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - unset(_libDllPath) - file(GLOB _libDllPath "${_libDllBinPath}/libxml2-*.dll") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) - - # /mingw64/libexec - execute_process( - COMMAND cygpath -m /mingw64/libexec - OUTPUT_VARIABLE MSYS64_LIBEXEC_PATH - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - # gpgme-w32spawn.exe - unset(_libExEPath) - file(GLOB _libExEPath "${MSYS64_LIBEXEC_PATH}/gpgme-*.exe") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libExEPath}) - - unset(_libExEPath) - file(GLOB _libExEPath "${_libDllBinPath}/gpgme-*.exe") - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libExEPath}) - - set(ALL_RUNTIME_DLL_FILES "") - - if(GPGFRONTEND_QT5_BUILD) - list(APPEND ALL_RUNTIME_DLL_FILES "Qt5Core.dll;Qt5Gui.dll;Qt5Network.dll;Qt5PrintSupport.dll;Qt5Svg.dll;Qt5Widgets.dll;libbrotlicommon.dll;libbrotlidec.dll;libdouble-conversion.dll;libzstd.dll;libmd4c.dll;") - else() - list(APPEND ALL_RUNTIME_DLL_FILES "Qt6Core.dll;Qt6Core5Compat.dll;Qt6Gui.dll;Qt6Network.dll;Qt6PrintSupport.dll;Qt6Svg.dll;Qt6Widgets.dll;libbrotlicommon.dll;libbrotlidec.dll;libdouble-conversion.dll;libzstd.dll;libmd4c.dll;") - endif() - - # find the other dlls - foreach (_dllFileName ${ALL_RUNTIME_DLL_FILES}) - message(STATUS "DLL FILE ${_dllFileName}") - list(APPEND ALL_DLL_NAME ${_dllFileName}) - unset(_runtimeDllLocalPath) - - find_file(_runtimeDllLocalPath NAMES ${_dllFileName} NO_CACHE REQUIRED) - list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_runtimeDllLocalPath}) - message(STATUS "DLL ${_dllFileName} Path is ${_runtimeDllLocalPath}") - endforeach() - - message(STATUS "All Runtime Dependencies Path ${ALL_RUNTIME_DEP_PATH_LIST}") - - # copy dependencies to release path - foreach (_dllRuntimeFilePath ${ALL_RUNTIME_DEP_PATH_LIST}) - file(COPY ${_dllRuntimeFilePath} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN) - endforeach() - - endif () -endif () - -if (BUILD_APPLICATION) - set(RESOURCE_FILES ${CMAKE_SOURCE_DIR}/gpgfrontend.qrc ${APP_ICON_RESOURCE_WINDOWS} ${QON_QM_FILES}) - add_custom_target(resources ALL DEPENDS ${RESOURCE_FILES}) -endif () - -if (BUILD_APPLICATION) - if (${CMAKE_BUILD_TYPE} STREQUAL "Release") - if (MINGW) - add_executable(${AppName} WIN32 ${BASE_SOURCE} ${RESOURCE_FILES}) - # include qt dependencies - if(NOT Qt6_DIR) - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND windeployqt --force ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.exe) - else() - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND windeployqt-qt6.exe --force ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.exe) - endif() - elseif (LINUX AND NOT LINUX_INSTALL_SOFTWARE) - add_executable(${AppName} ${BASE_SOURCE} ${RESOURCE_FILES}) - - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/bin" - COMMAND ${CMAKE_COMMAND} -E rename "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/bin/${AppName}" - COMMENT "Copying Binary into App Image" - ) - - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/plugins" - COMMENT "Complement to build the required architecture" - ) - - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/plugins/mods" - COMMAND ${CMAKE_COMMAND} -E rename "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mods" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/plugins/mods" - COMMENT "Copying Mods into App Image" - ) - - # app bundle packing using xcode - elseif (APPLE AND XCODE_BUILD) - # standard app bundle packing - add_executable(${AppName} MACOSX_BUNDLE ${GPGFRONTEND_MACOS_ICON} ${BASE_SOURCE} ${RESOURCE_FILES}) - - set_target_properties(${AppName} PROPERTIES - BUNDLE True - MACOSX_BUNDLE_GUI_IDENTIFIER com.bktus.gpgfrontend - MACOSX_BUNDLE_BUNDLE_NAME ${AppName} - MACOSX_BUNDLE_LONG_VERSION_STRING ${BUILD_VERSION} - MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION} - MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} - MACOSX_BUNDLE_COPYRIGHT "GPL-3.0" - MACOSX_BUNDLE_INFO_STRING "An OpenPGP Crypto Tool" - MACOSX_BUNDLE_ICON_FILE "gpgfrontend.icns" - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/resource/plist/MacOSXBundleInfo.plist.in) - - # option for sandbox mode, still under test - if(GPGFRONTEND_XOCDE_ENABLE_SANDBOX) - message(STATUS "Build Application With App Sandbox") - set(CUSTOM_ATTRIBUTE_ENABLE_APP_SANDBOX "Yes") - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND /bin/cp -rf ${CMAKE_SOURCE_DIR}/resource/lfs/macOS/GnuPG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/${AppName}.app/Contents/ - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMENT "Copying Buddled GnuPG into App Bundle Resource") - set_target_properties(${AppName} PROPERTIES - XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/resource/entitlements/GpgFrontend.entitlements") - else() - message(STATUS "Build Application Without App Sandbox") - set(CUSTOM_ATTRIBUTE_ENABLE_APP_SANDBOX "No") - endif() - - set_target_properties(${AppName} PROPERTIES - XCODE_ATTRIBUTE_INSTALL_PATH "$(LOCAL_APPS_DIR)" - XCODE_ATTRIBUTE_SKIP_INSTALL "No" - XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep --entitlements ${CMAKE_SOURCE_DIR}/resource/plist/entitlement.plist" - XCODE_ATTRIBUTE_ENABLE_APP_SANDBOX "${CUSTOM_ATTRIBUTE_ENABLE_APP_SANDBOX}" - XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "Yes" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") - elseif(LINUX AND LINUX_INSTALL_SOFTWARE) - add_executable(${AppName} ${BASE_SOURCE} ${RESOURCE_FILES}) - else () - message(FATAL_ERROR "cannot find a defined method to release application.") - endif () - else () - # if the status is debug - add_executable(${AppName} ${BASE_SOURCE} ${RESOURCE_FILES}) - if(MINGW) - # include qt dependencies - if(NOT Qt6_DIR) - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND windeployqt --force ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.exe) - else() - add_custom_command(TARGET ${AppName} POST_BUILD - COMMAND windeployqt-qt6.exe --force ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.exe) - endif() - endif() - endif () - - # Make app build with resources - add_dependencies(${AppName} resources) - - # using c++ standard 17 - target_compile_features(${AppName} PUBLIC cxx_std_17) - -endif () +if(BUILD_TEST) + include(CTest) + enable_testing() + add_subdirectory(test) +endif() -# link options for GpgFrontend -if (BUILD_APPLICATION) - target_link_libraries(${AppName} gpgfrontend_ui gpgfrontend_test) - if (MINGW) - message(STATUS "Link Application Library For MINGW") - target_link_libraries(${AppName} crypto) - elseif (APPLE) - message(STATUS "Link Application Library For macOS") - else () - message(STATUS "Link Application Library For Linux") - target_link_libraries(${AppName} crypto pthread) - endif () -endif () +# configure for output path and resources +if(BUILD_APPLICATION) + aux_source_directory(. BASE_SOURCE) + set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_SOURCE_DIR}/gpgfrontend.rc") + set_property(SOURCE gpgfrontend.rc APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_SOURCE_DIR}/gpgfrontend.ico) +endif() -# add i18n support -if (BUILD_APPLICATION) - set(LOCALE_TS_PATH ${CMAKE_SOURCE_DIR}/resource/lfs/locale/ts) - set(TS_FILES "${LOCALE_TS_PATH}/GpgFrontend.en_US.ts" - "${LOCALE_TS_PATH}/GpgFrontend.de_DE.ts" - "${LOCALE_TS_PATH}/GpgFrontend.fr_FR.ts" - "${LOCALE_TS_PATH}/GpgFrontend.zh_CN.ts" - "${LOCALE_TS_PATH}/GpgFrontend.zh_TW.ts" - "${LOCALE_TS_PATH}/GpgFrontend.it_IT.ts") - file(GLOB_RECURSE ALL_SOURCE_FILES RELACTIVE ${CMAKE_SOURCE_DIR}/src/*.cpp) - - if(GPGFRONTEND_QT5_BUILD) - # TODO - qt5_add_translation(GF_TRANSLATIONS_QM ${TS_FILES}) - message(STATUS "GF_TRANSLATIONS_QM ${GF_TRANSLATIONS_QM}") - - set(GF_QM_TRANSLATIONS_RESOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/i18n.qrc") - file(WRITE ${GF_QM_TRANSLATIONS_RESOURCE_FILE} "<!DOCTYPE RCC>\n<RCC version=\"1.0\">\n <qresource prefix=\"i18n\">\n") - foreach(QM_FILE ${GF_TRANSLATIONS_QM}) - file(RELATIVE_PATH QM_FILENAME ${CMAKE_CURRENT_BINARY_DIR} ${QM_FILE}) - file(APPEND ${GF_QM_TRANSLATIONS_RESOURCE_FILE} " <file alias=\"${QM_FILENAME}\">${QM_FILE}</file>\n") - endforeach() - file(APPEND ${GF_QM_TRANSLATIONS_RESOURCE_FILE} " </qresource>\n</RCC>\n") - qt5_add_resources(GF_I18N_RESOURCES ${GF_QM_TRANSLATIONS_RESOURCE_FILE}) - - file(GLOB QT_TRANSLATIONS_TS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/third_party/qttranslations/translations/*.ts) - list(FILTER QT_TRANSLATIONS_TS INCLUDE REGEX ".*(qt|qtbase)_.*\.ts$") - qt5_add_translation(QT_TRANSLATIONS_QM ${QT_TRANSLATIONS_TS}) - - set(QT_QM_TRANSLATIONS_RESOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/qt_i18n.qrc") - file(WRITE ${QT_QM_TRANSLATIONS_RESOURCE_FILE} "<!DOCTYPE RCC>\n<RCC version=\"1.0\">\n <qresource prefix=\"qt_i18n\">\n") - foreach(QM_FILE ${QT_TRANSLATIONS_QM}) - file(RELATIVE_PATH QM_FILENAME ${CMAKE_CURRENT_BINARY_DIR} ${QM_FILE}) - file(APPEND ${QT_QM_TRANSLATIONS_RESOURCE_FILE} " <file alias=\"${QM_FILENAME}\">${QM_FILE}</file>\n") - endforeach() - file(APPEND ${QT_QM_TRANSLATIONS_RESOURCE_FILE} " </qresource>\n</RCC>\n") - qt5_add_resources(GF_I18N_RESOURCES ${QT_QM_TRANSLATIONS_RESOURCE_FILE}) - - message(STATUS "GF_I18N_RESOURCES ${GF_I18N_RESOURCES}") - - target_sources(${AppName} PRIVATE ${GF_I18N_RESOURCES}) +if(BUILD_APPLICATION) + # Set Resource Output Path + if(${CMAKE_BUILD_TYPE} STREQUAL "Release") + if(APPLE) + set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Resources) + elseif(LINUX AND NOT LINUX_INSTALL_SOFTWARE) + file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir) + file(COPY ${CMAKE_SOURCE_DIR}/resource/lfs/hicolor DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share/icons) + file(COPY ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.metainfo.xml DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share/metainfo FOLLOW_SYMLINK_CHAIN) + file(COPY ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.desktop DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share/applications FOLLOW_SYMLINK_CHAIN) + file(COPY ${CMAKE_SOURCE_DIR}/resource/lfs/pixmaps/com.bktus.gpgfrontend.png DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir FOLLOW_SYMLINK_CHAIN) + set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/share) else() - qt_add_translations(${AppName} - RESOURCE_PREFIX "/i18n" - TS_FILES ${TS_FILES} - SOURCES ${ALL_SOURCE_FILES} - INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/src) - file(GLOB QT_TRANSLATIONS_TS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/third_party/qttranslations/translations/*.ts) - list(FILTER QT_TRANSLATIONS_TS INCLUDE REGEX ".*(qt|qtbase)_.*\.ts$") - add_custom_target(qttranslations ALL) - qt_add_lrelease(qttranslations - TS_FILES ${QT_TRANSLATIONS_TS} - QM_FILES_OUTPUT_VARIABLE QT_TRANSLATIONS_QM) - qt_add_resources(${AppName} "qttranslations" - PREFIX "/i18n_qt" - BASE ${CMAKE_CURRENT_BINARY_DIR} - FILES ${QT_TRANSLATIONS_QM}) + set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) endif() + else() + set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + endif() +endif() +if(BUILD_APPLICATION) + if(${CMAKE_BUILD_TYPE} STREQUAL "Release") + if(APPLE) + set(GPGFRONTEND_MACOS_ICON ${CMAKE_SOURCE_DIR}/gpgfrontend.icns) + set_source_files_properties(${GPGFRONTEND_MACOS_ICON} PROPERTIES + MACOSX_PACKAGE_LOCATION "Resources") + elseif(LINUX AND NOT LINUX_INSTALL_SOFTWARE) + file(REMOVE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/bin/${AppName}) + endif() + endif() +endif() + +if(BUILD_APPLICATION AND MINGW) + message(STATUS "Copying Dependent DLL For Windows Runtime Env") + + # all dep dll list + set(ALL_RUNTIME_DEP_PATH_LIST "") + + # /mingw64/libexec + execute_process( + COMMAND cygpath -m /mingw64/bin + OUTPUT_VARIABLE MSYS64_BIN_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # find libicu*.dll + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libicu[a-z]*[0-9][0-9].dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libassuan*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libbz*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libcrypto-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libexpat-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libfreetype-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libgcc_s_seh-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libglib-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libgpg-error*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libgpgme*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libgraphite2.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libharfbuzz-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libiconv-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libintl-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/liblz4.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/liblzma-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libpcre-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libpcre2-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libpng*-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libstdc++-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libwinpthread-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/zlib*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libb2-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + # openssl + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libssl-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libcrypto-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libxml2-*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + # /mingw64/libexec + execute_process( + COMMAND cygpath -m /mingw64/libexec + OUTPUT_VARIABLE MSYS64_LIBEXEC_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # gpgme-w32spawn.exe + unset(_libExEPath) + file(GLOB _libExEPath "${MSYS64_LIBEXEC_PATH}/gpgme-*.exe") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libExEPath}) + + unset(_libExEPath) + file(GLOB _libExEPath "${MSYS64_BIN_PATH}/gpgme-*.exe") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libExEPath}) + + # add gpgfrontend libraries + if(STABLE_BUILD_ONLY_APPLICATION) + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libgpgfrontend_*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libmimalloc*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/mimalloc*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libarchive*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + + unset(_libDllPath) + file(GLOB _libDllPath "${MSYS64_BIN_PATH}/libgtest*.dll") + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_libDllPath}) + endif() + + # dll with only name + set(ALL_RUNTIME_DLL_FILES "") + + if(GPGFRONTEND_QT5_BUILD) + list(APPEND ALL_RUNTIME_DLL_FILES "Qt5Core.dll;Qt5Gui.dll;Qt5Network.dll;Qt5PrintSupport.dll;Qt5Svg.dll;Qt5Widgets.dll;libbrotlicommon.dll;libbrotlidec.dll;libdouble-conversion.dll;libzstd.dll;libmd4c.dll;") + else() + list(APPEND ALL_RUNTIME_DLL_FILES "Qt6Core.dll;Qt6Core5Compat.dll;Qt6Gui.dll;Qt6Network.dll;Qt6PrintSupport.dll;Qt6Svg.dll;Qt6Widgets.dll;libbrotlicommon.dll;libbrotlidec.dll;libdouble-conversion.dll;libzstd.dll;libmd4c.dll;") + endif() + + # find the other dlls + foreach(_dllFileName ${ALL_RUNTIME_DLL_FILES}) + message(STATUS "DLL FILE ${_dllFileName}") + list(APPEND ALL_DLL_NAME ${_dllFileName}) + unset(_runtimeDllLocalPath) + + find_file(_runtimeDllLocalPath NAMES ${_dllFileName} NO_CACHE REQUIRED) + list(APPEND ALL_RUNTIME_DEP_PATH_LIST ${_runtimeDllLocalPath}) + message(STATUS "DLL: ${_dllFileName} , ITS Full Path is ${_runtimeDllLocalPath}") + endforeach() + + message(STATUS "All the Application Runtime Dependencies Path: ${ALL_RUNTIME_DEP_PATH_LIST}") + + # copy dependencies to release path + foreach(_dllRuntimeFilePath ${ALL_RUNTIME_DEP_PATH_LIST}) + file(COPY ${_dllRuntimeFilePath} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN) + endforeach() +endif() + +if(BUILD_APPLICATION) + set(RESOURCE_FILES ${CMAKE_SOURCE_DIR}/gpgfrontend.qrc ${APP_ICON_RESOURCE_WINDOWS} ${QON_QM_FILES}) + add_custom_target(resources ALL DEPENDS ${RESOURCE_FILES}) +endif() + +if(BUILD_APPLICATION) + if(${CMAKE_BUILD_TYPE} STREQUAL "Release") + if(MINGW) + add_executable(${AppName} WIN32 ${BASE_SOURCE} ${RESOURCE_FILES}) + elseif(LINUX AND NOT LINUX_INSTALL_SOFTWARE) + add_executable(${AppName} ${BASE_SOURCE} ${RESOURCE_FILES}) + + add_custom_command(TARGET ${AppName} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/bin" + COMMAND ${CMAKE_COMMAND} -E rename "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/AppDir/usr/bin/${AppName}" + COMMENT "Copying Binary into App Image" + ) + + # app bundle packing using xcode + elseif(APPLE AND XCODE_BUILD) + # standard app bundle packing + add_executable(${AppName} MACOSX_BUNDLE ${GPGFRONTEND_MACOS_ICON} ${BASE_SOURCE} ${RESOURCE_FILES}) + + set_target_properties(${AppName} PROPERTIES + BUNDLE True + MACOSX_BUNDLE_GUI_IDENTIFIER com.bktus.gpgfrontend + MACOSX_BUNDLE_BUNDLE_NAME ${AppName} + MACOSX_BUNDLE_LONG_VERSION_STRING ${BUILD_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION} + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_COPYRIGHT "GPL-3.0" + MACOSX_BUNDLE_INFO_STRING "An OpenPGP Crypto Tool" + MACOSX_BUNDLE_ICON_FILE "gpgfrontend.icns" + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/resource/plist/MacOSXBundleInfo.plist.in) + + # option for sandbox mode, still under test + if(GPGFRONTEND_XOCDE_ENABLE_SANDBOX) + message(STATUS "Build Application With App Sandbox") + set(CUSTOM_ATTRIBUTE_ENABLE_APP_SANDBOX "Yes") + add_custom_command(TARGET ${AppName} POST_BUILD + COMMAND /bin/cp -rf ${CMAKE_SOURCE_DIR}/resource/lfs/macOS/GnuPG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/${AppName}.app/Contents/ + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + COMMENT "Copying Buddled GnuPG into App Bundle Resource") + set_target_properties(${AppName} PROPERTIES + XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_SOURCE_DIR}/resource/entitlements/GpgFrontend.entitlements") + else() + message(STATUS "Build Application Without App Sandbox") + set(CUSTOM_ATTRIBUTE_ENABLE_APP_SANDBOX "No") + endif() + + set_target_properties(${AppName} PROPERTIES + XCODE_ATTRIBUTE_INSTALL_PATH "$(LOCAL_APPS_DIR)" + XCODE_ATTRIBUTE_SKIP_INSTALL "No" + XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS "--deep --entitlements ${CMAKE_SOURCE_DIR}/resource/plist/entitlement.plist" + XCODE_ATTRIBUTE_ENABLE_APP_SANDBOX "${CUSTOM_ATTRIBUTE_ENABLE_APP_SANDBOX}" + XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "Yes" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") + elseif(LINUX AND LINUX_INSTALL_SOFTWARE) + add_executable(${AppName} ${BASE_SOURCE} ${RESOURCE_FILES}) + else() + message(FATAL_ERROR "cannot find a defined method to release application.") + endif() + else() + # if the status is debug + add_executable(${AppName} ${BASE_SOURCE} ${RESOURCE_FILES}) + + if(MINGW) + # include qt dependencies + if(NOT Qt6_DIR) + add_custom_command(TARGET ${AppName} POST_BUILD + COMMAND windeployqt --force ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.exe) + else() + add_custom_command(TARGET ${AppName} POST_BUILD + COMMAND windeployqt-qt6.exe --force ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${AppName}.exe) + endif() + endif() + endif() + + # Make app build with resources + add_dependencies(${AppName} resources) + + # using c++ standard 17 + target_compile_features(${AppName} PUBLIC cxx_std_17) +endif() + +if(STABLE_BUILD_ONLY_APPLICATION) + message(STATUS "Application Headers Search Path: ${CMAKE_INSTALL_PREFIX}/include/gpgfrontend") + target_include_directories(${AppName} PUBLIC "${CMAKE_INSTALL_PREFIX}/include/gpgfrontend") + + # link qt + if(GPGFRONTEND_QT5_BUILD) + target_link_libraries(${AppName} Qt5::Core Qt5::Widgets) + else() + target_link_libraries(${AppName} Qt6::Core Qt6::Widgets) + endif() +endif() + +# link options for GpgFrontend +if(BUILD_APPLICATION) + target_link_libraries(${AppName} gpgfrontend_core gpgfrontend_ui gpgfrontend_test) + + if(MINGW) + message(STATUS "Link Application Library For MINGW") + target_link_libraries(${AppName} crypto) + elseif(APPLE) + message(STATUS "Link Application Library For macOS") + else() + message(STATUS "Link Application Library For Linux") + target_link_libraries(${AppName} crypto pthread) + endif() +endif() + +# add i18n support +if(BUILD_APPLICATION) + set(LOCALE_TS_PATH ${CMAKE_SOURCE_DIR}/resource/lfs/locale/ts) + set(TS_FILES "${LOCALE_TS_PATH}/GpgFrontend.en_US.ts" + "${LOCALE_TS_PATH}/GpgFrontend.de_DE.ts" + "${LOCALE_TS_PATH}/GpgFrontend.fr_FR.ts" + "${LOCALE_TS_PATH}/GpgFrontend.zh_CN.ts" + "${LOCALE_TS_PATH}/GpgFrontend.zh_TW.ts" + "${LOCALE_TS_PATH}/GpgFrontend.it_IT.ts") + file(GLOB_RECURSE ALL_SOURCE_FILES RELACTIVE ${CMAKE_SOURCE_DIR}/src/*.cpp) + + if(GPGFRONTEND_QT5_BUILD) + # TODO + qt5_add_translation(GF_TRANSLATIONS_QM ${TS_FILES}) + message(STATUS "GF_TRANSLATIONS_QM ${GF_TRANSLATIONS_QM}") + + set(GF_QM_TRANSLATIONS_RESOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/i18n.qrc") + file(WRITE ${GF_QM_TRANSLATIONS_RESOURCE_FILE} "<!DOCTYPE RCC>\n<RCC version=\"1.0\">\n <qresource prefix=\"i18n\">\n") + + foreach(QM_FILE ${GF_TRANSLATIONS_QM}) + file(RELATIVE_PATH QM_FILENAME ${CMAKE_CURRENT_BINARY_DIR} ${QM_FILE}) + file(APPEND ${GF_QM_TRANSLATIONS_RESOURCE_FILE} " <file alias=\"${QM_FILENAME}\">${QM_FILE}</file>\n") + endforeach() + + file(APPEND ${GF_QM_TRANSLATIONS_RESOURCE_FILE} " </qresource>\n</RCC>\n") + qt5_add_resources(GF_I18N_RESOURCES ${GF_QM_TRANSLATIONS_RESOURCE_FILE}) + + file(GLOB QT_TRANSLATIONS_TS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/third_party/qttranslations/translations/*.ts) + list(FILTER QT_TRANSLATIONS_TS INCLUDE REGEX ".*(qt|qtbase)_.*\.ts$") + qt5_add_translation(QT_TRANSLATIONS_QM ${QT_TRANSLATIONS_TS}) + + set(QT_QM_TRANSLATIONS_RESOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/qt_i18n.qrc") + file(WRITE ${QT_QM_TRANSLATIONS_RESOURCE_FILE} "<!DOCTYPE RCC>\n<RCC version=\"1.0\">\n <qresource prefix=\"qt_i18n\">\n") + + foreach(QM_FILE ${QT_TRANSLATIONS_QM}) + file(RELATIVE_PATH QM_FILENAME ${CMAKE_CURRENT_BINARY_DIR} ${QM_FILE}) + file(APPEND ${QT_QM_TRANSLATIONS_RESOURCE_FILE} " <file alias=\"${QM_FILENAME}\">${QM_FILE}</file>\n") + endforeach() + + file(APPEND ${QT_QM_TRANSLATIONS_RESOURCE_FILE} " </qresource>\n</RCC>\n") + qt5_add_resources(GF_I18N_RESOURCES ${QT_QM_TRANSLATIONS_RESOURCE_FILE}) + + message(STATUS "GF_I18N_RESOURCES ${GF_I18N_RESOURCES}") + + target_sources(${AppName} PRIVATE ${GF_I18N_RESOURCES}) + else() + add_custom_target(gftranslations ALL) + + qt_add_lrelease(gftranslations + TS_FILES ${TS_FILES} + QM_FILES_OUTPUT_VARIABLE GF_TRANSLATIONS_QM) + qt_add_resources(${AppName} "gftranslations" + PREFIX "/i18n" + BASE ${CMAKE_CURRENT_BINARY_DIR} + FILES ${GF_TRANSLATIONS_QM}) + + add_custom_target(qttranslations ALL) + + file(GLOB QT_TRANSLATIONS_TS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/third_party/qttranslations/translations/*.ts) + list(FILTER QT_TRANSLATIONS_TS INCLUDE REGEX ".*(qt|qtbase)_.*\.ts$") + qt_add_lrelease(qttranslations + TS_FILES ${QT_TRANSLATIONS_TS} + QM_FILES_OUTPUT_VARIABLE QT_TRANSLATIONS_QM) + qt_add_resources(${AppName} "qttranslations" + PREFIX "/i18n_qt" + BASE ${CMAKE_CURRENT_BINARY_DIR} + FILES ${QT_TRANSLATIONS_QM}) + endif() endif() # if building linux package -if (LINUX AND LINUX_INSTALL_SOFTWARE) - include(GNUInstallDirs) - set(GPGFRONTEND_INSTALL_LIBRARIES - mimalloc - spdlog - gpgfrontend_core - gpgfrontend_ui - gpgfrontend_test - gpgfrontend_pinentry - gpgfrontend_module_sdk) - - message(STATUS "GpgFrontend Install Libraries: ${GPGFRONTEND_INSTALL_LIBRARIES}") - install(TARGETS ${AppName} ${GPGFRONTEND_INSTALL_LIBRARIES} - EXPORT GpgFrontendTargets - RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}) - - install(FILES ${CMAKE_SOURCE_DIR}/TRANSLATORS - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/${AppName}/) - install(FILES ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.appdata.xml - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/metainfo/) - install(FILES ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.desktop - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/applications/) - install(DIRECTORY ${CMAKE_SOURCE_DIR}/resource/lfs/pixmaps/ - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/pixmaps/) - install(DIRECTORY ${CMAKE_SOURCE_DIR}/resource/lfs/hicolor/ - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/icons/hicolor/) -endif () +if(LINUX AND LINUX_INSTALL_SOFTWARE) + include(GNUInstallDirs) + + if(STABLE_BUILD_ONLY_APPLICATION) + set(GPGFRONTEND_INSTALL_LIBRARIES "") + else() + set(GPGFRONTEND_INSTALL_LIBRARIES + gpgfrontend_core + gpgfrontend_ui + gpgfrontend_test + gpgfrontend_module_sdk) + endif() + + message(STATUS "GpgFrontend Install Libraries: ${GPGFRONTEND_INSTALL_LIBRARIES}") + install(TARGETS ${AppName} ${GPGFRONTEND_INSTALL_LIBRARIES} + EXPORT GpgFrontendTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + + install(FILES ${CMAKE_SOURCE_DIR}/TRANSLATORS + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${AppName}/) + install(FILES ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.appdata.xml + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo/) + install(FILES ${CMAKE_SOURCE_DIR}/resource/appstream/com.bktus.gpgfrontend.desktop + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/) + install(DIRECTORY ${CMAKE_SOURCE_DIR}/resource/lfs/pixmaps/ + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps/) + install(DIRECTORY ${CMAKE_SOURCE_DIR}/resource/lfs/hicolor/ + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/) +endif() + +# if only build sdk +if(STABLE_BUILD_ONLY_SDK) + include(GNUInstallDirs) + set(GPGFRONTEND_SDK_INSTALL_LIBRARIES + gpgfrontend_module_sdk) + + install(TARGETS ${GPGFRONTEND_SDK_INSTALL_LIBRARIES} + EXPORT GpgFrontendTargets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() + +# if build full sdk +if(STABLE_BUILD_FULL_SDK) + include(GNUInstallDirs) + + set(GPGFRONTEND_SDK_INSTALL_LIBRARIES + gpgfrontend_core + gpgfrontend_ui + gpgfrontend_test + gpgfrontend_module_sdk) + + install(TARGETS ${GPGFRONTEND_SDK_INSTALL_LIBRARIES} + EXPORT GpgFrontendTargets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/core" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gpgfrontend" + FILES_MATCHING + PATTERN "*.h" + ) + + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ui" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gpgfrontend" + FILES_MATCHING + PATTERN "*.h" + ) + + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/test" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gpgfrontend" + FILES_MATCHING + PATTERN "*.h" + ) +endif()
\ No newline at end of file diff --git a/src/GpgFrontendContext.h b/src/GpgFrontendContext.h index 00bbcfbe..9dd805b7 100644 --- a/src/GpgFrontendContext.h +++ b/src/GpgFrontendContext.h @@ -28,6 +28,10 @@ #pragma once +#include <qapplication.h> + +#include <memory> + namespace GpgFrontend { struct GpgFrontendContext; @@ -38,7 +42,6 @@ using GFCxtSPtr = std::shared_ptr<GpgFrontendContext>; struct GpgFrontendContext { int argc; char** argv; - spdlog::level::level_enum log_level; bool gather_external_gnupg_info; bool load_default_gpg_context; diff --git a/src/app.cpp b/src/app.cpp index 9aa72894..4e67a0d6 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -34,7 +34,6 @@ // main #include "init.h" -#include "main.h" namespace GpgFrontend { @@ -50,20 +49,18 @@ constexpr int kCrashCode = ~0; ///< auto StartApplication(const GFCxtWPtr& p_ctx) -> int { GFCxtSPtr ctx = p_ctx.lock(); if (ctx == nullptr) { - GF_MAIN_LOG_ERROR("cannot get gpgfrontend context."); + qWarning("cannot get gpgfrontend context."); return -1; } auto* app = ctx->GetApp(); if (app == nullptr) { - GF_MAIN_LOG_ERROR("cannot get qapplication from gpgfrontend context."); + qWarning("cannot get QApplication from gpgfrontend context."); return -1; } - GF_MAIN_LOG_DEBUG("start running gui application"); - /** - * internationalisation. loop to restart main window + * internationalization. loop to restart main window * with changed translation when settings change. */ int return_from_event_loop_code; @@ -71,7 +68,7 @@ auto StartApplication(const GFCxtWPtr& p_ctx) -> int { do { // refresh locale settings - if (restart_count > 0) InitLocale(); + InitLocale(); // after that load ui totally GpgFrontend::UI::InitGpgFrontendUI(app); @@ -79,13 +76,8 @@ auto StartApplication(const GFCxtWPtr& p_ctx) -> int { // finally create main window return_from_event_loop_code = GpgFrontend::UI::RunGpgFrontendUI(app); - GF_MAIN_LOG_DEBUG("try to destroy modules system and core"); - restart_count++; - GF_MAIN_LOG_DEBUG( - "restart loop refresh, event loop code: {}, restart count: {}", - return_from_event_loop_code, restart_count); } while (return_from_event_loop_code == GpgFrontend::kRestartCode && restart_count < 99); @@ -94,17 +86,10 @@ auto StartApplication(const GFCxtWPtr& p_ctx) -> int { // then shutdown the core GpgFrontend::DestroyGpgFrontendCore(); - GF_MAIN_LOG_DEBUG("core and modules system destroyed"); - - // log for debug - GF_MAIN_LOG_INFO("GpgFrontend is about to exit."); // deep restart mode if (return_from_event_loop_code == GpgFrontend::kDeepRestartCode || return_from_event_loop_code == kCrashCode) { - // log for debug - GF_MAIN_LOG_DEBUG( - "deep restart or cash loop status caught, restart a new application"); QProcess::startDetached(qApp->arguments()[0], qApp->arguments()); }; diff --git a/src/cmd.cpp b/src/cmd.cpp index d41b6de0..06222431 100644 --- a/src/cmd.cpp +++ b/src/cmd.cpp @@ -28,13 +28,16 @@ #include "cmd.h" -#include "core/utils/BuildInfoUtils.h" -#include "main.h" +#include <qdatetime.h> +#include <qglobal.h> +#include <qloggingcategory.h> +#include <qstring.h> +#include <qtextstream.h> -// std -#include <iostream> +#include "core/utils/BuildInfoUtils.h" // GpgFrontend + #include "GpgFrontendContext.h" #include "test/GpgFrontendTest.h" @@ -42,7 +45,7 @@ namespace GpgFrontend { auto PrintVersion() -> int { QTextStream stream(stdout); - stream << PROJECT_NAME << " " << GetProjectVersion() << '\n'; + stream << GetProjectName() << " " << GetProjectVersion() << '\n'; stream << "Copyright (©) 2021 Saturneric <[email protected]>" << '\n' << QCoreApplication::tr( "This is free software; see the source for copying conditions.") @@ -60,30 +63,29 @@ auto PrintVersion() -> int { return 0; } -auto ParseLogLevel(const QString& log_level) -> spdlog::level::level_enum { - if (log_level == "trace") { - return spdlog::level::trace; - } +auto ParseLogLevel(const QString& log_level) -> int { if (log_level == "debug") { - return spdlog::level::debug; - } - if (log_level == "info") { - return spdlog::level::info; + QLoggingCategory::setFilterRules( + "core.debug=true\nui.debug=true\ntest.debug=true\nmodule.debug=true"); + } else if (log_level == "info") { + QLoggingCategory::setFilterRules( + "*.debug=false\ncore.info=true\nui.info=true\ntest.info=" + "true\nmodule.info=true"); + } else if (log_level == "warning") { + QLoggingCategory::setFilterRules("*.debug=false\n*.info=false\n"); + } else if (log_level == "critical") { + QLoggingCategory::setFilterRules( + "*.debug=false\n*.info=false\n*.warning=false\n"); + } else { + qWarning() << "unknown log level: " << log_level; } - if (log_level == "warn") { - return spdlog::level::warn; - } - if (log_level == "error") { - return spdlog::level::err; - } - - return spdlog::level::info; + return 0; } auto RunTest(const GFCxtWPtr& p_ctx) -> int { GpgFrontend::GFCxtSPtr const ctx = p_ctx.lock(); if (ctx == nullptr) { - GF_MAIN_LOG_ERROR("cannot get gpgfrontend context for test running"); + qWarning("cannot get gpgfrontend context for test running"); return -1; } @@ -36,7 +36,7 @@ namespace GpgFrontend { auto PrintVersion() -> int; -auto ParseLogLevel(const QString& level) -> spdlog::level::level_enum; +auto ParseLogLevel(const QString& level) -> int; auto RunTest(const GFCxtWPtr&) -> int; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cedbe69a..d5b213ca 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -23,7 +23,7 @@ # # SPDX-License-Identifier: GPL-3.0-or-later - +# gather source files aux_source_directory(./function/result_analyse CORE_SOURCE) aux_source_directory(./function/basic CORE_SOURCE) aux_source_directory(./function/gpg CORE_SOURCE) @@ -40,24 +40,24 @@ aux_source_directory(. CORE_SOURCE) # define libgpgfrontend_core set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) + add_library(gpgfrontend_core SHARED ${CORE_SOURCE}) + +# generate headers set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GpgFrontendCoreExport.h") generate_export_header(gpgfrontend_core EXPORT_FILE_NAME "${_export_file}") +# compile definitions +target_compile_definitions(gpgfrontend_core PUBLIC GF_CORE) + +# mimalloc (except apple macos) if(NOT APPLE) - target_link_libraries(gpgfrontend_core PUBLIC mimalloc) - if(MINGW) - set_target_properties(mimalloc - PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - ) - endif() + target_link_libraries(gpgfrontend_core PUBLIC mimalloc) endif() # qt-aes target_sources(gpgfrontend_core PRIVATE - ${CMAKE_SOURCE_DIR}/third_party/qt-aes/qaesencryption.cpp) + ${CMAKE_SOURCE_DIR}/third_party/qt-aes/qaesencryption.cpp) # encoding detect library aux_source_directory(${CMAKE_SOURCE_DIR}/third_party/encoding-detect ENCODING_DETECT_SOURCE_CODE) @@ -65,44 +65,27 @@ target_sources(gpgfrontend_core PUBLIC ${ENCODING_DETECT_SOURCE_CODE}) # link gnupg libraries target_link_libraries(gpgfrontend_core PUBLIC gpgme assuan gpg-error) + # link openssl target_link_libraries(gpgfrontend_core PUBLIC OpenSSL::SSL OpenSSL::Crypto) -if (MINGW) - # for uuid ability in mingw - target_link_libraries(gpgfrontend_core PUBLIC bcrypt) -endif () -# spdlog -target_link_libraries(gpgfrontend_core PRIVATE spdlog) if(MINGW) - set_target_properties(spdlog - PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - ) + # for uuid ability in mingw + target_link_libraries(gpgfrontend_core PUBLIC bcrypt) endif() # configure libarchive -if(NOT MINGW) - if(APPLE) - if(EXISTS "/usr/local/opt/libarchive/include") - set(LibArchive_INCLUDE_DIR "/usr/local/opt/libarchive/include") - else() - set(LibArchive_INCLUDE_DIR "/opt/homebrew/opt/libarchive/include") - endif() - endif() - find_package(LibArchive REQUIRED) - target_include_directories(gpgfrontend_core PRIVATE ${LibArchive_INCLUDE_DIR}) -else() - if(MINGW) - set_target_properties(archive - PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - ) - endif() +if(APPLE) + if(EXISTS "/usr/local/opt/libarchive/include") + set(LibArchive_INCLUDE_DIR "/usr/local/opt/libarchive/include") + else() + set(LibArchive_INCLUDE_DIR "/opt/homebrew/opt/libarchive/include") + endif() endif() +find_package(LibArchive REQUIRED) +target_include_directories(gpgfrontend_core PRIVATE ${LibArchive_INCLUDE_DIR}) + # link libarchive target_link_libraries(gpgfrontend_core PRIVATE archive) @@ -116,30 +99,38 @@ endif() # set up pch target_precompile_headers(gpgfrontend_core - PUBLIC ${CMAKE_SOURCE_DIR}/src/GpgFrontend.h - PUBLIC GpgFrontendCore.h - PUBLIC GpgConstants.h) + PUBLIC ${CMAKE_SOURCE_DIR}/src/GpgFrontend.h + PUBLIC GpgFrontendCore.h + PUBLIC GpgConstants.h) # using std c++ 17 target_compile_features(gpgfrontend_core PUBLIC cxx_std_17) +if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") + # lib output path + set_target_properties(gpgfrontend_core PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib) +endif() + # link for different platforms -if (MINGW) - message(STATUS "Link GPG Static Library For MINGW") - target_link_libraries(gpgfrontend_core PUBLIC wsock32) -elseif (APPLE) - message(STATUS "Link GPG Static Library For macOS") - if (XCODE_BUILD) - set_target_properties(gpgfrontend_core - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") - endif () -else () - # linux - message(STATUS "Link GPG Static Library For Unix") - target_link_libraries(gpgfrontend_core PUBLIC pthread dl) -endif () +if(MINGW) + message(STATUS "Link GPG Static Library For MINGW") + target_link_libraries(gpgfrontend_core PUBLIC wsock32) +elseif(APPLE) + message(STATUS "Link GPG Static Library For macOS") + + if(XCODE_BUILD) + set_target_properties(gpgfrontend_core + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") + endif() +else() + # linux + message(STATUS "Link GPG Static Library For Unix") + target_link_libraries(gpgfrontend_core PUBLIC pthread dl) +endif() diff --git a/src/core/GpgConstants.h b/src/core/GpgConstants.h index 91d5f1ef..1165db78 100644 --- a/src/core/GpgConstants.h +++ b/src/core/GpgConstants.h @@ -53,9 +53,13 @@ constexpr const char* PGP_PRIVATE_KEY_BEGIN = "-----BEGIN PGP PRIVATE KEY BLOCK-----"; ///< // MODULE ID -const QString kGnuPGInfoGatheringModuleID = +constexpr const char* kGnuPGInfoGatheringModuleID = "com.bktus.gpgfrontend.module.gnupg_info_gathering"; -const QString kVersionCheckingModuleID = +constexpr const char* kVersionCheckingModuleID = "com.bktus.gpgfrontend.module.version_checking"; +constexpr const char* kPinentryModuleID = + "com.bktus.gpgfrontend.module.pinentry"; +constexpr const char* kPaperKeyModuleID = + "com.bktus.gpgfrontend.module.paper_key"; } // namespace GpgFrontend diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp index 2952d6e4..4e1b64e1 100644 --- a/src/core/GpgCoreInit.cpp +++ b/src/core/GpgCoreInit.cpp @@ -78,7 +78,6 @@ auto SearchGpgconfPath(const QList<QString>& candidate_paths) -> QString { auto SearchKeyDatabasePath(const QList<QString>& candidate_paths) -> QString { for (const auto& path : candidate_paths) { - GF_CORE_LOG_DEBUG("searh for candidate key database path: {}", path); if (VerifyKeyDatabasePath(QFileInfo(path))) { return path; } @@ -97,8 +96,6 @@ auto InitGpgME(const QString& gpgconf_path, const QString& gnupg_path) -> bool { #endif if (!gnupg_path.isEmpty()) { - GF_CORE_LOG_DEBUG("gpgme set engine info, gpgconf path: {}, gnupg path: {}", - gpgconf_path, gnupg_path); CheckGpgError(gpgme_set_engine_info(GPGME_PROTOCOL_GPGCONF, gpgconf_path.toUtf8(), nullptr)); CheckGpgError(gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, @@ -121,15 +118,6 @@ auto InitGpgME(const QString& gpgconf_path, const QString& gnupg_path) -> bool { continue; } - GF_CORE_LOG_DEBUG( - "gpg context engine info: {} {} {} {}", - gpgme_get_protocol_name(engine_info->protocol), - QString(engine_info->file_name == nullptr ? "null" - : engine_info->file_name), - QString(engine_info->home_dir == nullptr ? "null" - : engine_info->home_dir), - QString(engine_info->version ? "null" : engine_info->version)); - switch (engine_info->protocol) { case GPGME_PROTOCOL_OpenPGP: find_openpgp = true; @@ -183,12 +171,11 @@ auto InitGpgME(const QString& gpgconf_path, const QString& gnupg_path) -> bool { const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gnupg_version", QString{"0.0.0"}); - GF_CORE_LOG_DEBUG("got gnupg version from rt: {}", gnupg_version); // conditional check: only support gpg 2.1.x now if (!(GFCompareSoftwareVersion(gnupg_version, "2.1.0") >= 0 && find_gpgconf && find_openpgp && find_cms)) { - GF_CORE_LOG_ERROR("gpgme env check failed, abort"); + qCWarning(core, "gpgme env check failed, abort"); return false; } @@ -249,8 +236,8 @@ auto DetectGpgConfPath() -> QString { #endif if (!VerifyGpgconfPath(QFileInfo(gnupg_install_fs_path))) { - GF_CORE_LOG_ERROR("core loaded custom gpgconf path is illegal: {}", - gnupg_install_fs_path); + qCWarning(core) << "core loaded custom gpgconf path is illegal: " + << gnupg_install_fs_path; gnupg_install_fs_path = ""; } } @@ -260,15 +247,11 @@ auto DetectGpgConfPath() -> QString { #ifdef MACOS gnupg_install_fs_path = SearchGpgconfPath( {"/usr/local/bin/gpgconf", "/opt/homebrew/bin/gpgconf"}); - GF_CORE_LOG_DEBUG("core loaded searched gpgconf path: {}", - gnupg_install_fs_path); #endif #ifdef WINDOWS gnupg_install_fs_path = SearchGpgconfPath({"C:/Program Files (x86)/gnupg/bin"}); - GF_CORE_LOG_DEBUG("core loaded searched gpgconf path: {}", - gnupg_install_fs_path); #endif } @@ -289,13 +272,10 @@ void InitGpgFrontendCore(CoreInitArgs args) { Module::UpsertRTValue("core", "env.state.basic", 0); Module::UpsertRTValue("core", "env.state.all", 0); - // initialize locale environment - GF_CORE_LOG_DEBUG("locale: {}", setlocale(LC_CTYPE, nullptr)); - auto gpgconf_install_fs_path = DetectGpgConfPath(); auto gnupg_install_fs_path = DetectGnuPGPath(gpgconf_install_fs_path); - GF_CORE_LOG_INFO("detected gpgconf path: {}", gpgconf_install_fs_path); - GF_CORE_LOG_INFO("detected gnupg path: {}", gnupg_install_fs_path); + qCInfo(core) << "detected gpgconf path: " << gpgconf_install_fs_path; + qCInfo(core) << "detected gnupg path: " << gnupg_install_fs_path; // initialize library gpgme if (!InitGpgME(gpgconf_install_fs_path, gnupg_install_fs_path)) { @@ -334,11 +314,6 @@ void InitGpgFrontendCore(CoreInitArgs args) { QString::fromLocal8Bit(qgetenv("container")) != "flatpak") .toBool(); - GF_CORE_LOG_DEBUG("core loaded if use custom key databse path: {}", - use_custom_key_database_path); - GF_CORE_LOG_DEBUG("core loaded custom key databse path: {}", - custom_key_database_path); - // check key database path QString key_database_fs_path; // user defined @@ -346,21 +321,17 @@ void InitGpgFrontendCore(CoreInitArgs args) { !custom_key_database_path.isEmpty()) { key_database_fs_path = custom_key_database_path; if (VerifyKeyDatabasePath(QFileInfo(key_database_fs_path))) { - GF_CORE_LOG_ERROR( - "core loaded custom gpg key database is illegal: {}", - key_database_fs_path); + qCWarning(core) + << "core loaded custom gpg key database is illegal: " + << key_database_fs_path; } else { use_custom_key_database_path = true; - GF_CORE_LOG_DEBUG("core loaded custom gpg key database path: {}", - key_database_fs_path); } } else { #if defined(LINUX) || defined(MACOS) use_custom_key_database_path = true; key_database_fs_path = SearchKeyDatabasePath({QDir::home().path() + "/.gnupg"}); - GF_CORE_LOG_DEBUG("core loaded searched key database path: {}", - key_database_fs_path); #endif } @@ -377,13 +348,11 @@ void InitGpgFrontendCore(CoreInitArgs args) { if (dir_info.exists() && dir_info.isDir() && dir_info.isReadable() && dir_info.isWritable()) { args.db_path = dir_info.absoluteFilePath(); - GF_CORE_LOG_INFO("using key database path: {}", - args.db_path); } else { - GF_CORE_LOG_ERROR( - "custom key database path: {}, is not point to " - "an accessible directory", - key_database_fs_path); + qCWarning(core) + << "custom key database path: " << key_database_fs_path + << ", is not point to " + "an accessible directory"; } } @@ -404,7 +373,7 @@ void InitGpgFrontendCore(CoreInitArgs args) { // exit if failed if (!ctx.Good()) { - GF_CORE_LOG_ERROR("default gnupg context init error, abort"); + qCWarning(core, "default gnupg context init error, abort"); CoreSignalStation::GetInstance()->SignalBadGnupgEnv( QCoreApplication::tr("GpgME Context initiation failed")); return -1; @@ -415,11 +384,12 @@ void InitGpgFrontendCore(CoreInitArgs args) { if (args.load_default_gpg_context) { if (!GpgKeyGetter::GetInstance().FlushKeyCache()) { CoreSignalStation::GetInstance()->SignalBadGnupgEnv( - QCoreApplication::tr("Gpg Key Detabase initiation failed")); + QCoreApplication::tr("Gpg Key Database initiation failed")); }; } - GF_CORE_LOG_DEBUG( + qCDebug( + core, "basic env checking finished, including gpgme, ctx, and key infos"); Module::UpsertRTValue("core", "env.state.basic", 1); diff --git a/src/core/GpgFrontendCore.cpp b/src/core/GpgFrontendCore.cpp index 82ed09f4..ab589abc 100644 --- a/src/core/GpgFrontendCore.cpp +++ b/src/core/GpgFrontendCore.cpp @@ -27,3 +27,5 @@ */ #include "core/GpgFrontendCore.h" + +Q_LOGGING_CATEGORY(core, "core")
\ No newline at end of file diff --git a/src/core/GpgFrontendCore.h b/src/core/GpgFrontendCore.h index f07824cf..0310804c 100644 --- a/src/core/GpgFrontendCore.h +++ b/src/core/GpgFrontendCore.h @@ -30,3 +30,11 @@ // Qt #include <QtCore> + +// declare area of core +#ifdef GF_CORE + +// declare logging category +Q_DECLARE_LOGGING_CATEGORY(core) + +#endif
\ No newline at end of file diff --git a/src/core/function/ArchiveFileOperator.cpp b/src/core/function/ArchiveFileOperator.cpp index 475ef434..0df1a284 100644 --- a/src/core/function/ArchiveFileOperator.cpp +++ b/src/core/function/ArchiveFileOperator.cpp @@ -46,14 +46,14 @@ auto CopyData(struct archive *ar, struct archive *aw) -> int { r = archive_read_data_block(ar, &buff, &size, &offset); if (r == ARCHIVE_EOF) return (ARCHIVE_OK); if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR("archive_read_data_block() failed: {}", - archive_error_string(ar)); + qCWarning(core) << "archive_read_data_block() failed: " + << archive_error_string(ar); return (r); } r = archive_write_data_block(aw, buff, size, offset); if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR("archive_write_data_block() failed: {}", - archive_error_string(aw)); + qCWarning(core) << "archive_write_data_block() failed: " + << archive_error_string(aw); return (r); } } @@ -113,8 +113,8 @@ void ArchiveFileOperator::NewArchive2DataExchanger( #endif if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR("archive_read_disk_open() failed: {}, abort...", - archive_error_string(disk)); + qCWarning(core, "archive_read_disk_open() failed: %s, abort...", + archive_error_string(disk)); archive_read_free(disk); archive_write_free(archive); return -1; @@ -125,8 +125,9 @@ void ArchiveFileOperator::NewArchive2DataExchanger( r = archive_read_next_header2(disk, entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR( - "archive_read_next_header2() failed, ret: {}, explain: {}", r, + qCWarning( + core, + "archive_read_next_header2() failed, ret: %d, explain: %s", r, archive_error_string(disk)); ret = -1; break; @@ -143,11 +144,8 @@ void ArchiveFileOperator::NewArchive2DataExchanger( #endif QFile file(source_path); -#ifdef QT5_BUILD + if (file.open(QIODevice::ReadOnly)) { -#else - if (file.open(QIODeviceBase::ReadOnly)) { -#endif // turn absolute path to relative path auto relativ_path_name = base_path.relativeFilePath(source_path); archive_entry_set_pathname(entry, relativ_path_name.toUtf8()); @@ -164,17 +162,17 @@ void ArchiveFileOperator::NewArchive2DataExchanger( r = archive_write_header(archive, entry); if (r < ARCHIVE_OK) { - GF_CORE_LOG_ERROR( - "archive_write_header() failed, ret: {}, explain: {} ", r, - archive_error_string(archive)); + qCWarning(core, + "archive_write_header() failed, ret: %d, explain: %s", + r, archive_error_string(archive)); continue; } if (r == ARCHIVE_FATAL) { - GF_CORE_LOG_ERROR( - "archive_write_header() failed, ret: {}, explain: {}, " - "abort ...", - r, archive_error_string(archive)); + qCWarning(core, + "archive_write_header() failed, ret: %d, explain: %s, " + "abort ...", + r, archive_error_string(archive)); ret = -1; break; } @@ -201,7 +199,6 @@ void ArchiveFileOperator::NewArchive2DataExchanger( void ArchiveFileOperator::ExtractArchiveFromDataExchanger( std::shared_ptr<GFDataExchanger> ex, const QString &target_path, const OperationCallback &cb) { - GF_CORE_LOG_INFO("target path: {}", target_path); RunIOOperaAsync( [=](const DataObjectPtr &data_object) -> GFError { auto *archive = archive_read_new(); @@ -209,17 +206,17 @@ void ArchiveFileOperator::ExtractArchiveFromDataExchanger( auto r = archive_read_support_filter_all(archive); if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR( - "archive_read_support_filter_all(), ret: {}, reason: {}", r, - archive_error_string(archive)); + qCWarning(core, + "archive_read_support_filter_all(), ret: %d, reason: %s", r, + archive_error_string(archive)); return r; } r = archive_read_support_format_all(archive); if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR( - "archive_read_support_format_all(), ret: {}, reason: {}", r, - archive_error_string(archive)); + qCWarning(core, + "archive_read_support_format_all(), ret: %d, reason: %s", r, + archive_error_string(archive)); return r; } @@ -230,16 +227,16 @@ void ArchiveFileOperator::ExtractArchiveFromDataExchanger( nullptr); if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR("archive_read_open(), ret: {}, reason: {}", r, - archive_error_string(archive)); + qCWarning(core, "archive_read_open(), ret: %d, reason: %s", r, + archive_error_string(archive)); return r; } r = archive_write_disk_set_options(ext, 0); if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR( - "archive_write_disk_set_options(), ret: {}, reason: {}", r, - archive_error_string(archive)); + qCWarning(core, + "archive_write_disk_set_options(), ret: %d, reason: %s", r, + archive_error_string(archive)); return r; } @@ -248,8 +245,8 @@ void ArchiveFileOperator::ExtractArchiveFromDataExchanger( r = archive_read_next_header(archive, &entry); if (r == ARCHIVE_EOF) break; if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR("archive_read_next_header(), ret: {}, reason: {}", - r, archive_error_string(archive)); + qCWarning(core, "archive_read_next_header(), ret: %d, reason: %s", + r, archive_error_string(archive)); break; } @@ -267,8 +264,8 @@ void ArchiveFileOperator::ExtractArchiveFromDataExchanger( r = archive_write_header(ext, entry); if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR("archive_write_header(), ret: {}, reason: {}", r, - archive_error_string(archive)); + qCWarning(core, "archive_write_header(), ret: %d, reason: %s", r, + archive_error_string(archive)); } else { r = CopyData(archive, ext); } @@ -276,13 +273,13 @@ void ArchiveFileOperator::ExtractArchiveFromDataExchanger( r = archive_read_free(archive); if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR("archive_read_free(), ret: {}, reason: {}", r, - archive_error_string(archive)); + qCWarning(core, "archive_read_free(), ret: %d, reason: %s", r, + archive_error_string(archive)); } r = archive_write_free(ext); if (r != ARCHIVE_OK) { - GF_CORE_LOG_ERROR("archive_read_free(), ret: {}, reason: {}", r, - archive_error_string(archive)); + qCWarning(core, "archive_read_free(), ret: %d, reason: %s", r, + archive_error_string(archive)); } return 0; @@ -302,8 +299,8 @@ void ArchiveFileOperator::ListArchive(const QString &archive_path) { 10240); // Note 1 if (r != ARCHIVE_OK) return; while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { - GF_CORE_LOG_DEBUG("File: {}", archive_entry_pathname(entry)); - GF_CORE_LOG_DEBUG("File Path: {}", archive_entry_pathname(entry)); + qCDebug(core, core, "File: %s", archive_entry_pathname(entry)); + qCDebug(core, core, "File Path: %s", archive_entry_pathname(entry)); archive_read_data_skip(a); // Note 2 } r = archive_read_free(a); // Note 3 diff --git a/src/core/function/CacheManager.cpp b/src/core/function/CacheManager.cpp index 719c962d..e71936fe 100644 --- a/src/core/function/CacheManager.cpp +++ b/src/core/function/CacheManager.cpp @@ -107,7 +107,6 @@ class CacheManager::Impl : public QObject { durable_cache_storage_.insert(key, value); if (!key_storage_.contains(key)) { - GF_CORE_LOG_DEBUG("register new key of cache", key); key_storage_.push_back(key); } @@ -126,8 +125,8 @@ class CacheManager::Impl : public QObject { return {}; } - auto LoadDurableCache(const QString& key, QJsonDocument default_value) - -> QJsonDocument { + auto LoadDurableCache(const QString& key, + QJsonDocument default_value) -> QJsonDocument { auto data_object_key = get_data_object_key(key); if (!durable_cache_storage_.exists(key)) { durable_cache_storage_.insert( @@ -165,9 +164,10 @@ class CacheManager::Impl : public QObject { * */ void slot_flush_cache_storage() { + qCDebug(core, "write cache to file system..."); + for (const auto& cache : durable_cache_storage_.mirror()) { auto key = get_data_object_key(cache.first); - GF_CORE_LOG_TRACE("save cache into filesystem, key {}", key); GpgFrontend::DataObjectOperator::GetInstance().SaveDataObj( key, QJsonDocument(cache.second)); } @@ -215,7 +215,7 @@ class CacheManager::Impl : public QObject { * */ void load_all_cache_storage() { - GF_CORE_LOG_DEBUG("start to load all cache from file system"); + qCDebug(core, "start to load all cache from file system"); auto stored_data = GpgFrontend::DataObjectOperator::GetInstance().GetDataObject(drk_key_); @@ -258,9 +258,8 @@ auto CacheManager::LoadDurableCache(const QString& key) -> QJsonDocument { return p_->LoadDurableCache(key); } -auto CacheManager::LoadDurableCache(const QString& key, - QJsonDocument default_value) - -> QJsonDocument { +auto CacheManager::LoadDurableCache( + const QString& key, QJsonDocument default_value) -> QJsonDocument { return p_->LoadDurableCache(key, std::move(default_value)); } diff --git a/src/core/function/CoreSignalStation.h b/src/core/function/CoreSignalStation.h index 8827c803..5c19f3b0 100644 --- a/src/core/function/CoreSignalStation.h +++ b/src/core/function/CoreSignalStation.h @@ -62,12 +62,6 @@ class GPGFRONTEND_CORE_EXPORT CoreSignalStation : public QObject { * @brief * */ - void SignalUserInputPassphraseCallback(QSharedPointer<GpgPassphraseContext>); - - /** - * @brief - * - */ void SignalBadGnupgEnv(QString); /** diff --git a/src/core/function/DataObjectOperator.cpp b/src/core/function/DataObjectOperator.cpp index cbf21f8e..dbf92cd1 100644 --- a/src/core/function/DataObjectOperator.cpp +++ b/src/core/function/DataObjectOperator.cpp @@ -36,7 +36,6 @@ namespace GpgFrontend { void DataObjectOperator::init_app_secure_key() { - GF_CORE_LOG_INFO("initializing application secure key..."); WriteFile(app_secure_key_path_, PassphraseGenerator::GetInstance().Generate(256).toUtf8()); QFile::setPermissions(app_secure_key_path_, @@ -50,8 +49,8 @@ DataObjectOperator::DataObjectOperator(int channel) QByteArray key; if (!ReadFile(app_secure_key_path_, key)) { - GF_CORE_LOG_ERROR("failed to read app secure key file: {}", - app_secure_key_path_); + qCWarning(core) << "failed to read app secure key file: " + << app_secure_key_path_; // unsafe mode key = {}; } @@ -85,8 +84,6 @@ auto DataObjectOperator::SaveDataObj(const QString& key, QAESEncryption(QAESEncryption::AES_256, QAESEncryption::ECB, QAESEncryption::Padding::ISO) .encode(value.toJson(), hash_key_); - GF_CORE_LOG_TRACE("saving data object {} to disk {} , size: {} bytes", - hash_obj_key, target_obj_path, encoded_data.size()); // recreate if not exists if (!QDir(app_data_objs_path_).exists()) { @@ -94,7 +91,7 @@ auto DataObjectOperator::SaveDataObj(const QString& key, } if (!WriteFile(target_obj_path, encoded_data)) { - GF_CORE_LOG_ERROR("failed to write data object to disk: {}", key); + qCWarning(core) << "failed to write data object to disk: " << key; } return key.isEmpty() ? hash_obj_key : QString(); } @@ -102,20 +99,19 @@ auto DataObjectOperator::SaveDataObj(const QString& key, auto DataObjectOperator::GetDataObject(const QString& key) -> std::optional<QJsonDocument> { try { - GF_CORE_LOG_TRACE("try to get data object from disk, key: {}", key); auto hash_obj_key = QCryptographicHash::hash(hash_key_ + key.toUtf8(), QCryptographicHash::Sha256) .toHex(); const auto obj_path = app_data_objs_path_ + "/" + hash_obj_key; if (!QFileInfo(obj_path).exists()) { - GF_CORE_LOG_WARN("data object not found from disk, key: {}", key); + qCWarning(core) << "data object not found from disk, key: " << key; return {}; } QByteArray encoded_data; if (!ReadFile(obj_path, encoded_data)) { - GF_CORE_LOG_ERROR("failed to read data object from disk, key: {}", key); + qCWarning(core) << "failed to read data object from disk, key: " << key; return {}; } @@ -124,11 +120,11 @@ auto DataObjectOperator::GetDataObject(const QString& key) auto decoded_data = encryption.removePadding(encryption.decode(encoded_data, hash_key_)); - GF_CORE_LOG_TRACE("data object has been decoded, key: {}, data: {}", key, - decoded_data); + return QJsonDocument::fromJson(decoded_data); } catch (...) { - GF_CORE_LOG_ERROR("failed to get data object, caught exception: {}", key); + qCWarning(core) << "failed to get data object:" << key + << " caught exception."; return {}; } } diff --git a/src/core/function/GlobalSettingStation.cpp b/src/core/function/GlobalSettingStation.cpp index 45ab11f9..e123f249 100644 --- a/src/core/function/GlobalSettingStation.cpp +++ b/src/core/function/GlobalSettingStation.cpp @@ -40,13 +40,11 @@ class GlobalSettingStation::Impl { * */ explicit Impl() noexcept { - GF_CORE_LOG_INFO("app path: {}", GetAppDir()); - GF_CORE_LOG_INFO("app working path: {}", working_path_); + qCInfo(core) << "app path: " << GetAppDir(); + qCInfo(core) << "app working path: " << working_path_; auto portable_file_path = working_path_ + "/PORTABLE.txt"; if (QFileInfo(portable_file_path).exists()) { - GF_CORE_LOG_INFO( - "dectected portable mode, reconfiguring config and data path..."); Module::UpsertRTValue("core", "env.state.portable", 1); app_data_path_ = working_path_; @@ -56,11 +54,11 @@ class GlobalSettingStation::Impl { portable_mode_ = true; } - GF_CORE_LOG_INFO("app data path: {}", app_data_path_); - GF_CORE_LOG_INFO("app log path: {}", app_log_path_); + qCInfo(core) << "app data path: " << app_data_path_; + qCInfo(core) << "app log path: " << app_log_path_; #ifdef WINDOWS - GF_CORE_LOG_INFO("app config path: {}", app_config_path_); + qCInfo(core) << "app config path: " << app_config_path_; #endif #ifdef WINDOWS diff --git a/src/core/function/GlobalSettingStation.h b/src/core/function/GlobalSettingStation.h index c907bdb5..d3287ac2 100644 --- a/src/core/function/GlobalSettingStation.h +++ b/src/core/function/GlobalSettingStation.h @@ -28,6 +28,8 @@ #pragma once +#include <qsettings.h> + #include "core/function/basic/GpgFunctionObject.h" namespace GpgFrontend { diff --git a/src/core/function/KeyPackageOperator.cpp b/src/core/function/KeyPackageOperator.cpp index d185b0ef..d4642cf7 100644 --- a/src/core/function/KeyPackageOperator.cpp +++ b/src/core/function/KeyPackageOperator.cpp @@ -28,6 +28,7 @@ #include "KeyPackageOperator.h" +#include <qglobal.h> #include <qt-aes/qaesencryption.h> #include "core/function/KeyPackageOperator.h" @@ -44,7 +45,7 @@ namespace GpgFrontend { auto KeyPackageOperator::GeneratePassphrase(const QString& phrase_path, QString& phrase) -> bool { phrase = PassphraseGenerator::GetInstance().Generate(256); - GF_CORE_LOG_DEBUG("generated passphrase: {} bytes", phrase.size()); + qCDebug(core, "generated passphrase: %lld bytes", phrase.size()); return WriteFile(phrase_path, phrase.toUtf8()); } @@ -53,13 +54,11 @@ void KeyPackageOperator::GenerateKeyPackage(const QString& key_package_path, const KeyArgsList& keys, QString& phrase, bool secret, const OperationCallback& cb) { - GF_CORE_LOG_DEBUG("generating key package: {}", key_package_name); - GpgKeyImportExporter::GetInstance().ExportAllKeys( keys, secret, true, [=](GpgError err, const DataObjectPtr& data_obj) { if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { - GF_LOG_ERROR("export keys error, reason: {}", - DescribeGpgErrCode(err).second); + qCWarning(core) << "export keys error, reason: " + << DescribeGpgErrCode(err).second; cb(-1, data_obj); return; } @@ -78,7 +77,6 @@ void KeyPackageOperator::GenerateKeyPackage(const QString& key_package_path, QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB, QAESEncryption::Padding::ISO); auto encoded_data = encryption.encode(data, hash_key); - GF_CORE_LOG_DEBUG("writing key package, name: {}", key_package_name); cb(WriteFile(key_package_path, encoded_data) ? 0 : -1, TransferParams()); @@ -91,20 +89,18 @@ void KeyPackageOperator::ImportKeyPackage(const QString& key_package_path, const OperationCallback& cb) { RunOperaAsync( [=](const DataObjectPtr& data_object) -> GFError { - GF_CORE_LOG_DEBUG("importing key package: {}", key_package_path); - QByteArray encrypted_data; ReadFile(key_package_path, encrypted_data); if (encrypted_data.isEmpty()) { - GF_CORE_LOG_ERROR("failed to read key package: {}", key_package_path); + qCWarning(core) << "failed to read key package: " << key_package_path; return -1; }; QByteArray passphrase; ReadFile(phrase_path, passphrase); if (passphrase.size() != 256) { - GF_CORE_LOG_ERROR("passphrase size mismatch: {}", phrase_path); + qCWarning(core) << "passphrase size mismatch: " << phrase_path; return -1; } diff --git a/src/core/function/LoggerManager.cpp b/src/core/function/LoggerManager.cpp deleted file mode 100644 index c7088128..00000000 --- a/src/core/function/LoggerManager.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "LoggerManager.h" - -#include <spdlog/async.h> -#include <spdlog/common.h> -#include <spdlog/sinks/rotating_file_sink.h> -#include <spdlog/sinks/stdout_color_sinks.h> - -#include "core/function/GlobalSettingStation.h" - -namespace GpgFrontend { - -std::shared_ptr<spdlog::logger> LoggerManager::default_logger = nullptr; -spdlog::level::level_enum LoggerManager::default_log_level = - spdlog::level::debug; - -LoggerManager::LoggerManager(int channel) - : SingletonFunctionObject<LoggerManager>(channel) { - spdlog::init_thread_pool(1024, 2); - spdlog::flush_every(std::chrono::seconds(5)); -} - -LoggerManager::~LoggerManager() { -#ifdef WINDOWS - // Under VisualStudio, this must be called before main finishes to workaround - // a known VS issue - spdlog::drop_all(); - spdlog::shutdown(); -#endif - - if (default_logger) default_logger = nullptr; -} - -auto LoggerManager::GetLogger(const QString& id) - -> std::shared_ptr<spdlog::logger> { - auto m_it = logger_map_.find(id); - if (m_it == logger_map_.end()) return GetDefaultLogger(); - return m_it->second; -} - -auto LoggerManager::RegisterAsyncLogger(const QString& id, - spdlog::level::level_enum level) - -> std::shared_ptr<spdlog::logger> { - // get the log directory - auto log_file_path = - GlobalSettingStation::GetInstance().GetLogDir() + "/" + id + ".log"; - - // sinks - std::vector<spdlog::sink_ptr> sinks; - sinks.push_back(GpgFrontend::SecureCreateSharedObject< - spdlog::sinks::stderr_color_sink_mt>()); - sinks.push_back(GpgFrontend::SecureCreateSharedObject< - spdlog::sinks::rotating_file_sink_mt>( - log_file_path.toUtf8().constData(), 1048576 * 32, 8)); - - // logger - auto logger = GpgFrontend::SecureCreateSharedObject<spdlog::async_logger>( - id.toStdString(), begin(sinks), end(sinks), spdlog::thread_pool()); - logger->set_pattern( - "[%H:%M:%S.%e] [T:%t] [%=6n] %^[%=8l]%$ [%s:%#] [%!] -> %v (+%ius)"); - - // set the level of logger - logger->set_level(level); - - // flush policy -#ifdef DEBUG - logger->flush_on(spdlog::level::trace); -#else - logger->flush_on(spdlog::level::err); -#endif - - logger_map_[id] = logger; - return logger; -} - -auto LoggerManager::RegisterSyncLogger(const QString& id, - spdlog::level::level_enum level) - -> std::shared_ptr<spdlog::logger> { - // get the log directory - auto log_file_path = - GlobalSettingStation::GetInstance().GetLogDir() + "/" + id + ".log"; - - // sinks - std::vector<spdlog::sink_ptr> sinks; - sinks.push_back(GpgFrontend::SecureCreateSharedObject< - spdlog::sinks::stderr_color_sink_mt>()); - sinks.push_back(GpgFrontend::SecureCreateSharedObject< - spdlog::sinks::rotating_file_sink_mt>( - log_file_path.toUtf8().constData(), 1048576 * 32, 8)); - - // logger - auto logger = GpgFrontend::SecureCreateSharedObject<spdlog::logger>( - id.toStdString(), begin(sinks), end(sinks)); - logger->set_pattern( - "[%H:%M:%S.%e] [T:%t] [%=6n] %^[%=8l]%$ [%s:%#] [%!] -> %v (+%ius)"); - - // set the level of logger - logger->set_level(level); - - logger_map_[id] = logger; - return logger; -} - -auto LoggerManager::GetDefaultLogger() -> std::shared_ptr<spdlog::logger> { - if (default_logger == nullptr) { - // sinks - std::vector<spdlog::sink_ptr> sinks; - sinks.push_back(GpgFrontend::SecureCreateSharedObject< - spdlog::sinks::stderr_color_sink_mt>()); - - // logger - auto logger = GpgFrontend::SecureCreateSharedObject<spdlog::logger>( - "default", begin(sinks), end(sinks)); - logger->set_pattern( - "[%H:%M:%S.%e] [T:%t] [%=6n] %^[%=8l]%$ [%s:%#] [%!] -> %v (+%ius)"); - - // set the level of logger - logger->set_level(default_log_level); - spdlog::set_default_logger(logger); - default_logger = logger; - } - return default_logger; -} - -void LoggerManager::SetDefaultLogLevel(spdlog::level::level_enum level) { - default_log_level = level; -} -} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/LoggerManager.h b/src/core/function/LoggerManager.h deleted file mode 100644 index 78fecc3c..00000000 --- a/src/core/function/LoggerManager.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include "core/function/basic/GpgFunctionObject.h" - -namespace spdlog { -class logger; -} - -namespace GpgFrontend { - -class GPGFRONTEND_CORE_EXPORT LoggerManager - : public SingletonFunctionObject<LoggerManager> { - public: - explicit LoggerManager(int channel); - - ~LoggerManager() override; - - auto RegisterAsyncLogger(const QString& id, spdlog::level::level_enum) - -> std::shared_ptr<spdlog::logger>; - - auto RegisterSyncLogger(const QString& id, spdlog::level::level_enum) - -> std::shared_ptr<spdlog::logger>; - - auto GetLogger(const QString& id) -> std::shared_ptr<spdlog::logger>; - - static auto GetDefaultLogger() -> std::shared_ptr<spdlog::logger>; - - static void SetDefaultLogLevel(spdlog::level::level_enum); - - private: - static spdlog::level::level_enum default_log_level; - static std::shared_ptr<spdlog::logger> default_logger; - - std::map<QString, std::shared_ptr<spdlog::logger>> logger_map_; -}; - -} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/SecureMemoryAllocator.cpp b/src/core/function/SecureMemoryAllocator.cpp index fccd09fe..651e4085 100644 --- a/src/core/function/SecureMemoryAllocator.cpp +++ b/src/core/function/SecureMemoryAllocator.cpp @@ -28,36 +28,40 @@ #include "SecureMemoryAllocator.h" -#if !defined(MACOS) && defined(DEBUG) +#ifndef MACOS + #include <mimalloc.h> -#endif namespace GpgFrontend { auto SecureMemoryAllocator::Allocate(std::size_t size) -> void* { -#if !defined(MACOS) && defined(DEBUG) auto* addr = mi_malloc(size); -#else - auto* addr = malloc(size); -#endif return addr; } auto SecureMemoryAllocator::Reallocate(void* ptr, std::size_t size) -> void* { -#if !defined(MACOS) && defined(DEBUG) auto* addr = mi_realloc(ptr, size); + return addr; +} + +void SecureMemoryAllocator::Deallocate(void* p) { mi_free(p); } + #else + +namespace GpgFrontend { + +auto SecureMemoryAllocator::Allocate(std::size_t size) -> void* { + auto* addr = malloc(size); + return addr; +} + +auto SecureMemoryAllocator::Reallocate(void* ptr, std::size_t size) -> void* { auto* addr = realloc(ptr, size); -#endif return addr; } -void SecureMemoryAllocator::Deallocate(void* p) { -#if !defined(MACOS) && defined(DEBUG) - mi_free(p); -#else - free(p); +void SecureMemoryAllocator::Deallocate(void* p) { free(p); } + #endif -} } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/SecureMemoryAllocator.h b/src/core/function/SecureMemoryAllocator.h index e86d54d6..77295f53 100644 --- a/src/core/function/SecureMemoryAllocator.h +++ b/src/core/function/SecureMemoryAllocator.h @@ -29,7 +29,6 @@ #pragma once #include "core/GpgFrontendCoreExport.h" -#include "core/utils/LogUtils.h" namespace GpgFrontend { diff --git a/src/core/function/basic/ChannelObject.cpp b/src/core/function/basic/ChannelObject.cpp index 18449ddb..1d9d60b5 100644 --- a/src/core/function/basic/ChannelObject.cpp +++ b/src/core/function/basic/ChannelObject.cpp @@ -39,7 +39,7 @@ ChannelObject::ChannelObject(int channel, QString type) #ifdef DEBUG ChannelObject::~ChannelObject() noexcept { - // using iostream instead of spdlog bacause at this time spdlog may have + // using iostream instead of log bacause at this time log object may have // already been destroyed. QTextStream(stdout) << "releasing channel object: " << this->type_ << Qt::endl; diff --git a/src/core/function/basic/GpgFunctionObject.cpp b/src/core/function/basic/GpgFunctionObject.cpp index e9e444f1..2e531c15 100644 --- a/src/core/function/basic/GpgFunctionObject.cpp +++ b/src/core/function/basic/GpgFunctionObject.cpp @@ -44,8 +44,8 @@ std::mutex g_function_object_mutex_map_lock; std::map<size_t, FunctionObjectTypeLockInfo> g_function_object_mutex_map; namespace GpgFrontend { -auto GetGlobalFunctionObjectChannelLock(const std::type_info& type, int channel) - -> std::mutex& { +auto GetGlobalFunctionObjectChannelLock(const std::type_info& type, + int channel) -> std::mutex& { std::lock_guard<std::mutex> lock_guard(g_function_object_mutex_map_lock); auto& channel_map = g_function_object_mutex_map[type.hash_code()]; return channel_map.channel_lock_map[channel]; @@ -64,24 +64,17 @@ auto GetGlobalFunctionObjectTypeLock(const std::type_info& type) * @param channel * @return T& */ -auto GetChannelObjectInstance(const std::type_info& type, int channel) - -> ChannelObject* { - GF_DEFAULT_LOG_TRACE("try to get instance of type: {} at channel: {}", - type.name(), channel); - +auto GetChannelObjectInstance(const std::type_info& type, + int channel) -> ChannelObject* { // lock this channel std::lock_guard<std::mutex> guard( GetGlobalFunctionObjectChannelLock(type, channel)); auto* p_storage = SingletonStorageCollection::GetInstance(false)->GetSingletonStorage(type); - GF_DEFAULT_LOG_TRACE("get singleton storage result, p_storage: {}", - static_cast<void*>(p_storage)); auto* p_pbj = static_cast<ChannelObject*>(p_storage->FindObjectInChannel(channel)); - GF_DEFAULT_LOG_TRACE("find channel object result, channel {}, p_pbj: {}", - channel, static_cast<void*>(p_pbj)); return p_pbj; } @@ -95,8 +88,6 @@ auto CreateChannelObjectInstance(const std::type_info& type, int channel, auto* p_storage = SingletonStorageCollection::GetInstance(false)->GetSingletonStorage(type); - GF_DEFAULT_LOG_TRACE("create channel object, channel {}, type: {}", channel, - type.name()); // do create object of this channel return p_storage->SetObjectInChannel(channel, std::move(channel_object)); diff --git a/src/core/function/basic/SingletonStorage.cpp b/src/core/function/basic/SingletonStorage.cpp index eab71e0f..fd583820 100644 --- a/src/core/function/basic/SingletonStorage.cpp +++ b/src/core/function/basic/SingletonStorage.cpp @@ -53,8 +53,7 @@ class SingletonStorage::Impl { std::shared_lock<std::shared_mutex> lock(instances_mutex_); ins_it = instances_map_.find(channel); if (ins_it == instances_map_.end()) { - GF_DEFAULT_LOG_TRACE("cannot find channel object, channel: {}", - channel); + qCDebug(core, "cannot find channel object, channel: %d", channel); return nullptr; } return ins_it->second.get(); @@ -72,14 +71,14 @@ class SingletonStorage::Impl { auto SetObjectInChannel(int channel, ChannelObjectPtr p_obj) -> GpgFrontend::ChannelObject* { - GF_DEFAULT_LOG_TRACE( - "set channel object, type: {} in channel: {}, address: {}", - typeid(p_obj.get()).name(), channel, static_cast<void*>(p_obj.get())); + qCDebug(core, "set channel object, type: %s in channel: %d, address: %p", + typeid(p_obj.get()).name(), channel, + static_cast<void*>(p_obj.get())); assert(p_obj != nullptr); if (p_obj == nullptr) { - GF_DEFAULT_LOG_ERROR( - "cannot set a nullptr as a channel obejct of channel: {}", channel); + qCWarning(core, "cannot set a nullptr as a channel object of channel: %d", + channel); return nullptr; } @@ -87,17 +86,16 @@ class SingletonStorage::Impl { auto* raw_obj = p_obj.get(); { - GF_DEFAULT_LOG_TRACE( - "register channel object to instances map, " - "channel: {}, address: {}", - channel, static_cast<void*>(p_obj.get())); + qCDebug(core, + "register channel object to instances map, " + "channel: %d, address: %p", + channel, static_cast<void*>(p_obj.get())); std::unique_lock<std::shared_mutex> lock(instances_mutex_); instances_map_[channel] = std::move(p_obj); } - GF_DEFAULT_LOG_TRACE( - "set channel: {} success, current channel object address: {}", channel, - static_cast<void*>(raw_obj)); + qCDebug(core, "set channel: %d success, current channel object address: %p", + channel, static_cast<void*>(raw_obj)); return raw_obj; } diff --git a/src/core/function/basic/SingletonStorageCollection.cpp b/src/core/function/basic/SingletonStorageCollection.cpp index c22b5242..1eee087a 100644 --- a/src/core/function/basic/SingletonStorageCollection.cpp +++ b/src/core/function/basic/SingletonStorageCollection.cpp @@ -49,9 +49,9 @@ class SingletonStorageCollection::Impl { static auto GetInstance(bool force_refresh) -> SingletonStorageCollection* { if (force_refresh || global_instance == nullptr) { global_instance = SecureCreateUniqueObject<SingletonStorageCollection>(); - GF_DEFAULT_LOG_TRACE( - "a new global singleton storage collection created, address: {}", - static_cast<void*>(global_instance.get())); + qCDebug(core, + "a new global singleton storage collection created, address: %p", + static_cast<void*>(global_instance.get())); } return global_instance.get(); } @@ -80,10 +80,6 @@ class SingletonStorageCollection::Impl { } if (ins_it == storages_map_.end()) { auto storage = SecureCreateUniqueObject<SingletonStorage>(); - GF_DEFAULT_LOG_TRACE( - "hash: {} created, singleton storage address: {} type_name: {}", - hash, static_cast<void*>(storage.get()), type_id.name()); - { std::unique_lock<std::shared_mutex> lock(storages_mutex_); storages_map_.insert({hash, std::move(storage)}); @@ -110,8 +106,9 @@ auto GpgFrontend::SingletonStorageCollection::GetInstance(bool force_refresh) } void SingletonStorageCollection::Destroy() { - GF_DEFAULT_LOG_TRACE( - "global singleton storage collection is about to destroy, address: {}", + qCDebug( + core, + "global singleton storage collection is about to destroy, address: %p", static_cast<void*>(global_instance.get())); return SingletonStorageCollection::Impl::Destroy(); } diff --git a/src/core/function/gpg/GpgAdvancedOperator.cpp b/src/core/function/gpg/GpgAdvancedOperator.cpp index cb8fec00..18b38460 100644 --- a/src/core/function/gpg/GpgAdvancedOperator.cpp +++ b/src/core/function/gpg/GpgAdvancedOperator.cpp @@ -39,10 +39,9 @@ void GpgFrontend::GpgAdvancedOperator::ClearGpgPasswordCache( OperationCallback cb) { const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gpgconf_path", QString{}); - GF_CORE_LOG_DEBUG("got gpgconf path from rt: {}", gpgconf_path); if (gpgconf_path.isEmpty()) { - GF_CORE_LOG_ERROR("cannot get valid gpgconf path from rt, abort."); + qCWarning(core, "cannot get valid gpgconf path from rt, abort."); cb(-1, TransferParams()); return; } @@ -51,7 +50,6 @@ void GpgFrontend::GpgAdvancedOperator::ClearGpgPasswordCache( {gpgconf_path, QStringList{"--reload", "gpg-agent"}, [=](int exit_code, const QString & /*p_out*/, const QString & /*p_err*/) { - GF_CORE_LOG_DEBUG("gpgconf reload exit code: {}", exit_code); cb(exit_code == 0 ? 0 : -1, TransferParams()); }}); } @@ -60,10 +58,9 @@ void GpgFrontend::GpgAdvancedOperator::ReloadGpgComponents( OperationCallback cb) { const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gpgconf_path", QString{}); - GF_CORE_LOG_DEBUG("got gpgconf path from rt: {}", gpgconf_path); if (gpgconf_path.isEmpty()) { - GF_CORE_LOG_ERROR("cannot get valid gpgconf path from rt, abort."); + qCWarning(core, "cannot get valid gpgconf path from rt, abort."); cb(-1, TransferParams()); return; } @@ -71,7 +68,7 @@ void GpgFrontend::GpgAdvancedOperator::ReloadGpgComponents( GpgFrontend::GpgCommandExecutor::ExecuteSync( {gpgconf_path, QStringList{"--reload"}, [=](int exit_code, const QString &, const QString &) { - GF_CORE_LOG_DEBUG("gpgconf reload exit code: {}", exit_code); + qCDebug(core, "gpgconf reload exit code: %d", exit_code); cb(exit_code == 0 ? 0 : -1, TransferParams()); }}); } @@ -79,59 +76,53 @@ void GpgFrontend::GpgAdvancedOperator::ReloadGpgComponents( void GpgFrontend::GpgAdvancedOperator::KillAllGpgComponents() { const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gpgconf_path", QString{}); - GF_CORE_LOG_DEBUG("got gpgconf path from rt: {}", gpgconf_path); if (gpgconf_path.isEmpty()) { - GF_CORE_LOG_ERROR("cannot get valid gpgconf path from rt, abort."); + qCWarning(core, "cannot get valid gpgconf path from rt, abort."); return; } GpgFrontend::GpgCommandExecutor::ExecuteSync( {gpgconf_path, QStringList{"--verbose", "--kill", "all"}, [=](int exit_code, const QString &p_out, const QString &p_err) { - GF_CORE_LOG_DEBUG("gpgconf --kill all command got exit code: {}", - exit_code); bool success = true; if (exit_code != 0) { success = false; - GF_CORE_LOG_ERROR( - "gpgconf execute error, process stderr: {}, process stdout: {}", - p_err, p_out); + qCWarning(core) << "gpgconf execute error, process stderr: " << p_err + << ", process stdout: " << p_out; return; } - GF_CORE_LOG_DEBUG("gpgconf --kill --all execute result: {}", success); + qCDebug(core, "gpgconf --kill --all execute result: %d", success); }}); } void GpgFrontend::GpgAdvancedOperator::RestartGpgComponents() { const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gpgconf_path", QString{}); - GF_CORE_LOG_DEBUG("got gpgconf path from rt: {}", gpgconf_path); if (gpgconf_path.isEmpty()) { - GF_CORE_LOG_ERROR("cannot get valid gpgconf path from rt, abort."); + qCWarning(core, "cannot get valid gpgconf path from rt, abort."); return; } GpgFrontend::GpgCommandExecutor::ExecuteSync( {gpgconf_path, QStringList{"--verbose", "--kill", "all"}, [=](int exit_code, const QString &p_out, const QString &p_err) { - GF_CORE_LOG_DEBUG("gpgconf --kill all command got exit code: {}", - exit_code); + qCDebug(core, "gpgconf --kill all command got exit code: %d", + exit_code); bool success = true; if (exit_code != 0) { success = false; - GF_CORE_LOG_ERROR( - "gpgconf execute error, process stderr: {}, process stdout: {}", - p_err, p_out); + qCWarning(core) << "gpgconf execute error, process stderr: " << p_err + << ", process stdout: " << p_out; return; } - GF_CORE_LOG_DEBUG("gpgconf --kill --all execute result: {}", success); + qCDebug(core, "gpgconf --kill --all execute result: %d", success); if (!success) { - GF_CORE_LOG_ERROR( - "restart all component after core initilized failed"); + qCWarning(core, + "restart all component after core initilized failed"); Module::UpsertRTValue( "core", "gpg_advanced_operator.restart_gpg_components", false); return; @@ -150,10 +141,9 @@ void GpgFrontend::GpgAdvancedOperator::RestartGpgComponents() { void GpgFrontend::GpgAdvancedOperator::ResetConfigures(OperationCallback cb) { const auto gpgconf_path = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gpgconf_path", QString{}); - GF_CORE_LOG_DEBUG("got gpgconf path from rt: {}", gpgconf_path); if (gpgconf_path.isEmpty()) { - GF_CORE_LOG_ERROR("cannot get valid gpgconf path from rt, abort."); + qCWarning(core, "cannot get valid gpgconf path from rt, abort."); cb(-1, TransferParams()); return; } @@ -161,7 +151,7 @@ void GpgFrontend::GpgAdvancedOperator::ResetConfigures(OperationCallback cb) { GpgFrontend::GpgCommandExecutor::ExecuteSync( {gpgconf_path, QStringList{"--apply-defaults"}, [=](int exit_code, const QString &, const QString &) { - GF_CORE_LOG_DEBUG("gpgconf apply-defaults exit code: {}", exit_code); + qCDebug(core, "gpgconf apply-defaults exit code: %d", exit_code); cb(exit_code == 0 ? 0 : -1, TransferParams()); }}); } @@ -174,14 +164,12 @@ void GpgFrontend::GpgAdvancedOperator::StartGpgAgent(OperationCallback cb) { const auto gpg_agent_path = Module::RetrieveRTValueTypedOrDefault<>( kGnuPGInfoGatheringModuleID, "gnupg.gpg_agent_path", QString{}); - GF_CORE_LOG_DEBUG("got gnupg agent path from rt: {}", gpg_agent_path); const auto home_path = Module::RetrieveRTValueTypedOrDefault<>( kGnuPGInfoGatheringModuleID, "gnupg.home_path", QString{}); - GF_CORE_LOG_DEBUG("got gnupg home path from rt: {}", home_path); if (gpg_agent_path.isEmpty()) { - GF_CORE_LOG_ERROR("cannot get valid gpg agent path from rt, abort."); + qCWarning(core, "cannot get valid gpg agent path from rt, abort."); cb(-1, TransferParams()); return; } @@ -189,7 +177,7 @@ void GpgFrontend::GpgAdvancedOperator::StartGpgAgent(OperationCallback cb) { GpgFrontend::GpgCommandExecutor::ExecuteSync( {gpg_agent_path, QStringList{"--homedir", home_path, "--daemon"}, [=](int exit_code, const QString &, const QString &) { - GF_CORE_LOG_DEBUG("gpgconf daemon exit code: {}", exit_code); + qCDebug(core, "gpgconf daemon exit code: %d", exit_code); cb(exit_code >= 0 ? 0 : -1, TransferParams()); }}); } @@ -202,14 +190,12 @@ void GpgFrontend::GpgAdvancedOperator::StartDirmngr(OperationCallback cb) { const auto dirmngr_path = Module::RetrieveRTValueTypedOrDefault<>( kGnuPGInfoGatheringModuleID, "gnupg.dirmngr_path", QString{}); - GF_CORE_LOG_DEBUG("got gnupg dirmngr path from rt: {}", dirmngr_path); const auto home_path = Module::RetrieveRTValueTypedOrDefault<>( kGnuPGInfoGatheringModuleID, "gnupg.home_path", QString{}); - GF_CORE_LOG_DEBUG("got gnupg home path from rt: {}", home_path); if (dirmngr_path.isEmpty()) { - GF_CORE_LOG_ERROR("cannot get valid dirmngr path from rt, abort."); + qCWarning(core, "cannot get valid dirmngr path from rt, abort."); cb(-1, TransferParams()); return; } @@ -217,7 +203,7 @@ void GpgFrontend::GpgAdvancedOperator::StartDirmngr(OperationCallback cb) { GpgFrontend::GpgCommandExecutor::ExecuteSync( {dirmngr_path, QStringList{"--homedir", home_path, "--daemon"}, [=](int exit_code, const QString &, const QString &) { - GF_CORE_LOG_DEBUG("gpgconf daemon exit code: {}", exit_code); + qCDebug(core, "gpgconf daemon exit code: %d", exit_code); cb(exit_code >= 0 ? 0 : -1, TransferParams()); }}); } @@ -230,14 +216,12 @@ void GpgFrontend::GpgAdvancedOperator::StartKeyBoxd(OperationCallback cb) { const auto keyboxd_path = Module::RetrieveRTValueTypedOrDefault<>( kGnuPGInfoGatheringModuleID, "gnupg.keyboxd_path", QString{}); - GF_CORE_LOG_DEBUG("got gnupg keyboxd path from rt: {}", keyboxd_path); const auto home_path = Module::RetrieveRTValueTypedOrDefault<>( kGnuPGInfoGatheringModuleID, "gnupg.home_path", QString{}); - GF_CORE_LOG_DEBUG("got gnupg home path from rt: {}", home_path); if (keyboxd_path.isEmpty()) { - GF_CORE_LOG_ERROR("cannot get valid keyboxd path from rt, abort."); + qCWarning(core, "cannot get valid keyboxd path from rt, abort."); cb(-1, TransferParams()); return; } @@ -245,7 +229,7 @@ void GpgFrontend::GpgAdvancedOperator::StartKeyBoxd(OperationCallback cb) { GpgFrontend::GpgCommandExecutor::ExecuteSync( {keyboxd_path, QStringList{"--homedir", home_path, "--daemon"}, [=](int exit_code, const QString &, const QString &) { - GF_CORE_LOG_DEBUG("gpgconf daemon exit code: {}", exit_code); + qCDebug(core, "gpgconf daemon exit code: %d", exit_code); cb(exit_code >= 0 ? 0 : -1, TransferParams()); }}); } diff --git a/src/core/function/gpg/GpgBasicOperator.cpp b/src/core/function/gpg/GpgBasicOperator.cpp index 8b62aad0..d7106a33 100644 --- a/src/core/function/gpg/GpgBasicOperator.cpp +++ b/src/core/function/gpg/GpgBasicOperator.cpp @@ -251,10 +251,9 @@ void GpgBasicOperator::Sign(const KeyArgsList& signers, cb, "gpgme_op_sign", "2.1.0"); } -auto GpgBasicOperator::SignSync(const KeyArgsList& signers, - const GFBuffer& in_buffer, GpgSignMode mode, - bool ascii) - -> std::tuple<GpgError, DataObjectPtr> { +auto GpgBasicOperator::SignSync( + const KeyArgsList& signers, const GFBuffer& in_buffer, GpgSignMode mode, + bool ascii) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( [=](const DataObjectPtr& data_object) -> GpgError { if (signers.empty()) return GPG_ERR_CANCELED; @@ -391,15 +390,14 @@ void GpgBasicOperator::SetSigners(const KeyArgsList& signers, bool ascii) { gpgme_signers_clear(ctx); for (const GpgKey& key : signers) { - GF_CORE_LOG_DEBUG("key fpr: {}", key.GetFingerprint()); + qCDebug(core) << "signer's key fpr: " << key.GetFingerprint(); if (key.IsHasActualSigningCapability()) { - GF_CORE_LOG_DEBUG("signer"); auto error = gpgme_signers_add(ctx, gpgme_key_t(key)); CheckGpgError(error); } } if (signers.size() != gpgme_signers_count(ctx_.DefaultContext())) - GF_CORE_LOG_DEBUG("not all signers added"); + qCDebug(core, "not all signers added"); } auto GpgBasicOperator::GetSigners(bool ascii) -> std::unique_ptr<KeyArgsList> { diff --git a/src/core/function/gpg/GpgCommandExecutor.cpp b/src/core/function/gpg/GpgCommandExecutor.cpp index 66c18ae1..5e0f3826 100644 --- a/src/core/function/gpg/GpgCommandExecutor.cpp +++ b/src/core/function/gpg/GpgCommandExecutor.cpp @@ -27,6 +27,8 @@ */ #include "GpgCommandExecutor.h" +#include <qglobal.h> + #include "core/model/DataObject.h" #include "core/module/Module.h" #include "core/thread/Task.h" @@ -41,18 +43,14 @@ auto BuildTaskFromExecCtx(const GpgCommandExecutor::ExecuteContext &context) const auto &interact_function = context.int_func; const auto &cmd_executor_callback = context.cb_func; - const QString joined_argument = arguments.join(" "); - - GF_CORE_LOG_DEBUG("building task: called cmd {} arguments size: {}", cmd, - arguments.size()); - Thread::Task::TaskCallback result_callback = - [cmd, joined_argument](int /*rtn*/, const DataObjectPtr &data_object) { - GF_CORE_LOG_DEBUG( - "data object args count of cmd executor result callback: {}", - data_object->GetObjectSize()); + [cmd](int /*rtn*/, const DataObjectPtr &data_object) { + qCDebug(core, + "data object args count of cmd executor result callback: %ld", + data_object->GetObjectSize()); + if (!data_object->Check<int, QString, GpgCommandExecutorCallback>()) { - GF_CORE_LOG_ERROR("data object checking failed"); + qCWarning(core, "data object checking failed"); return; } @@ -61,22 +59,17 @@ auto BuildTaskFromExecCtx(const GpgCommandExecutor::ExecuteContext &context) auto callback = ExtractParams<GpgCommandExecutorCallback>(data_object, 2); - // call callback - GF_CORE_LOG_DEBUG( - "calling custom callback from caller of cmd {} {}, " - "exit_code: {}", - cmd, joined_argument, exit_code); callback(exit_code, process_stdout, {}); }; Thread::Task::TaskRunnable runner = - [joined_argument](const DataObjectPtr &data_object) -> int { - GF_CORE_LOG_DEBUG("process runner called, data object size: {}", - data_object->GetObjectSize()); + [](const DataObjectPtr &data_object) -> int { + qCDebug(core, "process runner called, data object size: %lu", + data_object->GetObjectSize()); if (!data_object->Check<QString, QStringList, GpgCommandExecutorInteractor, GpgCommandExecutorCallback>()) { - GF_CORE_LOG_ERROR("data object checking failed"); + qCWarning(core, "data object checking failed"); return -1; } @@ -86,6 +79,7 @@ auto BuildTaskFromExecCtx(const GpgCommandExecutor::ExecuteContext &context) auto interact_func = ExtractParams<GpgCommandExecutorInteractor>(data_object, 2); auto callback = ExtractParams<GpgCommandExecutorCallback>(data_object, 3); + const QString joined_argument = arguments.join(" "); // create process auto *cmd_process = new QProcess(); @@ -106,26 +100,23 @@ auto BuildTaskFromExecCtx(const GpgCommandExecutor::ExecuteContext &context) QObject::connect( cmd_process, &QProcess::started, [cmd, joined_argument]() -> void { - GF_CORE_LOG_DEBUG( - "\n== Process Execute Started ==\nCommand: {}\nArguments: " - "{}\n========================", - cmd, joined_argument); + qCDebug(core) << "\n== Process Execute Started ==\nCommand: " << cmd + << "\nArguments: " << joined_argument + << " \n========================"; }); QObject::connect( cmd_process, &QProcess::readyReadStandardOutput, [interact_func, cmd_process]() { interact_func(cmd_process); }); - QObject::connect( - cmd_process, &QProcess::errorOccurred, - [=](QProcess::ProcessError error) { - GF_CORE_LOG_ERROR( - "caught error while executing command: {} {}, error: {}", cmd, - joined_argument, error); - }); + QObject::connect(cmd_process, &QProcess::errorOccurred, + [=](QProcess::ProcessError error) { + qCWarning(core) + << "caught error while executing command: " << cmd + << joined_argument << ", error:" << error; + }); - GF_CORE_LOG_DEBUG( - "\n== Process Execute Ready ==\nCommand: {}\nArguments: " - "{}\n========================", - cmd, joined_argument); + qCDebug(core) << "\n== Process Execute Ready ==\nCommand: " << cmd + << "\nArguments: " << joined_argument + << "\n========================"; cmd_process->start(); cmd_process->waitForFinished(); @@ -133,15 +124,13 @@ auto BuildTaskFromExecCtx(const GpgCommandExecutor::ExecuteContext &context) QString process_stdout = cmd_process->readAllStandardOutput(); int exit_code = cmd_process->exitCode(); - GF_CORE_LOG_DEBUG( - "\n==== Process Execution Summary ====\n" - "Command: {}\n" - "Arguments: {}\n" - "Exit Code: {}\n" - "---- Standard Output ----\n" - "{}\n" - "===============================", - cmd, joined_argument, exit_code, process_stdout); + qCDebug(core) << "\n==== Process Execution Summary ====\n" + << "Command: " << cmd << "\n" + << "Arguments: " << joined_argument << "\n" + << "Exit Code: " << exit_code << "\n" + << "---- Standard Output ----\n" + << process_stdout << "\n" + << "==============================="; cmd_process->close(); cmd_process->deleteLater(); @@ -177,7 +166,7 @@ void GpgCommandExecutor::ExecuteSync(ExecuteContext context) { // to arvoid dead lock issue we need to check if current thread is the same as // target thread. if it is, we can't call exec() because it will block the // current thread. - GF_CORE_LOG_TRACE("blocking until gpg command finish..."); + qCDebug(core, "blocking until gpg command finish..."); // block until task finished // this is to keep reference vaild until task finished looper.exec(); @@ -185,9 +174,6 @@ void GpgCommandExecutor::ExecuteSync(ExecuteContext context) { void GpgCommandExecutor::ExecuteConcurrentlyAsync(ExecuteContexts contexts) { for (auto &context : contexts) { - const auto &cmd = context.cmd; - GF_CORE_LOG_INFO("gpg concurrently called cmd {}", cmd); - Thread::Task *task = BuildTaskFromExecCtx(context); if (context.task_runner != nullptr) { @@ -208,15 +194,15 @@ void GpgCommandExecutor::ExecuteConcurrentlySync(ExecuteContexts contexts) { for (auto &context : contexts) { const auto &cmd = context.cmd; - GF_CORE_LOG_DEBUG("gpg concurrently called cmd: {}", cmd); + qCDebug(core) << "gpg concurrently called cmd: " << cmd; Thread::Task *task = BuildTaskFromExecCtx(context); QObject::connect(task, &Thread::Task::SignalTaskEnd, [&]() { --remaining_tasks; - GF_CORE_LOG_DEBUG("remaining tasks: {}", remaining_tasks); + qCDebug(core, "remaining tasks: %lld", remaining_tasks); if (remaining_tasks <= 0) { - GF_CORE_LOG_DEBUG("no remaining task, quit"); + qCDebug(core, "no remaining task, quit"); looper.quit(); } }); @@ -232,7 +218,7 @@ void GpgCommandExecutor::ExecuteConcurrentlySync(ExecuteContexts contexts) { target_task_runner->PostTask(task); } - GF_CORE_LOG_TRACE("blocking until concurrent gpg commands finish..."); + qCDebug(core, "blocking until concurrent gpg commands finish..."); // block until task finished // this is to keep reference vaild until task finished looper.exec(); diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 7dec318e..75e97e0c 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -32,6 +32,7 @@ #include <gpgme.h> #include <cassert> +#include <cstddef> #include <mutex> #include "core/function/CoreSignalStation.h" @@ -77,8 +78,8 @@ class GpgContext::Impl { [[nodiscard]] auto Good() const -> bool { return good_; } - auto SetPassphraseCb(const gpgme_ctx_t &ctx, gpgme_passphrase_cb_t cb) - -> bool { + auto SetPassphraseCb(const gpgme_ctx_t &ctx, + gpgme_passphrase_cb_t cb) -> bool { if (gpgme_get_pinentry_mode(ctx) != GPGME_PINENTRY_MODE_LOOPBACK) { if (CheckGpgError(gpgme_set_pinentry_mode( ctx, GPGME_PINENTRY_MODE_LOOPBACK)) != GPG_ERR_NO_ERROR) { @@ -92,31 +93,24 @@ class GpgContext::Impl { static auto TestPassphraseCb(void *opaque, const char *uid_hint, const char *passphrase_info, int last_was_bad, int fd) -> gpgme_error_t { - size_t res; -#ifdef QT5_BUILD - QString pass_qstr = "abcdefg\n"; - QByteArray pass = pass_qstr.toUtf8(); -#else - QString pass = "abcdefg\n"; -#endif - - auto passpahrase_size = pass.size(); - size_t off = 0; - - do { -#ifdef QT5_BUILD - const char *p_pass = pass.data(); - res = gpgme_io_write(fd, &p_pass[off], passpahrase_size - off); -#else - res = gpgme_io_write(fd, &pass[off], passpahrase_size - off); -#endif - if (res > 0) off += res; - } while (res > 0 && off != passpahrase_size); + QString passphrase = "abcdefg"; + auto pass_bytes = passphrase.toLatin1(); + auto pass_size = pass_bytes.size(); + const auto *p_pass_bytes = pass_bytes.constData(); + + ssize_t res = 0; + if (pass_size > 0) { + ssize_t off = 0; + ssize_t ret = 0; + do { + ret = gpgme_io_write(fd, &p_pass_bytes[off], pass_size - off); + if (ret > 0) off += ret; + } while (ret > 0 && off != pass_size); + res = off; + } res += gpgme_io_write(fd, "\n", 1); - return res == passpahrase_size + 1 - ? 0 - : gpgme_error_from_errno(GPG_ERR_CANCELED); + return res == pass_size + 1 ? 0 : gpgme_error_from_errno(GPG_ERR_CANCELED); } static auto CustomPassphraseCb(void *hook, const char *uid_hint, @@ -130,47 +124,54 @@ class GpgContext::Impl { passphrase_info != nullptr ? passphrase_info : "", prev_was_bad != 0, ask_for_new)); - GF_CORE_LOG_DEBUG( - "custom passphrase cb called, uid: {}, info: {}, last_was_bad: {}", - uid_hint == nullptr ? "<empty>" : QString{uid_hint}, - passphrase_info == nullptr ? "<empty>" : QString{passphrase_info}, - prev_was_bad); + qCDebug(core) << "custom passphrase cb called, uid: " + << (uid_hint == nullptr ? "<empty>" : QString{uid_hint}) + << ", info: " + << (passphrase_info == nullptr ? "<empty>" + : QString{passphrase_info}) + << ", last_was_bad: " << prev_was_bad; QEventLoop looper; - QObject::connect(CoreSignalStation::GetInstance(), - &CoreSignalStation::SignalUserInputPassphraseCallback, - &looper, &QEventLoop::quit); + QString passphrase = ""; + + Module::TriggerEvent( + "REQUEST_PIN_ENTRY", + {{"uid_hint", uid_hint != nullptr ? uid_hint : ""}, + {"passphrase_info", passphrase_info != nullptr ? passphrase_info : ""}, + {"prev_was_bad", (prev_was_bad != 0) ? "1" : "0"}, + {"ask_for_new", ask_for_new ? "1" : "0"}}, + [&passphrase, &looper](Module::EventIdentifier i, + Module::Event::ListenerIdentifier ei, + Module::Event::Params p) { + passphrase = p["passphrase"]; + looper.quit(); + }); - emit CoreSignalStation::GetInstance()->SignalNeedUserInputPassphrase( - context); looper.exec(); - ResetCacheValue("PinentryContext"); - auto passphrase = context->GetPassphrase().toStdString(); - auto passpahrase_size = passphrase.size(); - GF_CORE_LOG_DEBUG("get passphrase from pinentry size: {}", - passpahrase_size); - - size_t res = 0; - if (passpahrase_size > 0) { - size_t off = 0; + + auto pass_bytes = passphrase.toLatin1(); + auto pass_size = pass_bytes.size(); + const auto *p_pass_bytes = pass_bytes.constData(); + + ssize_t res = 0; + if (pass_size > 0) { + ssize_t off = 0; + ssize_t ret = 0; do { - res = gpgme_io_write(fd, &passphrase[off], passpahrase_size - off); - if (res > 0) off += res; - } while (res > 0 && off != passpahrase_size); + ret = gpgme_io_write(fd, &p_pass_bytes[off], pass_size - off); + if (ret > 0) off += ret; + } while (ret > 0 && off != pass_size); + res = off; } res += gpgme_io_write(fd, "\n", 1); - - GF_CORE_LOG_DEBUG("custom passphrase cd is about to return, res: {}", res); - return res == passpahrase_size + 1 - ? 0 - : gpgme_error_from_errno(GPG_ERR_CANCELED); + return res == pass_size + 1 ? 0 : gpgme_error_from_errno(GPG_ERR_CANCELED); } - static auto TestStatusCb(void *hook, const char *keyword, const char *args) - -> gpgme_error_t { - GF_CORE_LOG_DEBUG("keyword {}", keyword); + static auto TestStatusCb(void *hook, const char *keyword, + const char *args) -> gpgme_error_t { + qCDebug(core, "keyword %s", keyword); return GPG_ERR_NO_ERROR; } @@ -188,10 +189,11 @@ class GpgContext::Impl { const auto gpgme_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.version", QString{"0.0.0"}); - GF_CORE_LOG_DEBUG("got gpgme version version from rt: {}", gpgme_version); + qCDebug(core) << "got gpgme version version from rt: " << gpgme_version; if (gpgme_get_keylist_mode(ctx) == 0) { - GF_CORE_LOG_ERROR( + qCWarning( + core, "ctx is not a valid pointer, reported by gpgme_get_keylist_mode"); return false; } @@ -210,8 +212,8 @@ class GpgContext::Impl { const auto database_path = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.database_path", QString{}); - GF_CORE_LOG_DEBUG("ctx set engine info, db path: {}, app path: {}", - database_path, app_path); + qCDebug(core) << "ctx set engine info, db path: " << database_path + << ", app path: " << app_path; auto app_path_buffer = app_path.toUtf8(); auto database_path_buffer = database_path.toUtf8(); @@ -232,23 +234,22 @@ class GpgContext::Impl { assert(ctx != nullptr); if (args.custom_gpgconf && !args.custom_gpgconf_path.isEmpty()) { - GF_CORE_LOG_DEBUG("set custom gpgconf path: {}", - args.custom_gpgconf_path); + qCDebug(core) << "set custom gpgconf path: " << args.custom_gpgconf_path; auto err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_GPGCONF, args.custom_gpgconf_path.toUtf8(), nullptr); if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { - GF_CORE_LOG_ERROR("set gpg context engine info error: {}", - DescribeGpgErrCode(err).second); + qCWarning(core) << "set gpg context engine info error: " + << DescribeGpgErrCode(err).second; return false; } } // set context offline mode - GF_CORE_LOG_DEBUG("gpg context: offline mode: {}", args_.offline_mode); - GF_CORE_LOG_DEBUG("gpg context: auto import missing key: {}", - args_.auto_import_missing_key); + qCDebug(core, "gpg context: offline mode: %d", args_.offline_mode); + qCDebug(core, "gpg context: auto import missing key: %d", + args_.auto_import_missing_key); gpgme_set_offline(ctx, args_.offline_mode ? 1 : 0); // set option auto import missing key @@ -260,19 +261,20 @@ class GpgContext::Impl { } if (!set_ctx_key_list_mode(ctx)) { - GF_CORE_LOG_DEBUG("set ctx key list mode failed"); + qCDebug(core, "set ctx key list mode failed"); return false; } // for unit test if (args_.test_mode) { if (!SetPassphraseCb(ctx, TestPassphraseCb)) { - GF_CORE_LOG_ERROR("set passphrase cb failed, test"); + qCWarning(core, "set passphrase cb failed, test"); return false; }; - } else if (!args_.use_pinentry) { + } else if (!args_.use_pinentry && + Module::IsModuleActivate(kPinentryModuleID)) { if (!SetPassphraseCb(ctx, CustomPassphraseCb)) { - GF_CORE_LOG_DEBUG("set passphrase cb failed, custom"); + qCDebug(core, "set passphrase cb failed, custom"); return false; } } @@ -283,7 +285,7 @@ class GpgContext::Impl { } if (!set_ctx_openpgp_engine_info(ctx)) { - GF_CORE_LOG_ERROR("set gpgme context openpgp engine info failed"); + qCWarning(core, "set gpgme context openpgp engine info failed"); return false; } @@ -293,15 +295,15 @@ class GpgContext::Impl { auto binary_ctx_initialize(const GpgContextInitArgs &args) -> bool { gpgme_ctx_t p_ctx; if (auto err = CheckGpgError(gpgme_new(&p_ctx)); err != GPG_ERR_NO_ERROR) { - GF_CORE_LOG_ERROR("get new gpg context error: {}", - DescribeGpgErrCode(err).second); + qCWarning(core) << "get new gpg context error: " + << DescribeGpgErrCode(err).second; return false; } assert(p_ctx != nullptr); binary_ctx_ref_ = p_ctx; if (!common_ctx_initialize(binary_ctx_ref_, args)) { - GF_CORE_LOG_ERROR("get new ctx failed, binary"); + qCWarning(core, "get new ctx failed, binary"); return false; } @@ -312,7 +314,7 @@ class GpgContext::Impl { auto default_ctx_initialize(const GpgContextInitArgs &args) -> bool { gpgme_ctx_t p_ctx; if (CheckGpgError(gpgme_new(&p_ctx)) != GPG_ERR_NO_ERROR) { - GF_CORE_LOG_ERROR("get new ctx failed, default"); + qCWarning(core, "get new ctx failed, default"); return false; } assert(p_ctx != nullptr); diff --git a/src/core/function/gpg/GpgContext.h b/src/core/function/gpg/GpgContext.h index 2a8f6fdd..0fcf3e43 100644 --- a/src/core/function/gpg/GpgContext.h +++ b/src/core/function/gpg/GpgContext.h @@ -40,7 +40,7 @@ namespace GpgFrontend { * */ struct GpgContextInitArgs { - QString db_path = {}; ///< + QString db_path; ///< bool test_mode = false; ///< bool offline_mode = false; ///< @@ -63,7 +63,7 @@ class GPGFRONTEND_CORE_EXPORT GpgContext explicit GpgContext(GpgContextInitArgs args, int channel); - virtual ~GpgContext() override; + ~GpgContext(); [[nodiscard]] auto Good() const -> bool; diff --git a/src/core/function/gpg/GpgFileOpera.cpp b/src/core/function/gpg/GpgFileOpera.cpp index ad506c4a..9ada4afa 100644 --- a/src/core/function/gpg/GpgFileOpera.cpp +++ b/src/core/function/gpg/GpgFileOpera.cpp @@ -69,10 +69,9 @@ void GpgFileOpera::EncryptFile(const KeyArgsList& keys, const QString& in_path, cb, "gpgme_op_encrypt", "2.1.0"); } -auto GpgFileOpera::EncryptFileSync(const KeyArgsList& keys, - const QString& in_path, bool ascii, - const QString& out_path) - -> std::tuple<GpgError, DataObjectPtr> { +auto GpgFileOpera::EncryptFileSync( + const KeyArgsList& keys, const QString& in_path, bool ascii, + const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( [=](const DataObjectPtr& data_object) -> GpgError { std::vector<gpgme_key_t> recipients(keys.begin(), keys.end()); @@ -111,7 +110,7 @@ void GpgFileOpera::EncryptDirectory(const KeyArgsList& keys, GpgData data_in(ex); GpgData data_out(out_path, false); - GF_CORE_LOG_DEBUG("encrypt directory start"); + qCDebug(core, "encrypt directory start"); auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); auto err = CheckGpgError(gpgme_op_encrypt(ctx, recipients.data(), @@ -119,15 +118,14 @@ void GpgFileOpera::EncryptDirectory(const KeyArgsList& keys, data_in, data_out)); data_object->Swap({GpgEncryptResult(gpgme_op_encrypt_result(ctx))}); - GF_CORE_LOG_DEBUG("encrypt directory finished, err: {}", err); + qCDebug(core, "encrypt directory finished, err: %d", err); return err; }, cb, "gpgme_op_encrypt", "2.1.0"); ArchiveFileOperator::NewArchive2DataExchanger( in_path, ex, [=](GFError err, const DataObjectPtr&) { - GF_CORE_LOG_DEBUG("new archive 2 data exchanger operation, err: {}", - err); + qCDebug(core, "new archive 2 data exchanger operation, err: %d", err); if (decltype(ex) p_ex = w_ex.lock(); err < 0 && p_ex != nullptr) { ex->CloseWrite(); } @@ -176,8 +174,8 @@ void GpgFileOpera::DecryptArchive(const QString& in_path, ArchiveFileOperator::ExtractArchiveFromDataExchanger( ex, out_path, [](GFError err, const DataObjectPtr&) { - GF_CORE_LOG_DEBUG( - "extract archive from data exchanger operation, err: {}", err); + qCDebug(core, "extract archive from data exchanger operation, err: %d", + err); }); RunGpgOperaAsync( @@ -331,11 +329,10 @@ void GpgFileOpera::EncryptSignFile(const KeyArgsList& keys, cb, "gpgme_op_encrypt_sign", "2.1.0"); } -auto GpgFileOpera::EncryptSignFileSync(const KeyArgsList& keys, - const KeyArgsList& signer_keys, - const QString& in_path, bool ascii, - const QString& out_path) - -> std::tuple<GpgError, DataObjectPtr> { +auto GpgFileOpera::EncryptSignFileSync( + const KeyArgsList& keys, const KeyArgsList& signer_keys, + const QString& in_path, bool ascii, + const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( [=](const DataObjectPtr& data_object) -> GpgError { GpgError err; @@ -399,7 +396,7 @@ void GpgFileOpera::EncryptSignDirectory(const KeyArgsList& keys, ArchiveFileOperator::NewArchive2DataExchanger( in_path, ex, [=](GFError err, const DataObjectPtr&) { - GF_CORE_LOG_DEBUG("new archive 2 fd operation, err: {}", err); + qCDebug(core, "new archive 2 fd operation, err: %d", err); if (decltype(ex) p_ex = w_ex.lock(); err < 0 && p_ex != nullptr) { ex->CloseWrite(); } @@ -459,7 +456,7 @@ void GpgFileOpera::DecryptVerifyArchive(const QString& in_path, ArchiveFileOperator::ExtractArchiveFromDataExchanger( ex, out_path, [](GFError err, const DataObjectPtr&) { - GF_CORE_LOG_DEBUG("extract archive from ex operation, err: {}", err); + qCDebug(core, "extract archive from ex operation, err: %d", err); }); RunGpgOperaAsync( @@ -545,19 +542,18 @@ void GpgFileOpera::EncryptDerectorySymmetric(const QString& in_path, bool ascii, ArchiveFileOperator::NewArchive2DataExchanger( in_path, ex, [=](GFError err, const DataObjectPtr&) { - GF_CORE_LOG_DEBUG("new archive 2 fd operation, err: {}", err); + qCDebug(core, "new archive 2 fd operation, err: %d", err); }); } -auto GpgFileOpera::EncryptDerectorySymmetricSync(const QString& in_path, - bool ascii, - const QString& out_path) - -> std::tuple<GpgError, DataObjectPtr> { +auto GpgFileOpera::EncryptDerectorySymmetricSync( + const QString& in_path, bool ascii, + const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { auto ex = std::make_shared<GFDataExchanger>(kDataExchangerSize); ArchiveFileOperator::NewArchive2DataExchanger( in_path, ex, [=](GFError err, const DataObjectPtr&) { - GF_CORE_LOG_DEBUG("new archive 2 fd operation, err: {}", err); + qCDebug(core, "new archive 2 fd operation, err: %d", err); }); return RunGpgOperaSync( diff --git a/src/core/function/gpg/GpgKeyGetter.cpp b/src/core/function/gpg/GpgKeyGetter.cpp index 4a35d3cd..8b78b754 100644 --- a/src/core/function/gpg/GpgKeyGetter.cpp +++ b/src/core/function/gpg/GpgKeyGetter.cpp @@ -42,9 +42,7 @@ namespace GpgFrontend { class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { public: explicit Impl(int channel) - : SingletonFunctionObject<GpgKeyGetter::Impl>(channel) { - GF_CORE_LOG_DEBUG("called channel: {}", channel); - } + : SingletonFunctionObject<GpgKeyGetter::Impl>(channel) {} auto GetKey(const QString& fpr, bool use_cache) -> GpgKey { // find in cache first @@ -56,7 +54,8 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { gpgme_key_t p_key = nullptr; gpgme_get_key(ctx_.DefaultContext(), fpr.toUtf8(), &p_key, 1); if (p_key == nullptr) { - GF_CORE_LOG_WARN("GpgKeyGetter GetKey Private _p_key Null fpr", fpr); + qCWarning(core) << "GpgKeyGetter GetKey Private _p_key Null, fpr: " + << fpr; return GetPubkey(fpr, true); } return GpgKey(std::move(p_key)); @@ -72,7 +71,7 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { gpgme_key_t p_key = nullptr; gpgme_get_key(ctx_.DefaultContext(), fpr.toUtf8(), &p_key, 0); if (p_key == nullptr) - GF_CORE_LOG_WARN("GpgKeyGetter GetKey _p_key Null", fpr); + qCWarning(core) << "GpgKeyGetter GetKey _p_key Null, fpr: " << fpr; return GpgKey(std::move(p_key)); } @@ -92,9 +91,23 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { return keys_list; } - auto FlushKeyCache() -> bool { - GF_CORE_LOG_DEBUG("flush key channel called, channel: {}", GetChannel()); + auto FetchGpgKeyList() -> GpgKeyList { + if (keys_search_cache_.empty()) { + FlushKeyCache(); + } + auto keys_list = GpgKeyList{}; + { + // get the lock + std::lock_guard<std::mutex> lock(keys_cache_mutex_); + for (const auto& key : keys_cache_) { + keys_list.push_back(key); + } + } + return keys_list; + } + + auto FlushKeyCache() -> bool { // clear the keys cache keys_cache_.clear(); keys_search_cache_.clear(); @@ -129,17 +142,12 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { } } - GF_CORE_LOG_DEBUG("flush key channel cache address: {} object address: {}", - static_cast<void*>(&keys_search_cache_), - static_cast<void*>(this)); - // for debug assert(CheckGpgError2ErrCode(err, GPG_ERR_EOF) == GPG_ERR_EOF); err = gpgme_op_keylist_end(ctx_.DefaultContext()); assert(CheckGpgError2ErrCode(err, GPG_ERR_EOF) == GPG_ERR_NO_ERROR); - GF_CORE_LOG_DEBUG("flush key channel done, channel: {}", GetChannel()); return true; } @@ -165,6 +173,11 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { return keys_copy; } + auto GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel> { + return SecureCreateQSharedObject<GpgKeyTableModel>(FetchGpgKeyList(), + nullptr); + } + private: /** * @brief Get the gpgme context object @@ -218,9 +231,7 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { GpgKeyGetter::GpgKeyGetter(int channel) : SingletonFunctionObject<GpgKeyGetter>(channel), - p_(SecureCreateUniqueObject<Impl>(channel)) { - GF_CORE_LOG_DEBUG("called channel: {}", channel); -} + p_(SecureCreateUniqueObject<Impl>(channel)) {} GpgKeyGetter::~GpgKeyGetter() = default; @@ -248,4 +259,8 @@ auto GpgKeyGetter::GetKeysCopy(const KeyListPtr& keys) -> KeyListPtr { auto GpgKeyGetter::FetchKey() -> KeyLinkListPtr { return p_->FetchKey(); } +auto GpgKeyGetter::GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel> { + return p_->GetGpgKeyTableModel(); +} + } // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgKeyGetter.h b/src/core/function/gpg/GpgKeyGetter.h index 91138623..2c4c0706 100644 --- a/src/core/function/gpg/GpgKeyGetter.h +++ b/src/core/function/gpg/GpgKeyGetter.h @@ -29,6 +29,7 @@ #pragma once #include "core/function/basic/GpgFunctionObject.h" +#include "core/model/GpgKeyTableModel.h" #include "core/typedef/GpgTypedef.h" namespace GpgFrontend { @@ -106,6 +107,13 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter */ auto GetKeysCopy(const KeyLinkListPtr& keys) -> KeyLinkListPtr; + /** + * @brief + * + * @return GpgKeyTableModel + */ + auto GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel>; + private: class Impl; SecureUniquePtr<Impl> p_; diff --git a/src/core/function/gpg/GpgKeyImportExporter.cpp b/src/core/function/gpg/GpgKeyImportExporter.cpp index ef8cb112..b9875131 100644 --- a/src/core/function/gpg/GpgKeyImportExporter.cpp +++ b/src/core/function/gpg/GpgKeyImportExporter.cpp @@ -49,11 +49,11 @@ auto GpgKeyImportExporter::ImportKey(const GFBuffer& in_buffer) if (in_buffer.Empty()) return {}; GpgData data_in(in_buffer); - auto err = CheckGpgError(gpgme_op_import(ctx_.DefaultContext(), data_in)); + auto err = CheckGpgError(gpgme_op_import(ctx_.BinaryContext(), data_in)); if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return {}; gpgme_import_result_t result; - result = gpgme_op_import_result(ctx_.DefaultContext()); + result = gpgme_op_import_result(ctx_.BinaryContext()); gpgme_import_status_t status = result->imports; auto import_info = SecureCreateSharedObject<GpgImportInformation>(result); while (status != nullptr) { @@ -91,11 +91,8 @@ auto GpgKeyImportExporter::ExportKey(const GpgKey& key, bool secret, bool ascii, GpgData data_out; auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); auto err = gpgme_op_export_keys(ctx, keys_array.data(), mode, data_out); - if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return {}; + if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return {err, {}}; - GF_CORE_LOG_DEBUG( - "operation of exporting a key finished, ascii: {}, read_bytes: {}", ascii, - gpgme_data_seek(data_out, 0, SEEK_END)); return {err, data_out.Read2GFBuffer()}; } @@ -125,11 +122,7 @@ void GpgKeyImportExporter::ExportKeys(const KeyArgsList& keys, bool secret, GpgData data_out; auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); auto err = gpgme_op_export_keys(ctx, keys_array.data(), mode, data_out); - if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return {}; - - GF_CORE_LOG_DEBUG( - "operation of exporting keys finished, ascii: {}, read_bytes: {}", - ascii, gpgme_data_seek(data_out, 0, SEEK_END)); + if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return err; data_object->Swap({data_out.Read2GFBuffer()}); return err; @@ -159,11 +152,8 @@ void GpgKeyImportExporter::ExportAllKeys(const KeyArgsList& keys, bool secret, GpgData data_out; auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); auto err = gpgme_op_export_keys(ctx, keys_array.data(), mode, data_out); - if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return {}; + if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return err; - GF_CORE_LOG_DEBUG( - "operation of exporting keys finished, ascii: {}, read_bytes: {}", - ascii, gpgme_data_seek(data_out, 0, SEEK_END)); auto buffer = data_out.Read2GFBuffer(); if (secret) { @@ -173,12 +163,8 @@ void GpgKeyImportExporter::ExportAllKeys(const KeyArgsList& keys, bool secret, GpgData data_out_secret; auto err = gpgme_op_export_keys(ctx, keys_array.data(), mode, data_out_secret); - if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return {}; + if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return err; - GF_CORE_LOG_DEBUG( - "operation of exporting secret keys finished, " - "ascii: {}, read_bytes: {}", - ascii, gpgme_data_seek(data_out_secret, 0, SEEK_END)); buffer.Append(data_out_secret.Read2GFBuffer()); } diff --git a/src/core/function/gpg/GpgKeyManager.cpp b/src/core/function/gpg/GpgKeyManager.cpp index b5efe141..93a864ca 100644 --- a/src/core/function/gpg/GpgKeyManager.cpp +++ b/src/core/function/gpg/GpgKeyManager.cpp @@ -73,10 +73,9 @@ auto GpgFrontend::GpgKeyManager::RevSign( return true; } -auto GpgFrontend::GpgKeyManager::SetExpire(const GpgFrontend::GpgKey& key, - std::unique_ptr<GpgSubKey>& subkey, - std::unique_ptr<QDateTime>& expires) - -> bool { +auto GpgFrontend::GpgKeyManager::SetExpire( + const GpgFrontend::GpgKey& key, std::unique_ptr<GpgSubKey>& subkey, + std::unique_ptr<QDateTime>& expires) -> bool { unsigned long expires_time = 0; if (expires != nullptr) expires_time = expires->toSecsSinceEpoch(); @@ -95,81 +94,83 @@ auto GpgFrontend::GpgKeyManager::SetExpire(const GpgFrontend::GpgKey& key, auto GpgFrontend::GpgKeyManager::SetOwnerTrustLevel(const GpgKey& key, int trust_level) -> bool { if (trust_level < 0 || trust_level > 5) { - GF_CORE_LOG_ERROR("illegal owner trust level: {}", trust_level); + qCWarning(core, "illegal owner trust level: %d", trust_level); } - AutomatonNextStateHandler next_state_handler = [](AutomatonState state, - QString status, - QString args) { - GF_CORE_LOG_DEBUG("next_state_handler state: {}, gpg_status: {}, args: {}", - state, status, args); - auto tokens = args.split(' '); + AutomatonNextStateHandler next_state_handler = + [](AutomatonState state, QString status, QString args) { + qCDebug(core) << "next_state_handler state: " + << static_cast<unsigned int>(state) + << ", gpg_status: " << status << ", args: " << args; - switch (state) { - case AS_START: - if (status == "GET_LINE" && args == "keyedit.prompt") { - return AS_COMMAND; - } - return AS_ERROR; - case AS_COMMAND: - if (status == "GET_LINE" && args == "edit_ownertrust.value") { - return AS_VALUE; - } - return AS_ERROR; - case AS_VALUE: - if (status == "GET_LINE" && args == "keyedit.prompt") { - return AS_QUIT; - } else if (status == "GET_BOOL" && - args == "edit_ownertrust.set_ultimate.okay") { - return AS_REALLY_ULTIMATE; - } - return AS_ERROR; - case AS_REALLY_ULTIMATE: - if (status == "GET_LINE" && args == "keyedit.prompt") { - return AS_QUIT; - } - return AS_ERROR; - case AS_QUIT: - if (status == "GET_LINE" && args == "keyedit.save.okay") { - return AS_SAVE; - } - return AS_ERROR; - case AS_ERROR: - if (status == "GET_LINE" && args == "keyedit.prompt") { - return AS_QUIT; - } - return AS_ERROR; - default: - return AS_ERROR; - }; - }; + auto tokens = args.split(' '); - AutomatonActionHandler action_handler = - [trust_level](AutomatonHandelStruct& handler, AutomatonState state) { - GF_CORE_LOG_DEBUG("action_handler state: {}", state); switch (state) { + case AS_START: + if (status == "GET_LINE" && args == "keyedit.prompt") { + return AS_COMMAND; + } + return AS_ERROR; case AS_COMMAND: - return QString("trust"); + if (status == "GET_LINE" && args == "edit_ownertrust.value") { + return AS_VALUE; + } + return AS_ERROR; case AS_VALUE: - handler.SetSuccess(true); - return QString::number(trust_level); + if (status == "GET_LINE" && args == "keyedit.prompt") { + return AS_QUIT; + } else if (status == "GET_BOOL" && + args == "edit_ownertrust.set_ultimate.okay") { + return AS_REALLY_ULTIMATE; + } + return AS_ERROR; case AS_REALLY_ULTIMATE: - handler.SetSuccess(true); - return QString("Y"); + if (status == "GET_LINE" && args == "keyedit.prompt") { + return AS_QUIT; + } + return AS_ERROR; case AS_QUIT: - return QString("quit"); - case AS_SAVE: - handler.SetSuccess(true); - return QString("Y"); - case AS_START: + if (status == "GET_LINE" && args == "keyedit.save.okay") { + return AS_SAVE; + } + return AS_ERROR; case AS_ERROR: - return QString(""); + if (status == "GET_LINE" && args == "keyedit.prompt") { + return AS_QUIT; + } + return AS_ERROR; default: - return QString(""); - } - return QString(""); + return AS_ERROR; + }; }; + AutomatonActionHandler action_handler = [trust_level]( + AutomatonHandelStruct& handler, + AutomatonState state) { + qCDebug(core, "action_handler state: %d", static_cast<unsigned int>(state)); + switch (state) { + case AS_COMMAND: + return QString("trust"); + case AS_VALUE: + handler.SetSuccess(true); + return QString::number(trust_level); + case AS_REALLY_ULTIMATE: + handler.SetSuccess(true); + return QString("Y"); + case AS_QUIT: + return QString("quit"); + case AS_SAVE: + handler.SetSuccess(true); + return QString("Y"); + case AS_START: + case AS_ERROR: + return QString(""); + default: + return QString(""); + } + return QString(""); + }; + auto key_fpr = key.GetFingerprint(); AutomatonHandelStruct handel_struct(key_fpr); handel_struct.SetHandler(next_state_handler, action_handler); @@ -185,21 +186,19 @@ auto GpgFrontend::GpgKeyManager::SetOwnerTrustLevel(const GpgKey& key, auto GpgFrontend::GpgKeyManager::interactor_cb_fnc(void* handle, const char* status, - const char* args, int fd) - -> gpgme_error_t { + const char* args, + int fd) -> gpgme_error_t { auto* handle_struct = static_cast<AutomatonHandelStruct*>(handle); QString status_s = status; QString args_s = args; - GF_CORE_LOG_DEBUG( - "cb start status: {}, args: {}, fd: {}, handle struct state: {}", - status_s, args_s, fd, handle_struct->CuurentStatus()); if (status_s == "KEY_CONSIDERED") { auto tokens = QString(args).split(' '); if (tokens.empty() || tokens[0] != handle_struct->KeyFpr()) { - GF_CORE_LOG_ERROR("handle struct key fpr {} mismatch token: {}, exit...", - handle_struct->KeyFpr(), tokens[0]); + qCWarning(core) << "handle struct key fpr " << handle_struct->KeyFpr() + << "mismatch token: " << tokens[0] << ", exit..."; + return -1; } @@ -207,13 +206,13 @@ auto GpgFrontend::GpgKeyManager::interactor_cb_fnc(void* handle, } if (status_s == "GOT_IT" || status_s.isEmpty()) { - GF_CORE_LOG_DEBUG("status GOT_IT, continue..."); + qCDebug(core, "status GOT_IT, continue..."); return 0; } AutomatonState next_state = handle_struct->NextState(status_s, args_s); if (next_state == AS_ERROR) { - GF_CORE_LOG_DEBUG("handle struct next state caught error, skipping..."); + qCDebug(core, "handle struct next state caught error, skipping..."); return GPG_ERR_FALSE; } @@ -224,8 +223,7 @@ auto GpgFrontend::GpgKeyManager::interactor_cb_fnc(void* handle, // set state and preform action handle_struct->SetStatus(next_state); Command cmd = handle_struct->Action(); - GF_CORE_LOG_DEBUG("handle struct action done, next state: {}, action cmd: {}", - next_state, cmd); + if (!cmd.isEmpty()) { auto btye_array = cmd.toUtf8(); gpgme_io_write(fd, btye_array, btye_array.size()); diff --git a/src/core/function/gpg/GpgKeyManager.h b/src/core/function/gpg/GpgKeyManager.h index 8b4d41b2..85dc6be5 100644 --- a/src/core/function/gpg/GpgKeyManager.h +++ b/src/core/function/gpg/GpgKeyManager.h @@ -105,7 +105,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager AS_ERROR, AS_QUIT, }; - + struct AutomatonHandelStruct; using AutomatonActionHandler = diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp index 14d58a10..0205ea2f 100644 --- a/src/core/function/gpg/GpgKeyOpera.cpp +++ b/src/core/function/gpg/GpgKeyOpera.cpp @@ -61,7 +61,7 @@ void GpgKeyOpera::DeleteKeys(KeyIdArgsListPtr key_ids) { GPGME_DELETE_ALLOW_SECRET | GPGME_DELETE_FORCE)); assert(gpg_err_code(err) == GPG_ERR_NO_ERROR); } else { - GF_CORE_LOG_WARN("GpgKeyOpera DeleteKeys get key failed", tmp); + qCWarning(core) << "GpgKeyOpera DeleteKeys get key failed: " << tmp; } } } @@ -113,14 +113,12 @@ void GpgKeyOpera::GenerateRevokeCert(const GpgKey& key, output_path, "--gen-revoke", key.GetFingerprint()}, [=](int exit_code, const QString& p_out, const QString& p_err) { if (exit_code != 0) { - GF_CORE_LOG_ERROR( - "gnupg gen revoke execute error, process stderr: {}, process " - "stdout: {}", - p_err, p_out); + qCWarning(core) << "gnupg gen revoke execute error, process stderr: " + << p_err << ", process stdout: " << p_out; } else { - GF_CORE_LOG_DEBUG( - "gnupg gen revoke exit_code: {}, process stdout size: {}", - exit_code, p_out.size()); + qCDebug(core, + "gnupg gen revoke exit_code: %d, process stdout size: %lld", + exit_code, p_out.size()); } }, nullptr, @@ -128,7 +126,6 @@ void GpgKeyOpera::GenerateRevokeCert(const GpgKey& key, // Code From Gpg4Win while (proc->canReadLine()) { const QString line = QString::fromUtf8(proc->readLine()).trimmed(); - GF_CORE_LOG_DEBUG("line: {}", line); if (line == QLatin1String("[GNUPG:] GET_BOOL gen_revoke.okay")) { proc->write("y\n"); } else if (line == QLatin1String("[GNUPG:] GET_LINE " @@ -162,8 +159,8 @@ void GpgKeyOpera::GenerateKey(const std::shared_ptr<GenKeyInfo>& params, auto userid = params->GetUserid(); auto algo = params->GetAlgo() + params->GetKeySizeStr(); - GF_CORE_LOG_DEBUG("params: {} {}", params->GetAlgo(), - params->GetKeySizeStr()); + qCDebug(core) << "params: " << params->GetAlgo() + << params->GetKeySizeStr(); unsigned long expires = QDateTime::currentDateTime().secsTo(params->GetExpireTime()); @@ -178,8 +175,9 @@ void GpgKeyOpera::GenerateKey(const std::shared_ptr<GenKeyInfo>& params, if (params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; if (params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; - GF_CORE_LOG_DEBUG("key generation args: {} {} {} {}", userid, algo, - expires, flags); + qCDebug(core) << "key generation args: " << userid << algo << expires + << flags; + err = gpgme_op_createkey(ctx.DefaultContext(), userid.toUtf8(), algo.toUtf8(), 0, expires, nullptr, flags); @@ -202,8 +200,8 @@ auto GpgKeyOpera::GenerateKeySync(const std::shared_ptr<GenKeyInfo>& params) auto userid = params->GetUserid(); auto algo = params->GetAlgo() + params->GetKeySizeStr(); - GF_CORE_LOG_DEBUG("params: {} {}", params->GetAlgo(), - params->GetKeySizeStr()); + qCDebug(core) << "params: " << params->GetAlgo() + << params->GetKeySizeStr(); unsigned long expires = QDateTime::currentDateTime().secsTo(params->GetExpireTime()); @@ -218,8 +216,9 @@ auto GpgKeyOpera::GenerateKeySync(const std::shared_ptr<GenKeyInfo>& params) if (params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; if (params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; - GF_CORE_LOG_DEBUG("key generation args: {} {} {} {}", userid, algo, - expires, flags); + qCDebug(core) << "key generation args: " << userid << algo << expires + << flags; + err = gpgme_op_createkey(ctx.DefaultContext(), userid.toUtf8(), algo.toUtf8(), 0, expires, nullptr, flags); @@ -242,8 +241,8 @@ void GpgKeyOpera::GenerateSubkey(const GpgKey& key, [key, &ctx = ctx_, params](const DataObjectPtr& data_object) -> GpgError { if (!params->IsSubKey()) return GPG_ERR_CANCELED; - GF_CORE_LOG_DEBUG("generate subkey algo {}, key size {}", - params->GetAlgo(), params->GetKeySizeStr()); + qCDebug(core) << "generate subkey algo: " << params->GetAlgo() + << "key size: " << params->GetKeySizeStr(); auto algo = params->GetAlgo() + params->GetKeySizeStr(); unsigned long expires = @@ -257,8 +256,9 @@ void GpgKeyOpera::GenerateSubkey(const GpgKey& key, if (params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; if (params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; - GF_CORE_LOG_DEBUG("subkey generation args: {} {} {} {}", key.GetId(), - algo, expires, flags); + qCDebug(core) << "subkey generation args: " << key.GetId() << algo + << expires << flags; + auto err = gpgme_op_createsubkey(ctx.DefaultContext(), static_cast<gpgme_key_t>(key), algo.toUtf8(), 0, expires, flags); @@ -281,8 +281,8 @@ auto GpgKeyOpera::GenerateSubkeySync(const GpgKey& key, [key, &ctx = ctx_, params](const DataObjectPtr& data_object) -> GpgError { if (!params->IsSubKey()) return GPG_ERR_CANCELED; - GF_CORE_LOG_DEBUG("generate subkey algo {} key size {}", - params->GetAlgo(), params->GetKeySizeStr()); + qCDebug(core) << "generate subkey algo: " << params->GetAlgo() + << " key size: " << params->GetKeySizeStr(); auto algo = params->GetAlgo() + params->GetKeySizeStr(); unsigned long expires = @@ -296,8 +296,7 @@ auto GpgKeyOpera::GenerateSubkeySync(const GpgKey& key, if (params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; if (params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; - GF_CORE_LOG_DEBUG("args: {} {} {} {}", key.GetId(), algo, expires, - flags); + qCDebug(core) << " args: " << key.GetId() << algo << expires << flags; auto err = gpgme_op_createsubkey(ctx.DefaultContext(), static_cast<gpgme_key_t>(key), @@ -337,8 +336,9 @@ void GpgKeyOpera::GenerateKeyWithSubkey( if (params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; if (params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; - GF_CORE_LOG_DEBUG("key generation args: {}", userid, algo, expires, - flags); + qCDebug(core) << "key generation args: " << userid << algo << expires + << flags; + err = gpgme_op_createkey(ctx.DefaultContext(), userid, algo, 0, expires, nullptr, flags); @@ -358,16 +358,11 @@ void GpgKeyOpera::GenerateKeyWithSubkey( auto key = GpgKeyGetter::GetInstance().GetKey(genkey_result.GetFingerprint()); if (!key.IsGood()) { - GF_CORE_LOG_ERROR("cannot get key which has been generate, fpr: {}", - genkey_result.GetFingerprint()); + qCWarning(core) << "cannot get key which has been generate, fpr: " + << genkey_result.GetFingerprint(); return err; } - GF_CORE_LOG_DEBUG( - "try to generate subkey of key: {}, algo {} key size {}", - key.GetId(), subkey_params->GetAlgo(), - subkey_params->GetKeySizeStr()); - algo = (subkey_params->GetAlgo() + subkey_params->GetKeySizeStr()) .toUtf8(); expires = @@ -380,8 +375,8 @@ void GpgKeyOpera::GenerateKeyWithSubkey( if (subkey_params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; if (subkey_params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; - GF_CORE_LOG_DEBUG("subkey generation args: {} {} {} {}", key.GetId(), - algo, expires, flags); + qCDebug(core) << "subkey generation args: " << key.GetId() << algo + << expires << flags; err = gpgme_op_createsubkey(ctx.DefaultContext(), static_cast<gpgme_key_t>(key), algo, 0, @@ -422,8 +417,9 @@ auto GpgKeyOpera::GenerateKeyWithSubkeySync( if (params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; if (params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; - GF_CORE_LOG_DEBUG("key generation args: {}", userid, algo, expires, - flags); + qCDebug(core) << "key generation args: " << userid << algo << expires + << flags; + err = gpgme_op_createkey(ctx.DefaultContext(), userid, algo, 0, expires, nullptr, flags); @@ -443,15 +439,14 @@ auto GpgKeyOpera::GenerateKeyWithSubkeySync( auto key = GpgKeyGetter::GetInstance().GetKey(genkey_result.GetFingerprint()); if (!key.IsGood()) { - GF_CORE_LOG_ERROR("cannot get key which has been generate, fpr: {}", - genkey_result.GetFingerprint()); + qCWarning(core) << "cannot get key which has been generate, fpr: " + << genkey_result.GetFingerprint(); return err; } - GF_CORE_LOG_DEBUG( - "try to generate subkey of key: {}, algo {} key size {}", - key.GetId(), subkey_params->GetAlgo(), - subkey_params->GetKeySizeStr()); + qCDebug(core) << "try to generate subkey of key: " << key.GetId() + << ", algo :" << subkey_params->GetAlgo() + << ", key size: " << subkey_params->GetKeySizeStr(); algo = (subkey_params->GetAlgo() + subkey_params->GetKeySizeStr()) .toUtf8(); @@ -465,8 +460,8 @@ auto GpgKeyOpera::GenerateKeyWithSubkeySync( if (subkey_params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; if (subkey_params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; - GF_CORE_LOG_DEBUG("subkey generation args: {} {} {} {}", key.GetId(), - algo, expires, flags); + qCDebug(core) << "subkey generation args: " << key.GetId() << algo + << expires << flags; err = gpgme_op_createsubkey(ctx.DefaultContext(), static_cast<gpgme_key_t>(key), algo, 0, @@ -495,15 +490,14 @@ void GpgKeyOpera::ModifyPassword(const GpgKey& key, callback, "gpgme_op_passwd", "2.0.15"); } -auto GpgKeyOpera::ModifyTOFUPolicy(const GpgKey& key, - gpgme_tofu_policy_t tofu_policy) - -> GpgError { +auto GpgKeyOpera::ModifyTOFUPolicy( + const GpgKey& key, gpgme_tofu_policy_t tofu_policy) -> GpgError { const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gnupg_version", QString{"2.0.0"}); - GF_CORE_LOG_DEBUG("got gnupg version from rt: {}", gnupg_version); + qCDebug(core) << "got gnupg version from rt: " << gnupg_version; if (GFCompareSoftwareVersion(gnupg_version, "2.1.10") < 0) { - GF_CORE_LOG_ERROR("operator not support"); + qCWarning(core, "operator not support"); return GPG_ERR_NOT_SUPPORTED; } diff --git a/src/core/function/gpg/GpgUIDOperator.cpp b/src/core/function/gpg/GpgUIDOperator.cpp index 6c0373de..4477dd2f 100644 --- a/src/core/function/gpg/GpgUIDOperator.cpp +++ b/src/core/function/gpg/GpgUIDOperator.cpp @@ -48,17 +48,17 @@ auto GpgUIDOperator::RevUID(const GpgKey& key, const QString& uid) -> bool { return CheckGpgError(err) == GPG_ERR_NO_ERROR; } -auto GpgUIDOperator::SetPrimaryUID(const GpgKey& key, const QString& uid) - -> bool { +auto GpgUIDOperator::SetPrimaryUID(const GpgKey& key, + const QString& uid) -> bool { auto err = CheckGpgError(gpgme_op_set_uid_flag( ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), uid.toUtf8(), "primary", nullptr)); return CheckGpgError(err) == GPG_ERR_NO_ERROR; } auto GpgUIDOperator::AddUID(const GpgKey& key, const QString& name, - const QString& comment, const QString& email) - -> bool { - GF_CORE_LOG_DEBUG("new uuid: {} {} {}", name, comment, email); + const QString& comment, + const QString& email) -> bool { + qCDebug(core) << "new uuid:" << name << comment << email; return AddUID(key, QString("%1(%2)<%3>").arg(name).arg(comment).arg(email)); } diff --git a/src/core/model/DataObject.h b/src/core/model/DataObject.h index 6b41a051..28678ca3 100644 --- a/src/core/model/DataObject.h +++ b/src/core/model/DataObject.h @@ -70,10 +70,6 @@ class GPGFRONTEND_CORE_EXPORT DataObject { for (size_t i = 0; i < type_list.size(); ++i) { if (std::type_index(*type_list[i]) != std::type_index((*this)[i].type())) { - GF_CORE_LOG_ERROR( - "value of index {} in data object is type: {}, " - "not expected type: {}", - i, ((*this)[i]).type().name(), type_list[i]->name()); return false; } } diff --git a/src/core/model/GFDataExchanger.cpp b/src/core/model/GFDataExchanger.cpp index abf79c6b..c0da517d 100644 --- a/src/core/model/GFDataExchanger.cpp +++ b/src/core/model/GFDataExchanger.cpp @@ -28,8 +28,6 @@ #include "GFDataExchanger.h" -#include "core/utils/LogUtils.h" - namespace GpgFrontend { auto GFDataExchanger::Write(const std::byte* buffer, size_t size) -> ssize_t { @@ -40,16 +38,22 @@ auto GFDataExchanger::Write(const std::byte* buffer, size_t size) -> ssize_t { std::unique_lock<std::mutex> lock(mutex_); try { for (size_t i = 0; i < size; i++) { - if (queue_.size() == queue_max_size_) not_empty_.notify_all(); - not_full_.wait(lock, - [=] { return queue_.size() < queue_max_size_ || close_; }); + if (queue_.size() == static_cast<unsigned long>(queue_max_size_)) { + not_empty_.notify_all(); + } + + not_full_.wait(lock, [=] { + return queue_.size() < static_cast<unsigned long>(queue_max_size_) || + close_; + }); if (close_) return -1; queue_.push(buffer[i]); write_bytes++; } } catch (...) { - GF_CORE_LOG_ERROR( + qCWarning( + core, "gf data exchanger caught exception when it writes to queue, abort..."); } @@ -72,7 +76,9 @@ auto GFDataExchanger::Read(std::byte* buffer, size_t size) -> ssize_t { read_bytes++; } - if (queue_.size() < queue_max_size_) not_full_.notify_all(); + if (queue_.size() < static_cast<unsigned long>(queue_max_size_)) { + not_full_.notify_all(); + } return read_bytes; } diff --git a/src/core/model/GpgDecryptResult.cpp b/src/core/model/GpgDecryptResult.cpp index 3568bfd9..57a83656 100644 --- a/src/core/model/GpgDecryptResult.cpp +++ b/src/core/model/GpgDecryptResult.cpp @@ -55,9 +55,9 @@ auto GpgDecryptResult::Recipients() -> std::vector<GpgRecipient> { try { result.emplace_back(reci); } catch (...) { - GF_CORE_LOG_ERROR( - "caught exception when processing invalid_recipients, " - "maybe nullptr of fpr"); + qCWarning(core, + "caught exception when processing invalid_recipients, " + "maybe nullptr of fpr"); } } return result; diff --git a/src/core/model/GpgEncryptResult.cpp b/src/core/model/GpgEncryptResult.cpp index 843cf7eb..7017432b 100644 --- a/src/core/model/GpgEncryptResult.cpp +++ b/src/core/model/GpgEncryptResult.cpp @@ -55,9 +55,9 @@ auto GpgEncryptResult::InvalidRecipients() try { result.emplace_back(QString{invalid_key->fpr}, invalid_key->reason); } catch (...) { - GF_CORE_LOG_ERROR( - "caught exception when processing invalid_recipients, " - "maybe nullptr of fpr"); + qCWarning(core, + "caught exception when processing invalid_recipients, " + "maybe nullptr of fpr"); } } return result; diff --git a/src/core/model/GpgGenKeyInfo.cpp b/src/core/model/GpgGenKeyInfo.cpp index d7daa852..47451253 100644 --- a/src/core/model/GpgGenKeyInfo.cpp +++ b/src/core/model/GpgGenKeyInfo.cpp @@ -30,13 +30,10 @@ #include <cassert> -#include "core/utils/LogUtils.h" - namespace GpgFrontend { void GenKeyInfo::SetAlgo(const QString &t_algo_args) { auto algo_args = t_algo_args.toLower(); - GF_CORE_LOG_DEBUG("set algo args: {}", algo_args); // reset all options reset_options(); @@ -74,6 +71,28 @@ void GenKeyInfo::SetAlgo(const QString &t_algo_args) { suggest_max_key_size_ = 3072; suggest_size_addition_step_ = 1024; SetKeyLength(2048); + } else if (algo_args == "elg") { + /** + * Algorithm (DSA) as a government standard for digital signatures. + * Originally, it supported key lengths between 512 and 1024 bits. + * Recently, NIST has declared 512-bit keys obsolete: + * now, DSA is available in 1024, 2048 and 3072-bit lengths. + */ + SetAllowEncryption(true); + + SetAllowAuthentication(false); + allow_change_authentication_ = false; + + SetAllowSigning(false); + allow_change_signing_ = false; + + SetAllowCertification(false); + allow_change_certification_ = false; + + suggest_min_key_size_ = 1024; + suggest_max_key_size_ = 4096; + suggest_size_addition_step_ = 1024; + SetKeyLength(3072); } else if (algo_args == "ed25519") { /** @@ -105,7 +124,7 @@ void GenKeyInfo::SetAlgo(const QString &t_algo_args) { suggest_size_addition_step_ = -1; SetKeyLength(-1); } else { - SPDLOG_ERROR("unsupported genkey algo arguments: {}", algo_args); + qCWarning(core) << "unsupported genkey algo arguments: " << algo_args; return; } @@ -189,6 +208,7 @@ auto GenKeyInfo::GetSupportedSubkeyAlgo() static const std::vector<GenKeyInfo::KeyGenAlgo> kSupportSubkeyAlgo = { {"RSA", "", "RSA"}, {"DSA", "", "DSA"}, + {"ELG-E", "", "ELG"}, {"ECDSA", "", "ED25519"}, {"ECDH", "", "CV25519"}, {"ECDH NIST P-256", "", "NISTP256"}, diff --git a/src/core/model/GpgKeyTableModel.cpp b/src/core/model/GpgKeyTableModel.cpp new file mode 100644 index 00000000..e2a4fe37 --- /dev/null +++ b/src/core/model/GpgKeyTableModel.cpp @@ -0,0 +1,172 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GpgKeyTableModel.h" + +#include "core/function/gpg/GpgKeyGetter.h" +#include "core/model/GpgKey.h" + +namespace GpgFrontend { + +GpgKeyTableModel::GpgKeyTableModel(GpgKeyList keys, QObject *parent) + : QAbstractTableModel(parent), + buffered_keys_(keys), + column_headers_({tr("Select"), tr("Type"), tr("Name"), + tr("Email Address"), tr("Usage"), tr("Trust"), + tr("Key ID"), tr("Create Date"), tr("Algorithm"), + tr("Subkey(s)"), tr("Comment")}), + key_check_state_(buffered_keys_.size()) {} + +auto GpgKeyTableModel::rowCount(const QModelIndex & /*parent*/) const -> int { + return static_cast<int>(buffered_keys_.size()); +} + +auto GpgKeyTableModel::columnCount(const QModelIndex & /*parent*/) const + -> int { + return 11; +} + +auto GpgKeyTableModel::data(const QModelIndex &index, int role) const + -> QVariant { + if (!index.isValid() || buffered_keys_.empty()) return {}; + + if (role == Qt::TextAlignmentRole) { + return Qt::AlignCenter; + } + + if (role == Qt::CheckStateRole) { + if (index.column() == 0) { + return key_check_state_[index.row()] ? Qt::Checked : Qt::Unchecked; + } + return {}; + } + + const auto &key = buffered_keys_.at(index.row()); + + switch (index.column()) { + case 0: { + return index.row(); + } + case 1: { + QString type_sym; + type_sym += key.IsPrivateKey() ? "pub/sec" : "pub"; + if (key.IsPrivateKey() && !key.IsHasMasterKey()) type_sym += "#"; + if (key.IsHasCardKey()) type_sym += "^"; + return type_sym; + } + case 2: { + return key.GetName(); + } + case 3: { + return key.GetEmail(); + } + case 4: { + QString usage_sym; + if (key.IsHasActualCertificationCapability()) usage_sym += "C"; + if (key.IsHasActualEncryptionCapability()) usage_sym += "E"; + if (key.IsHasActualSigningCapability()) usage_sym += "S"; + if (key.IsHasActualAuthenticationCapability()) usage_sym += "A"; + return usage_sym; + } + case 5: { + return key.GetOwnerTrust(); + } + case 6: { + return key.GetId(); + } + case 7: { + return key.GetCreateTime(); + } + case 8: { + return key.GetKeyAlgo(); + } + case 9: { + return static_cast<int>(key.GetSubKeys()->size()); + } + case 10: { + return key.GetComment(); + } + default: + return {}; + } +} + +auto GpgKeyTableModel::headerData(int section, Qt::Orientation orientation, + int role) const -> QVariant { + if (role != Qt::DisplayRole) return {}; + + if (orientation == Qt::Horizontal) { + return column_headers_[section]; + } + + return {}; +} + +auto GpgKeyTableModel::flags(const QModelIndex &index) const -> Qt::ItemFlags { + if (!index.isValid()) return Qt::NoItemFlags; + + if (index.column() == 0) { + return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled; + } + + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; +} + +auto GpgKeyTableModel::setData(const QModelIndex &index, const QVariant &value, + int role) -> bool { + if (!index.isValid()) return false; + + if (index.column() == 0 && role == Qt::CheckStateRole) { + key_check_state_[index.row()] = (value == Qt::Checked); + emit dataChanged(index, index); + return true; + } + + return false; +} + +auto GpgKeyTableModel::GetAllKeyIds() -> GpgKeyIDList { + GpgKeyIDList keys; + for (auto &key : buffered_keys_) { + keys.push_back(key.GetId()); + } + return keys; +} + +auto GpgKeyTableModel::GetKeyIDByRow(int row) const -> QString { + if (buffered_keys_.size() <= row) return {}; + + return buffered_keys_[row].GetId(); +} + +auto GpgKeyTableModel::IsPrivateKeyByRow(int row) const -> bool { + if (buffered_keys_.size() <= row) return false; + return buffered_keys_[row].IsPrivateKey(); +} + +} // namespace GpgFrontend diff --git a/src/core/model/GpgKeyTableModel.h b/src/core/model/GpgKeyTableModel.h new file mode 100644 index 00000000..50640a9f --- /dev/null +++ b/src/core/model/GpgKeyTableModel.h @@ -0,0 +1,216 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +/** + * @brief + * + */ +#include "core/model/GpgKey.h" +#include "core/typedef/GpgTypedef.h" + +namespace GpgFrontend { + +enum class GpgKeyTableColumn : unsigned int { + kNONE = 0, + kTYPE = 1 << 0, + kNAME = 1 << 1, + kEMAIL_ADDRESS = 1 << 2, + kUSAGE = 1 << 3, + kKEY_ID = 1 << 4, + kOWNER_TRUST = 1 << 5, + kCREATE_DATE = 1 << 6, + kALGO = 1 << 7, + kSUBKEYS_NUMBER = 1 << 8, + kCOMMENT = 1 << 9, + kALL = ~0U +}; + +inline auto operator|(GpgKeyTableColumn lhs, + GpgKeyTableColumn rhs) -> GpgKeyTableColumn { + using T = std::underlying_type_t<GpgKeyTableColumn>; + return static_cast<GpgKeyTableColumn>(static_cast<T>(lhs) | + static_cast<T>(rhs)); +} + +inline auto operator|=(GpgKeyTableColumn &lhs, + GpgKeyTableColumn rhs) -> GpgKeyTableColumn & { + lhs = lhs | rhs; + return lhs; +} + +inline auto operator&(GpgKeyTableColumn lhs, + GpgKeyTableColumn rhs) -> GpgKeyTableColumn { + using T = std::underlying_type_t<GpgKeyTableColumn>; + return static_cast<GpgKeyTableColumn>(static_cast<T>(lhs) & + static_cast<T>(rhs)); +} + +inline auto operator&=(GpgKeyTableColumn &lhs, + GpgKeyTableColumn rhs) -> GpgKeyTableColumn & { + lhs = lhs & rhs; + return lhs; +} + +inline auto operator~(GpgKeyTableColumn hs) -> GpgKeyTableColumn { + using T = std::underlying_type_t<GpgKeyTableColumn>; + return static_cast<GpgKeyTableColumn>(~static_cast<T>(hs)); +} + +enum class GpgKeyTableDisplayMode : unsigned int { + kNONE = 0, + kPUBLIC_KEY = 1 << 0, + kPRIVATE_KEY = 1 << 1, + kFAVORITES = 1 << 2, + kALL = ~0U +}; + +inline auto operator|(GpgKeyTableDisplayMode lhs, + GpgKeyTableDisplayMode rhs) -> GpgKeyTableDisplayMode { + using T = std::underlying_type_t<GpgKeyTableDisplayMode>; + return static_cast<GpgKeyTableDisplayMode>(static_cast<T>(lhs) | + static_cast<T>(rhs)); +} + +inline auto operator|=(GpgKeyTableDisplayMode &lhs, + GpgKeyTableDisplayMode rhs) -> GpgKeyTableDisplayMode & { + lhs = lhs | rhs; + return lhs; +} + +inline auto operator&(GpgKeyTableDisplayMode lhs, + GpgKeyTableDisplayMode rhs) -> bool { + using T = std::underlying_type_t<GpgKeyTableDisplayMode>; + return (static_cast<T>(lhs) & static_cast<T>(rhs)) != 0; +} + +class GPGFRONTEND_CORE_EXPORT GpgKeyTableModel : public QAbstractTableModel { + Q_OBJECT + public: + /** + * @brief Construct a new Gpg Key Table Model object + * + * @param keys + * @param parent + */ + explicit GpgKeyTableModel(GpgKeyList keys, QObject *parent = nullptr); + + /** + * @brief + * + * @param parent + * @return int + */ + [[nodiscard]] auto rowCount(const QModelIndex &parent) const -> int override; + + /** + * @brief + * + * @param parent + * @return int + */ + [[nodiscard]] auto columnCount(const QModelIndex &parent) const + -> int override; + + /** + * @brief + * + * @param index + * @param role + * @return QVariant + */ + [[nodiscard]] auto data(const QModelIndex &index, + int role) const -> QVariant override; + + /** + * @brief + * + * @param section + * @param orientation + * @param role + * @return QVariant + */ + [[nodiscard]] auto headerData(int section, Qt::Orientation orientation, + int role) const -> QVariant override; + + /** + * @brief Set the Data object + * + * @param index + * @param value + * @param role + * @return true + * @return false + */ + auto setData(const QModelIndex &index, const QVariant &value, + int role) -> bool override; + + /** + * @brief + * + * @param index + * @return Qt::ItemFlags + */ + [[nodiscard]] auto flags(const QModelIndex &index) const + -> Qt::ItemFlags override; + + /** + * @brief Get the All Key Ids object + * + * @return auto + */ + auto GetAllKeyIds() -> GpgKeyIDList; + + /** + * @brief Get the Key ID By Row object + * + * @return QString + */ + [[nodiscard]] auto GetKeyIDByRow(int row) const -> QString; + + /** + * @brief + * + * @param row + * @return true + * @return false + */ + [[nodiscard]] auto IsPrivateKeyByRow(int row) const -> bool; + + private: + GpgKeyList buffered_keys_; + QStringList column_headers_; +#ifdef QT5_BUILD + QVector<bool> key_check_state_; +#else + QList<bool> key_check_state_; +#endif +}; + +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/model/GpgKeyTableProxyModel.cpp b/src/core/model/GpgKeyTableProxyModel.cpp new file mode 100644 index 00000000..aebe06ef --- /dev/null +++ b/src/core/model/GpgKeyTableProxyModel.cpp @@ -0,0 +1,179 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GpgKeyTableProxyModel.h" + +#include <utility> + +#include "core/function/gpg/GpgKeyGetter.h" +#include "core/model/CacheObject.h" +#include "core/model/GpgKey.h" + +namespace GpgFrontend { + +GpgKeyTableProxyModel::GpgKeyTableProxyModel( + QSharedPointer<GpgKeyTableModel> model, GpgKeyTableDisplayMode display_mode, + GpgKeyTableColumn columns, KeyFilter filter, QObject *parent) + : QSortFilterProxyModel(parent), + model_(std::move(model)), + display_mode_(display_mode), + filter_columns_(columns), + custom_filter_(std::move(filter)) { + setSourceModel(model_.get()); + + connect(this, &GpgKeyTableProxyModel::SignalFavoritesChanged, this, + &GpgKeyTableProxyModel::slot_update_favorites); + connect(this, &GpgKeyTableProxyModel::SignalColumnTypeChange, this, + &GpgKeyTableProxyModel::slot_update_column_type); + + emit SignalFavoritesChanged(); +} + +auto GpgKeyTableProxyModel::filterAcceptsRow( + int source_row, const QModelIndex &sourceParent) const -> bool { + auto index = sourceModel()->index(source_row, 6, sourceParent); + auto key_id = sourceModel()->data(index).toString(); + auto key = GpgKeyGetter::GetInstance().GetKey(key_id); + + if (!(display_mode_ & GpgKeyTableDisplayMode::kPRIVATE_KEY) && + key.IsPrivateKey()) { + return false; + } + + if (!(display_mode_ & GpgKeyTableDisplayMode::kPUBLIC_KEY) && + !key.IsPrivateKey()) { + return false; + } + + if (!custom_filter_(key)) return false; + + if (display_mode_ & GpgKeyTableDisplayMode::kFAVORITES && + !favorite_fingerprints_.contains(key.GetFingerprint())) { + return false; + } + + if (filter_keywords_.isEmpty()) return true; + + QStringList infos; + for (int column = 0; column < sourceModel()->columnCount(); ++column) { + auto index = sourceModel()->index(source_row, column, sourceParent); + infos << sourceModel()->data(index).toString(); + + const auto uids = key.GetUIDs(); + for (const auto &uid : *uids) { + infos << uid.GetUID(); + } + } + + return std::any_of(infos.cbegin(), infos.cend(), [&](const QString &info) { + return info.contains(filter_keywords_, Qt::CaseInsensitive); + }); + + return false; +} + +auto GpgKeyTableProxyModel::filterAcceptsColumn( + int sourceColumn, const QModelIndex &sourceParent) const -> bool { + switch (sourceColumn) { + case 0: { + return true; + } + case 1: { + return (filter_columns_ & GpgKeyTableColumn::kTYPE) != + GpgKeyTableColumn::kNONE; + } + case 2: { + return (filter_columns_ & GpgKeyTableColumn::kNAME) != + GpgKeyTableColumn::kNONE; + } + case 3: { + return (filter_columns_ & GpgKeyTableColumn::kEMAIL_ADDRESS) != + GpgKeyTableColumn::kNONE; + } + case 4: { + return (filter_columns_ & GpgKeyTableColumn::kUSAGE) != + GpgKeyTableColumn::kNONE; + } + case 5: { + return (filter_columns_ & GpgKeyTableColumn::kOWNER_TRUST) != + GpgKeyTableColumn::kNONE; + } + case 6: { + return (filter_columns_ & GpgKeyTableColumn::kKEY_ID) != + GpgKeyTableColumn::kNONE; + } + case 7: { + return (filter_columns_ & GpgKeyTableColumn::kCREATE_DATE) != + GpgKeyTableColumn::kNONE; + } + case 8: { + return (filter_columns_ & GpgKeyTableColumn::kALGO) != + GpgKeyTableColumn::kNONE; + } + case 9: { + return (filter_columns_ & GpgKeyTableColumn::kSUBKEYS_NUMBER) != + GpgKeyTableColumn::kNONE; + } + case 10: { + return (filter_columns_ & GpgKeyTableColumn::kCOMMENT) != + GpgKeyTableColumn::kNONE; + } + default: + return false; + } +} + +void GpgKeyTableProxyModel::SetSearchKeywords(const QString &keywords) { + this->filter_keywords_ = keywords; + invalidateFilter(); +} + +void GpgKeyTableProxyModel::slot_update_favorites() { + // load cache + auto json_data = CacheObject("favourite_key_pair"); + if (!json_data.isArray()) return; + + auto key_fprs = json_data.array(); + for (const auto &key_fpr : key_fprs) { + if (key_fpr.isString()) favorite_fingerprints_.append(key_fpr.toString()); + } + + invalidateFilter(); +} + +void GpgKeyTableProxyModel::slot_update_column_type( + GpgKeyTableColumn filter_columns) { + filter_columns_ = filter_columns; +#ifdef QT5_BUILD + invalidateFilter(); +#else + invalidateColumnsFilter(); +#endif +} + +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/model/GpgKeyTableProxyModel.h b/src/core/model/GpgKeyTableProxyModel.h new file mode 100644 index 00000000..657b40cf --- /dev/null +++ b/src/core/model/GpgKeyTableProxyModel.h @@ -0,0 +1,94 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "core/model/GpgKeyTableModel.h" + +namespace GpgFrontend { + +class GPGFRONTEND_CORE_EXPORT GpgKeyTableProxyModel + : public QSortFilterProxyModel { + Q_OBJECT + public: + using KeyFilter = std::function<bool(const GpgKey &)>; + + explicit GpgKeyTableProxyModel(QSharedPointer<GpgKeyTableModel> model, + GpgKeyTableDisplayMode display_mode, + GpgKeyTableColumn columns, KeyFilter filter, + QObject *parent); + + void SetSearchKeywords(const QString &keywords); + + protected: + [[nodiscard]] auto filterAcceptsRow(int sourceRow, + const QModelIndex &sourceParent) const + -> bool override; + + [[nodiscard]] auto filterAcceptsColumn(int sourceColumn, + const QModelIndex &sourceParent) const + -> bool override; + + signals: + + /** + * @brief + * + */ + void SignalFavoritesChanged(); + + /** + * @brief + * + */ + void SignalColumnTypeChange(GpgKeyTableColumn); + + private slots: + + /** + * @brief + * + */ + void slot_update_favorites(); + + /** + * @brief + * + */ + void slot_update_column_type(GpgKeyTableColumn); + + private: + QSharedPointer<GpgKeyTableModel> model_; + GpgKeyTableDisplayMode display_mode_; + GpgKeyTableColumn filter_columns_; + QString filter_keywords_; + QList<QString> favorite_fingerprints_; + KeyFilter custom_filter_; +}; + +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/model/GpgSignResult.cpp b/src/core/model/GpgSignResult.cpp index 4a0e5f35..50f6cfb7 100644 --- a/src/core/model/GpgSignResult.cpp +++ b/src/core/model/GpgSignResult.cpp @@ -55,9 +55,9 @@ auto GpgSignResult::InvalidSigners() try { result.emplace_back(QString{invalid_key->fpr}, invalid_key->reason); } catch (...) { - GF_CORE_LOG_ERROR( - "caught exception when processing invalid_signers, " - "maybe nullptr of fpr"); + qCWarning(core, + "caught exception when processing invalid_signers, " + "maybe nullptr of fpr"); } } return result; diff --git a/src/core/model/SettingsObject.cpp b/src/core/model/SettingsObject.cpp index 09824f12..48eb65ff 100644 --- a/src/core/model/SettingsObject.cpp +++ b/src/core/model/SettingsObject.cpp @@ -35,20 +35,17 @@ namespace GpgFrontend { SettingsObject::SettingsObject(QString settings_name) : settings_name_(std::move(settings_name)) { try { - GF_CORE_LOG_DEBUG("loading settings from: {}", this->settings_name_); auto json_optional = DataObjectOperator::GetInstance().GetDataObject(settings_name_); if (json_optional.has_value() && json_optional->isObject()) { - GF_CORE_LOG_DEBUG("settings object: {} loaded.", settings_name_); QJsonObject::operator=(json_optional.value().object()); } else { - GF_CORE_LOG_DEBUG("settings object: {} not found.", settings_name_); QJsonObject::operator=({}); } } catch (std::exception& e) { - GF_CORE_LOG_ERROR("load setting object error: {}", e.what()); + qCWarning(core) << "load setting object error: {}" << e.what(); } } diff --git a/src/core/module/Event.cpp b/src/core/module/Event.cpp index 4b0b989b..6d39d7ba 100644 --- a/src/core/module/Event.cpp +++ b/src/core/module/Event.cpp @@ -34,21 +34,17 @@ namespace GpgFrontend::Module { class Event::Impl { public: - Impl(QString event_id, std::initializer_list<ParameterInitializer> params, - EventCallback callback) + Impl(QString event_id, Params params, EventCallback callback) : event_identifier_(std::move(event_id)), callback_(std::move(callback)), callback_thread_(QThread::currentThread()) { - for (const auto& param : params) { - AddParameter(param); - } - GF_CORE_LOG_DEBUG("create event {}", event_identifier_); + data_.insert(params); } auto operator[](const QString& key) const -> std::optional<ParameterValue> { auto it_data = data_.find(key); if (it_data != data_.end()) { - return it_data->second; + return it_data.value(); } return std::nullopt; } @@ -82,21 +78,17 @@ class Event::Impl { } void ExecuteCallback(ListenerIdentifier listener_id, - const DataObjectPtr& data_object) { - GF_CORE_LOG_DEBUG("try to execute callback for event {} with listener {}", - event_identifier_, listener_id); + const Params& data_object) { if (callback_) { - GF_CORE_LOG_DEBUG("executing callback for event {} with listener {}", - event_identifier_, listener_id); if (!QMetaObject::invokeMethod( callback_thread_, [callback = callback_, event_identifier = event_identifier_, listener_id, data_object]() { callback(event_identifier, listener_id, data_object); })) { - GF_CORE_LOG_ERROR( - "failed to invoke callback for event {} with listener {}", - event_identifier_, listener_id); + qCWarning(core) << "failed to invoke callback for event: " + << event_identifier_ + << " with listener:" << listener_id; } } } @@ -112,7 +104,22 @@ class Event::Impl { GFModuleEventParam* p_param; int index = 0; - for (const auto& data : data_) { + +#ifdef QT5_BUILD + for (auto it = data_.keyValueBegin(); it != data_.keyValueEnd(); ++it) { + p_param = static_cast<GFModuleEventParam*>( + SecureMalloc(sizeof(GFModuleEventParam))); + if (index++ == 0) event->params = p_param; + + p_param->name = GFStrDup(it->first); + p_param->value = GFStrDup(it->second); + p_param->next = nullptr; + + if (l_param != nullptr) l_param->next = p_param; + l_param = p_param; + } +#else + for (const auto& data : data_.asKeyValueRange()) { p_param = static_cast<GFModuleEventParam*>( SecureMalloc(sizeof(GFModuleEventParam))); if (index++ == 0) event->params = p_param; @@ -124,6 +131,7 @@ class Event::Impl { if (l_param != nullptr) l_param->next = p_param; l_param = p_param; } +#endif return event; } @@ -131,14 +139,12 @@ class Event::Impl { private: EventIdentifier event_identifier_; EventTriggerIdentifier trigger_uuid_ = QUuid::createUuid().toString(); - std::map<QString, QString> data_; + QMap<QString, QString> data_; EventCallback callback_; QThread* callback_thread_ = nullptr; ///< }; -Event::Event(const QString& event_id, - std::initializer_list<ParameterInitializer> params, - EventCallback callback) +Event::Event(const QString& event_id, Params params, EventCallback callback) : p_(SecureCreateUniqueObject<Impl>(event_id, params, std::move(callback))) {} @@ -170,8 +176,8 @@ void Event::AddParameter(const QString& key, const QString& value) { p_->AddParameter(key, value); } -void Event::ExecuteCallback(ListenerIdentifier l_id, DataObjectPtr d_o) { - p_->ExecuteCallback(std::move(l_id), d_o); +void Event::ExecuteCallback(ListenerIdentifier l_id, const Params& param) { + p_->ExecuteCallback(std::move(l_id), param); } auto Event::ToModuleEvent() -> GFModuleEvent* { return p_->ToModuleEvent(); } diff --git a/src/core/module/Event.h b/src/core/module/Event.h index b629caae..64c35592 100644 --- a/src/core/module/Event.h +++ b/src/core/module/Event.h @@ -34,7 +34,7 @@ #include "core/GpgFrontendCore.h" #include "core/model/DataObject.h" -#include "module/sdk/GFSDKModule.h" +#include "sdk/GFSDKModule.h" namespace GpgFrontend::Module { @@ -50,16 +50,16 @@ class GPGFRONTEND_CORE_EXPORT Event { using ParameterValue = std::any; using EventIdentifier = QString; using ListenerIdentifier = QString; + using Params = QMap<QString, QString>; + using EventCallback = - std::function<void(EventIdentifier, ListenerIdentifier, DataObjectPtr)>; + std::function<void(EventIdentifier, ListenerIdentifier, Params)>; struct ParameterInitializer { QString key; QString value; }; - explicit Event(const QString&, - std::initializer_list<ParameterInitializer> = {}, - EventCallback = nullptr); + explicit Event(const QString&, Params = {}, EventCallback = nullptr); ~Event(); @@ -81,7 +81,7 @@ class GPGFRONTEND_CORE_EXPORT Event { void AddParameter(const QString& key, const QString& value); - void ExecuteCallback(ListenerIdentifier, DataObjectPtr); + void ExecuteCallback(ListenerIdentifier, const Params&); auto ToModuleEvent() -> GFModuleEvent*; @@ -91,10 +91,8 @@ class GPGFRONTEND_CORE_EXPORT Event { }; template <typename... Args> -auto MakeEvent(const EventIdentifier& event_id, Args&&... args, +auto MakeEvent(const EventIdentifier& event_id, const Event::Params& params, Event::EventCallback e_cb) -> EventReference { - std::initializer_list<Event::ParameterInitializer> params = { - Event::ParameterInitializer{std::forward<Args>(args)}...}; return GpgFrontend::SecureCreateSharedObject<Event>(event_id, params, e_cb); } diff --git a/src/core/module/GlobalModuleContext.cpp b/src/core/module/GlobalModuleContext.cpp index e67e48f9..c35e5229 100644 --- a/src/core/module/GlobalModuleContext.cpp +++ b/src/core/module/GlobalModuleContext.cpp @@ -54,8 +54,8 @@ class GlobalModuleContext::Impl { // Search for the module in the register table. auto module_info_opt = search_module_register_table(module_id); if (!module_info_opt.has_value()) { - GF_CORE_LOG_ERROR("cannot find module id {} at register table", - module_id); + qCWarning(core) << "cannot find module id " << module_id + << " at register table"; return nullptr; } @@ -67,11 +67,11 @@ class GlobalModuleContext::Impl { auto module_info_opt = search_module_register_table(module->GetModuleIdentifier()); if (!module_info_opt.has_value()) { - GF_CORE_LOG_ERROR( - "cannot find module id {} at register table, fallbacking to " - "default " - "channel", - module->GetModuleIdentifier()); + qCWarning(core) << "cannot find module id " + << module->GetModuleIdentifier() + << " at register table, fallback to " + "default channel"; + return GetDefaultChannel(module); } @@ -99,20 +99,17 @@ class GlobalModuleContext::Impl { } auto RegisterModule(const ModulePtr& module, bool integrated_module) -> bool { - GF_CORE_LOG_DEBUG("attempting to register module: {}", - module->GetModuleIdentifier()); // Check if the module is null or already registered. if (module == nullptr || module_register_table_.find(module->GetModuleIdentifier()) != module_register_table_.end()) { - GF_CORE_LOG_ERROR( - "module is null or have already registered this module"); + qCWarning(core, "module is null or have already registered this module"); return false; } if (module->Register() != 0) { - GF_CORE_LOG_ERROR("register module {} failed", - module->GetModuleIdentifier()); + qCWarning(core) << "register module " << module->GetModuleIdentifier() + << " failed"; return false; } @@ -132,19 +129,15 @@ class GlobalModuleContext::Impl { // Register the module with its identifier. module_register_table_[module->GetModuleIdentifier()] = register_info; - GF_CORE_LOG_DEBUG("successfully registered module: {}", - module->GetModuleIdentifier()); return true; } auto ActiveModule(ModuleIdentifier module_id) -> bool { - GF_CORE_LOG_DEBUG("attempting to activate module: {}", module_id); - // Search for the module in the register table. auto module_info_opt = search_module_register_table(module_id); if (!module_info_opt.has_value()) { - GF_CORE_LOG_ERROR("cannot find module id {} at register table", - module_id); + qCWarning(core) << "cannot find module id " << module_id + << " at register table"; return false; } @@ -153,9 +146,8 @@ class GlobalModuleContext::Impl { // try to get module from module info auto module = module_info->module; if (module == nullptr) { - GF_CORE_LOG_ERROR( - "module id {} at register table is releated to a null module", - module_id); + qCWarning(core) << "module id:" << module_id + << " at register table is related to a null module"; return false; } @@ -165,19 +157,15 @@ class GlobalModuleContext::Impl { module_info->activate = true; } - GF_CORE_LOG_DEBUG("module activation status: {}", module_info->activate); return module_info->activate; } auto ListenEvent(ModuleIdentifier module_id, EventIdentifier event) -> bool { - GF_CORE_LOG_DEBUG("module: {} is attempting to listen to event {}", - module_id, event); - // module -> event auto module_info_opt = search_module_register_table(module_id); if (!module_info_opt.has_value()) { - GF_CORE_LOG_ERROR("cannot find module id {} at register table", - module_id); + qCWarning(core) << "cannot find module id" << module_id + << "at register table"; return false; } @@ -186,7 +174,6 @@ class GlobalModuleContext::Impl { if (met_it == module_events_table_.end()) { module_events_table_[event] = std::unordered_set<ModuleIdentifier>(); met_it = module_events_table_.find(event); - GF_CORE_LOG_DEBUG("new event {} of module system created", event); } module_info_opt.value()->listening_event_ids.push_back(event); @@ -204,14 +191,14 @@ class GlobalModuleContext::Impl { // search for the module in the register table. auto module_info_opt = search_module_register_table(module_id); if (!module_info_opt.has_value()) { - GF_CORE_LOG_ERROR("cannot find module id {} at register table", - module_id); + qCWarning(core) << "cannot find module id " << module_id + << " at register table"; return false; } auto module_info = module_info_opt.value(); - // activate the module if it is not already deactive. - if (module_info->activate && (module_info->module->Deactive() == 0)) { + // activate the module if it is not already Deactivate. + if (module_info->activate && (module_info->module->Deactivate() == 0)) { for (const auto& event_ids : module_info->listening_event_ids) { auto& modules = module_events_table_[event_ids]; if (auto it = modules.find(module_id); it != modules.end()) { @@ -228,15 +215,13 @@ class GlobalModuleContext::Impl { auto TriggerEvent(const EventReference& event) -> bool { auto event_id = event->GetIdentifier(); - GF_CORE_LOG_DEBUG("attempting to trigger event: {}", event_id); // Find the set of listeners associated with the given event in the table auto met_it = module_events_table_.find(event_id); if (met_it == module_events_table_.end()) { // Log a warning if the event is not registered and nobody is listening - GF_CORE_LOG_WARN( - "event {} is not listening by anyone and not registered as well", - event_id); + qCInfo(core) << "event: " << event_id + << " is not listening by anyone and not registered as well."; return false; } @@ -246,15 +231,10 @@ class GlobalModuleContext::Impl { // Check if the set of listeners is empty if (listeners_set.empty()) { // Log a warning if nobody is listening to this event - GF_CORE_LOG_WARN("event {} is not listening by anyone", - event->GetIdentifier()); + qCInfo(core) << "event: " << event_id << " is not listening by anyone"; return false; } - // Log the number of listeners for this event - GF_CORE_LOG_DEBUG("event {}'s current listeners size: {}", - event->GetIdentifier(), listeners_set.size()); - // register trigger id index table module_on_triggering_events_table_[event->GetTriggerIdentifier()] = event; @@ -265,8 +245,8 @@ class GlobalModuleContext::Impl { // Log an error if the module is not found in the registration table if (!module_info_opt.has_value()) { - GF_CORE_LOG_ERROR("cannot find module id {} at register table", - listener_module_id); + qCWarning(core) << "cannot find module id: " << listener_module_id + << " at register table"; continue; } @@ -274,11 +254,6 @@ class GlobalModuleContext::Impl { auto module_info = module_info_opt.value(); auto module = module_info->module; - GF_CORE_LOG_DEBUG( - "module {} is listening to event {}, activate state: {}", - module_info->module->GetModuleIdentifier(), event->GetIdentifier(), - module_info->activate); - // Check if the module is activated if (!module_info->activate) continue; @@ -289,9 +264,9 @@ class GlobalModuleContext::Impl { [listener_module_id, event_id](int code, DataObjectPtr) { if (code < 0) { // Log an error if the module execution fails - GF_CORE_LOG_ERROR( - "module {} execution failed of event {}: exec return code {}", - listener_module_id, event_id, code); + qCWarning(core) << "module " << listener_module_id + << "execution failed of event " << event_id + << ": exec return code: " << code; } }; diff --git a/src/core/module/GlobalRegisterTable.cpp b/src/core/module/GlobalRegisterTable.cpp index bac51d85..c19a9131 100644 --- a/src/core/module/GlobalRegisterTable.cpp +++ b/src/core/module/GlobalRegisterTable.cpp @@ -126,8 +126,8 @@ class GlobalRegisterTable::Impl { return rtn; } - auto ListenPublish(QObject* o, const Namespace& n, const Key& k, LPCallback c) - -> bool { + auto ListenPublish(QObject* o, const Namespace& n, const Key& k, + LPCallback c) -> bool { if (o == nullptr) return false; return QObject::connect(parent_, &GlobalRegisterTable::SignalPublish, o, [n, k, c](const Namespace& pn, const Key& pk, @@ -138,7 +138,7 @@ class GlobalRegisterTable::Impl { }) == nullptr; } - auto RootRTNode() -> RTNode* { return root_node_.get(); } + auto RootRTNode() -> RTNodePtr { return root_node_; } private: std::shared_mutex lock_; @@ -165,8 +165,8 @@ class GlobalRegisterTableTreeModel::Impl { return 4; } - [[nodiscard]] auto Data(const QModelIndex& index, int role) const - -> QVariant { + [[nodiscard]] auto Data(const QModelIndex& index, + int role) const -> QVariant { if (!index.isValid()) return {}; if (role == Qt::DisplayRole) { @@ -232,8 +232,8 @@ class GlobalRegisterTableTreeModel::Impl { return tr("<UNSUPPORTED>"); } - [[nodiscard]] auto Index(int row, int column, const QModelIndex& parent) const - -> QModelIndex { + [[nodiscard]] auto Index(int row, int column, + const QModelIndex& parent) const -> QModelIndex { if (!parent_->hasIndex(row, column, parent)) return {}; auto* parent_node = !parent.isValid() @@ -292,8 +292,8 @@ auto GlobalRegisterTable::PublishKV(Namespace n, Key k, std::any v) -> bool { return p_->PublishKV(n, k, v); } -auto GlobalRegisterTable::LookupKV(Namespace n, Key v) - -> std::optional<std::any> { +auto GlobalRegisterTable::LookupKV(Namespace n, + Key v) -> std::optional<std::any> { return p_->LookupKV(n, v); } @@ -302,14 +302,15 @@ auto GlobalRegisterTable::ListenPublish(QObject* o, Namespace n, Key k, return p_->ListenPublish(o, n, k, c); } -auto GlobalRegisterTable::ListChildKeys(Namespace n, Key k) - -> std::vector<Key> { +auto GlobalRegisterTable::ListChildKeys(Namespace n, + Key k) -> std::vector<Key> { return p_->ListChildKeys(n, k); } GlobalRegisterTableTreeModel::GlobalRegisterTableTreeModel( - GlobalRegisterTable* grt) - : p_(SecureCreateUniqueObject<Impl>(this, grt->p_.get())) {} + GlobalRegisterTable* grt, QObject* parent) + : QAbstractItemModel(parent), + p_(SecureCreateUniqueObject<Impl>(this, grt->p_.get())) {} auto GlobalRegisterTableTreeModel::rowCount(const QModelIndex& parent) const -> int { @@ -326,9 +327,8 @@ auto GlobalRegisterTableTreeModel::data(const QModelIndex& index, return p_->Data(index, role); } -auto GlobalRegisterTableTreeModel::index(int row, int column, - const QModelIndex& parent) const - -> QModelIndex { +auto GlobalRegisterTableTreeModel::index( + int row, int column, const QModelIndex& parent) const -> QModelIndex { return p_->Index(row, column, parent); } diff --git a/src/core/module/GlobalRegisterTableTreeModel.h b/src/core/module/GlobalRegisterTableTreeModel.h index fe4242a2..b7d56cc1 100644 --- a/src/core/module/GlobalRegisterTableTreeModel.h +++ b/src/core/module/GlobalRegisterTableTreeModel.h @@ -34,15 +34,16 @@ namespace GpgFrontend::Module { class GPGFRONTEND_CORE_EXPORT GlobalRegisterTableTreeModel : public QAbstractItemModel { public: - explicit GlobalRegisterTableTreeModel(GlobalRegisterTable *grt); + explicit GlobalRegisterTableTreeModel(GlobalRegisterTable *grt, + QObject *parent); [[nodiscard]] auto rowCount(const QModelIndex &parent) const -> int override; [[nodiscard]] auto columnCount(const QModelIndex &parent) const -> int override; - [[nodiscard]] auto data(const QModelIndex &index, int role) const - -> QVariant override; + [[nodiscard]] auto data(const QModelIndex &index, + int role) const -> QVariant override; [[nodiscard]] auto index(int row, int column, const QModelIndex &parent) const -> QModelIndex override; diff --git a/src/core/module/Module.cpp b/src/core/module/Module.cpp index 9c875fce..78a8810f 100644 --- a/src/core/module/Module.cpp +++ b/src/core/module/Module.cpp @@ -31,7 +31,7 @@ #include "core/module/GlobalModuleContext.h" #include "core/utils/CommonUtils.h" #include "core/utils/IOUtils.h" -#include "module/sdk/GFSDKModule.h" +#include "sdk/GFSDKModule.h" #include "utils/BuildInfoUtils.h" namespace GpgFrontend::Module { @@ -59,9 +59,9 @@ class Module::Impl { *required_symbol.pointer = reinterpret_cast<void*>(module_library.resolve(required_symbol.name)); if (*required_symbol.pointer == nullptr) { - GF_CORE_LOG_WARN( - "illegal module: {}, reason: cannot load symbol: {}, abort...", - module_library.fileName(), required_symbol.name); + qCWarning(core) << "illegal module: " << module_library.fileName() + << ", reason cannot load symbol: " + << required_symbol.name << ", abort..."; return; } } @@ -72,39 +72,38 @@ class Module::Impl { qt_env_ver_ = GFUnStrDup(get_qt_ver_api_()); if (!module_identifier_regex_exp_.match(identifier_).hasMatch()) { - GF_CORE_LOG_WARN( - "illegal module: {}, reasson invalid module id, abort...", - identifier_); + qCWarning(core) << "illegal module: " << identifier_ + << ", reason invalid module id, abort..."; return; } if (!module_version_regex_exp_.match(version_).hasMatch()) { - GF_CORE_LOG_WARN( - "illegal module: {}, reasson invalid version: {}, abort...", - identifier_, version_); + qCWarning(core) << "illegal module: " << identifier_ + << ", reason invalid version: " << version_ + << ", abort..."; return; } if (!module_version_regex_exp_.match(gf_sdk_ver_).hasMatch()) { - GF_CORE_LOG_WARN( - "illegal module: {}, reasson invalid sdk version: {}, abort...", - identifier_, gf_sdk_ver_); + qCWarning(core) << "illegal module: " << identifier_ + << ", reason invalid sdk version: " << gf_sdk_ver_ + << ", abort..."; return; } if (GFCompareSoftwareVersion(gf_sdk_ver_, GetProjectVersion()) > 0) { - GF_CORE_LOG_WARN( - "uncompatible module: {}, sdk version: {} greater than " - "current sdk version: {}, abort...", - identifier_, gf_sdk_ver_, GetProjectVersion()); + qCWarning(core) << "uncompatible module: " << identifier_ + << ", reason sdk version: " << gf_sdk_ver_ + << "current sdk version: " << GetProjectVersion() + << ", abort..."; return; } auto qt_env_ver_regex_match = module_version_regex_exp_.match(qt_env_ver_); if (!qt_env_ver_regex_match.hasMatch()) { - GF_CORE_LOG_WARN( - "illegal module: {}, reasson invalid qt env version: {}, abort...", - identifier_, qt_env_ver_); + qCWarning(core) << "illegal module: " << identifier_ + << ", reason invalid qt env version: " << qt_env_ver_ + << ", abort..."; return; } @@ -113,19 +112,13 @@ class Module::Impl { if (qt_env_ver_major != QString::number(QT_VERSION_MAJOR) + "." || qt_env_ver_minor != QString::number(QT_VERSION_MINOR) + ".") { - GF_CORE_LOG_WARN( - "uncompatible module: {}, qt version: {} is not binary uncompatible " - "with application's qt env version: {}, abort...", - identifier_, qt_env_ver_, QString::fromUtf8(QT_VERSION_STR)); + qCWarning(core) << "uncompatible module: " << identifier_ + << ", reason sdk version: " << qt_env_ver_ + << "current sdk version: " + << QString::fromUtf8(QT_VERSION_STR) << ", abort..."; return; } - GF_CORE_LOG_INFO( - "module loaded, id: {}, version: {}, " - "sdk version: {}, qt env version: {}, hash: {}, path: {}", - identifier_, version_, gf_sdk_ver_, qt_env_ver_, module_hash_, - module_library_path_); - ::GFModuleMetaData* p_meta_data = get_metadata_api_(); while (p_meta_data != nullptr) { @@ -159,7 +152,7 @@ class Module::Impl { return -1; } - auto Deactive() -> int { + auto Deactivate() -> int { if (good_ && deactivate_api_ != nullptr) return deactivate_api_(); return -1; } @@ -255,7 +248,7 @@ class Module::Impl { {"GFRegisterModule", reinterpret_cast<void**>(®ister_api_)}, {"GFActiveModule", reinterpret_cast<void**>(&activate_api_)}, {"GFExecuteModule", reinterpret_cast<void**>(&execute_api_)}, - {"GFDeactiveModule", reinterpret_cast<void**>(&deactivate_api_)}, + {"GFDeactivateModule", reinterpret_cast<void**>(&deactivate_api_)}, {"GFUnregisterModule", reinterpret_cast<void**>(&unregister_api_)}, }; @@ -286,7 +279,7 @@ auto Module::Exec(EventReference event) -> int { return p_->Exec(std::move(event)); } -auto Module::Deactive() -> int { return p_->Deactive(); } +auto Module::Deactivate() -> int { return p_->Deactivate(); } auto Module::UnRegister() -> int { return p_->UnRegister(); } diff --git a/src/core/module/Module.h b/src/core/module/Module.h index c332d455..e609d64e 100644 --- a/src/core/module/Module.h +++ b/src/core/module/Module.h @@ -61,7 +61,7 @@ class GPGFRONTEND_CORE_EXPORT Module : public QObject { virtual auto Exec(EventReference) -> int; - virtual auto Deactive() -> int; + virtual auto Deactivate() -> int; virtual auto UnRegister() -> int; diff --git a/src/core/module/ModuleInit.cpp b/src/core/module/ModuleInit.cpp index ceb5987e..dc001798 100644 --- a/src/core/module/ModuleInit.cpp +++ b/src/core/module/ModuleInit.cpp @@ -39,11 +39,8 @@ namespace GpgFrontend::Module { void LoadModuleFromPath(const QString& mods_path, bool integrated) { - for (const auto& module_library_name : - QDir(mods_path).entryList(QStringList() << "*.so" - << "*.dll" - << "*.dylib", - QDir::Files)) { + for (const auto& module_library_name : QDir(mods_path).entryList( + QStringList() << "*.so" << "*.dll" << "*.dylib", QDir::Files)) { ModuleManager::GetInstance().LoadModule( mods_path + "/" + module_library_name, integrated); } @@ -54,34 +51,30 @@ auto LoadIntegratedMods() -> bool { #if defined(MACOS) && defined(RELEASE) // App Bundle - auto mods_path = exec_binary_path + "/../PlugIns/mods"; + auto mods_path = exec_binary_path + "/../Modules"; #else // Debug Or Windows Platform - auto mods_path = exec_binary_path + "/mods"; + auto mods_path = exec_binary_path + "/modules"; #endif // AppImage if (!qEnvironmentVariable("APPIMAGE").isEmpty()) { - mods_path = qEnvironmentVariable("APPDIR") + "/usr/plugins/mods"; + mods_path = qEnvironmentVariable("APPDIR") + "/usr/modules"; } // Flatpak if (!qEnvironmentVariable("container").isEmpty()) { - mods_path = "/app/lib/mods"; + mods_path = "/app/modules"; } - GF_CORE_LOG_DEBUG("try loading integrated modules at path: {} ...", - mods_path); if (!QDir(mods_path).exists()) { - GF_CORE_LOG_WARN( - "integrated module directory at path {} not found, abort...", - mods_path); + qCWarning(core) << "integrated module directory at path: " << mods_path + << " not found, abort..."; return false; } LoadModuleFromPath(mods_path, true); - GF_CORE_LOG_DEBUG("load integrated modules done."); return true; } @@ -89,16 +82,14 @@ auto LoadExternalMods() -> bool { auto mods_path = GpgFrontend::GlobalSettingStation::GetInstance().GetModulesDir(); - GF_CORE_LOG_DEBUG("try loading external modules at path: {} ...", mods_path); if (!QDir(mods_path).exists()) { - GF_CORE_LOG_WARN("external module directory at path {} not found, abort...", - mods_path); + qCWarning(core) << "external module directory at path " << mods_path + << " not found, abort..."; return false; } LoadModuleFromPath(mods_path, false); - GF_CORE_LOG_DEBUG("load integrated modules done."); return true; } diff --git a/src/core/module/ModuleInit.h b/src/core/module/ModuleInit.h index e7e86f0f..c4f121ba 100644 --- a/src/core/module/ModuleInit.h +++ b/src/core/module/ModuleInit.h @@ -28,15 +28,11 @@ #pragma once -#include <spdlog/spdlog.h> - #include "core/GpgFrontendCoreExport.h" namespace GpgFrontend::Module { -struct ModuleInitArgs { - spdlog::level::level_enum log_level; -}; +struct ModuleInitArgs {}; /** * @brief init the module library diff --git a/src/core/module/ModuleManager.cpp b/src/core/module/ModuleManager.cpp index d07ca989..d575d40c 100644 --- a/src/core/module/ModuleManager.cpp +++ b/src/core/module/ModuleManager.cpp @@ -31,6 +31,7 @@ #include <memory> #include <utility> +#include "core/function/GlobalSettingStation.h" #include "core/function/SecureMemoryAllocator.h" #include "core/function/basic/GpgFunctionObject.h" #include "core/model/SettingsObject.h" @@ -54,25 +55,31 @@ class ModuleManager::Impl { auto LoadAndRegisterModule(const QString& module_library_path, bool integrated_module) -> void { + // give user ability to give up all modules + auto disable_loading_all_modules = + GlobalSettingStation::GetInstance() + .GetSettings() + .value("basic/disable_loading_all_modules", false) + .toBool(); + if (disable_loading_all_modules) return; + Thread::TaskRunnerGetter::GetInstance() .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default) ->PostTask(new Thread::Task( [=](GpgFrontend::DataObjectPtr) -> int { QLibrary module_library(module_library_path); if (!module_library.load()) { - GF_CORE_LOG_WARN( - "module manager failed to load module, " - "reason: broken library: {} ", - module_library.fileName()); + qCWarning(core) << "module manager failed to load module: " + << module_library.fileName() + << ", reason: " << module_library.errorString(); return -1; } auto module = SecureCreateSharedObject<Module>(module_library); if (!module->IsGood()) { - GF_CORE_LOG_WARN( - "module manager failed to load module, " - "reason: illegal module: {}", - module_library.fileName()); + qCWarning(core) << "module manager failed to load module, " + "reason: illegal module: " + << module_library.fileName(); return -1; } @@ -172,7 +179,7 @@ class ModuleManager::Impl { __func__, nullptr)); } - void DeactiveModule(const ModuleIdentifier& identifier) { + void DeactivateModule(const ModuleIdentifier& identifier) { Thread::TaskRunnerGetter::GetInstance() .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default) ->PostTask(new Thread::Task( @@ -231,13 +238,13 @@ auto UpsertRTValue(const QString& namespace_, const QString& key, std::any(value)); } -auto ListenRTPublishEvent(QObject* o, Namespace n, Key k, LPCallback c) - -> bool { +auto ListenRTPublishEvent(QObject* o, Namespace n, Key k, + LPCallback c) -> bool { return ModuleManager::GetInstance().ListenRTPublish(o, n, k, c); } -auto ListRTChildKeys(const QString& namespace_, const QString& key) - -> std::vector<Key> { +auto ListRTChildKeys(const QString& namespace_, + const QString& key) -> std::vector<Key> { return ModuleManager::GetInstance().ListRTChildKeys(namespace_, key); } @@ -283,8 +290,8 @@ void ModuleManager::ActiveModule(ModuleIdentifier id) { return p_->ActiveModule(id); } -void ModuleManager::DeactiveModule(ModuleIdentifier id) { - return p_->DeactiveModule(id); +void ModuleManager::DeactivateModule(ModuleIdentifier id) { + return p_->DeactivateModule(id); } auto ModuleManager::GetTaskRunner(ModuleIdentifier id) @@ -296,8 +303,8 @@ auto ModuleManager::UpsertRTValue(Namespace n, Key k, std::any v) -> bool { return p_->UpsertRTValue(n, k, v); } -auto ModuleManager::RetrieveRTValue(Namespace n, Key k) - -> std::optional<std::any> { +auto ModuleManager::RetrieveRTValue(Namespace n, + Key k) -> std::optional<std::any> { return p_->RetrieveRTValue(n, k); } @@ -306,8 +313,8 @@ auto ModuleManager::ListenRTPublish(QObject* o, Namespace n, Key k, return p_->ListenPublish(o, n, k, c); } -auto ModuleManager::ListRTChildKeys(const QString& n, const QString& k) - -> std::vector<Key> { +auto ModuleManager::ListRTChildKeys(const QString& n, + const QString& k) -> std::vector<Key> { return p_->ListRTChildKeys(n, k); } diff --git a/src/core/module/ModuleManager.h b/src/core/module/ModuleManager.h index ea2d88cb..9f7fab18 100644 --- a/src/core/module/ModuleManager.h +++ b/src/core/module/ModuleManager.h @@ -28,7 +28,6 @@ #pragma once -#include <mutex> #include <vector> #include "core/function/SecureMemoryAllocator.h" @@ -88,7 +87,7 @@ class GPGFRONTEND_CORE_EXPORT ModuleManager void ActiveModule(ModuleIdentifier); - void DeactiveModule(ModuleIdentifier); + void DeactivateModule(ModuleIdentifier); auto GetTaskRunner(ModuleIdentifier) -> std::optional<TaskRunnerPtr>; @@ -123,10 +122,10 @@ void RegisterAndActivateModule(Args&&... args) { } template <typename... Args> -void TriggerEvent(const EventIdentifier& event_id, Args&&... args, +void TriggerEvent(const EventIdentifier& event_id, + const Event::Params& params = {}, Event::EventCallback e_cb = nullptr) { - ModuleManager::GetInstance().TriggerEvent( - std::move(MakeEvent(event_id, std::forward<Args>(args)..., e_cb))); + ModuleManager::GetInstance().TriggerEvent(MakeEvent(event_id, params, e_cb)); } /** @@ -166,13 +165,12 @@ auto GPGFRONTEND_CORE_EXPORT ListenRTPublishEvent(QObject*, Namespace, Key, * @param key * @return std::vector<Key> */ -auto GPGFRONTEND_CORE_EXPORT ListRTChildKeys(const QString& namespace_, - const QString& key) - -> std::vector<Key>; +auto GPGFRONTEND_CORE_EXPORT ListRTChildKeys( + const QString& namespace_, const QString& key) -> std::vector<Key>; template <typename T> -auto RetrieveRTValueTyped(const QString& namespace_, const QString& key) - -> std::optional<T> { +auto RetrieveRTValueTyped(const QString& namespace_, + const QString& key) -> std::optional<T> { auto any_value = ModuleManager::GetInstance().RetrieveRTValue(namespace_, key); if (any_value && any_value->type() == typeid(T)) { @@ -183,8 +181,8 @@ auto RetrieveRTValueTyped(const QString& namespace_, const QString& key) template <typename T> auto RetrieveRTValueTypedOrDefault(const QString& namespace_, - const QString& key, const T& defaultValue) - -> T { + const QString& key, + const T& defaultValue) -> T { auto any_value = ModuleManager::GetInstance().RetrieveRTValue(namespace_, key); if (any_value && any_value->type() == typeid(T)) { diff --git a/src/core/thread/FileReadTask.cpp b/src/core/thread/FileReadTask.cpp index 49a3f540..78cd99e9 100644 --- a/src/core/thread/FileReadTask.cpp +++ b/src/core/thread/FileReadTask.cpp @@ -41,17 +41,15 @@ FileReadTask::FileReadTask(QString path) auto FileReadTask::Run() -> int { if (QFileInfo(read_file_path_).isFile()) { - GF_CORE_LOG_DEBUG("read open file: {}", read_file_path_); - target_file_.setFileName(read_file_path_); target_file_.open(QIODevice::ReadOnly); if (!(target_file_.isOpen() && target_file_.isReadable())) { - GF_CORE_LOG_ERROR("file not open or not readable"); + qCWarning(core, "file not open or not readable"); if (target_file_.isOpen()) target_file_.close(); return -1; } - GF_CORE_LOG_DEBUG("started reading: {}", read_file_path_); + slot_read_bytes(); } else { emit SignalFileBytesReadEnd(); @@ -64,10 +62,8 @@ void FileReadTask::slot_read_bytes() { if (QByteArray read_buffer; !target_file_.atEnd() && (read_buffer = target_file_.read(kBufferSize)).size() > 0) { - GF_CORE_LOG_DEBUG("io thread read bytes: {}", read_buffer.size()); emit SignalFileBytesRead(std::move(read_buffer)); } else { - GF_CORE_LOG_DEBUG("io thread read bytes end"); emit SignalFileBytesReadEnd(); // announce finish task emit SignalTaskShouldEnd(0); @@ -75,7 +71,6 @@ void FileReadTask::slot_read_bytes() { } FileReadTask::~FileReadTask() { - GF_CORE_LOG_DEBUG("close file: {}", read_file_path_); if (target_file_.isOpen()) target_file_.close(); } diff --git a/src/core/thread/Task.cpp b/src/core/thread/Task.cpp index dc0cfe94..14818aca 100644 --- a/src/core/thread/Task.cpp +++ b/src/core/thread/Task.cpp @@ -38,7 +38,6 @@ class Task::Impl { public: Impl(Task *parent, QString name) : parent_(parent), uuid_(generate_uuid()), name_(std::move(name)) { - GF_CORE_LOG_TRACE("task {} created", GetFullID()); init(); } @@ -51,8 +50,6 @@ class Task::Impl { callback_([](int, const DataObjectPtr &) {}), callback_thread_(QThread::currentThread()), data_object_(std::move(data_object)) { - GF_CORE_LOG_TRACE("task {} created with runnable, callback_thread_: {}", - GetFullID(), static_cast<void *>(callback_thread_)); init(); } @@ -65,13 +62,10 @@ class Task::Impl { callback_(std::move(callback)), callback_thread_(QThread::currentThread()), data_object_(std::move(data_object)) { - GF_CORE_LOG_TRACE( - "task {} created with runnable and callback, callback_thread_: {}", - GetFullID(), static_cast<void *>(callback_thread_)); init(); } - ~Impl() { GF_CORE_LOG_TRACE("task {} destroyed", GetFullID()); } + ~Impl() = default; /** * @brief @@ -95,13 +89,7 @@ class Task::Impl { * @return int */ auto Run() -> int { - GF_CORE_LOG_TRACE("task {} is in classical runnable and callback mode", - GetFullID()); - if (runnable_) return runnable_(data_object_); - - GF_CORE_LOG_WARN("no runnable in task, do callback operation, task: {}", - GetFullID()); return 0; } @@ -137,9 +125,6 @@ class Task::Impl { DataObjectPtr data_object_ = nullptr; ///< void init() { - GF_CORE_LOG_TRACE("task {} created, parent: {}, impl: {}", name_, - static_cast<void *>(parent_), static_cast<void *>(this)); - // HoldOnLifeCycle(false); @@ -156,17 +141,11 @@ class Task::Impl { SetRTN(rtn); try { if (callback_) { - GF_CORE_LOG_TRACE( - "task callback {} is starting with runnerable rtn: {}", - GetFullID(), rtn); - callback_(rtn_, data_object_); - GF_CORE_LOG_TRACE("task callback {} finished, rtn: {}", - GetFullID(), rtn); } } catch (...) { - GF_CORE_LOG_ERROR("task {} callback caught exception, rtn: {}", - GetFullID(), rtn); + qCWarning(core) << "task: {}, " << GetFullID() + << "callback caught exception, rtn: " << rtn; } emit parent_->SignalTaskEnd(); }); @@ -214,11 +193,7 @@ void Task::SafelyRun() { emit SignalRun(); } int Task::Run() { return p_->Run(); } -void Task::run() { - GF_CORE_LOG_TRACE("interface run() of task {} was called by thread: {}", - GetFullID(), QThread::currentThread()->currentThreadId()); - this->SafelyRun(); -} +void Task::run() { this->SafelyRun(); } Task::TaskHandler::TaskHandler(Task *task) : task_(task) {} @@ -238,14 +213,11 @@ auto Task::TaskHandler::GetTask() -> Task * { void Task::slot_exception_safe_run() noexcept { auto rtn = p_->GetRTN(); try { - GF_CORE_LOG_TRACE("task runnable {} is starting...", GetFullID()); - // Run() will set rtn by itself rtn = this->Run(); - GF_CORE_LOG_TRACE("task runnable {} finished, rtn: {}", GetFullID()); } catch (...) { - GF_CORE_LOG_ERROR("exception was caught at task: {}", GetFullID()); + qCWarning(core) << "exception was caught at task: {}" << GetFullID(); } // raise signal to anounce after runnable returned diff --git a/src/core/thread/TaskRunner.cpp b/src/core/thread/TaskRunner.cpp index 8e381384..0837b7b8 100644 --- a/src/core/thread/TaskRunner.cpp +++ b/src/core/thread/TaskRunner.cpp @@ -38,21 +38,19 @@ class TaskRunner::Impl : public QThread { void PostTask(Task* task) { if (task == nullptr) { - GF_CORE_LOG_ERROR("task posted is null"); + qCWarning(core, "task posted is null"); return; } task->setParent(nullptr); task->moveToThread(this); - GF_CORE_LOG_TRACE("runner starts task: {} at thread: {}", task->GetFullID(), - this->currentThreadId()); task->SafelyRun(); } auto RegisterTask(const QString& name, const Task::TaskRunnable& runnerable, - const Task::TaskCallback& cb, DataObjectPtr params) - -> Task::TaskHandler { + const Task::TaskCallback& cb, + DataObjectPtr params) -> Task::TaskHandler { auto* raw_task = new Task(runnerable, name, std::move(params), cb); raw_task->setParent(nullptr); raw_task->moveToThread(this); @@ -65,9 +63,6 @@ class TaskRunner::Impl : public QThread { pending_tasks_.remove(raw_task->GetFullID()); }); - GF_CORE_LOG_TRACE("runner starts task: {} at thread: {}", - raw_task->GetFullID(), this->currentThreadId()); - return Task::TaskHandler(raw_task); } @@ -78,7 +73,7 @@ class TaskRunner::Impl : public QThread { void PostConcurrentTask(Task* task) { if (task == nullptr) { - GF_CORE_LOG_ERROR("task posted is null"); + qCWarning(core, "task posted is null"); return; } @@ -93,8 +88,6 @@ class TaskRunner::Impl : public QThread { concurrent_thread->start(); - GF_CORE_LOG_TRACE("runner starts task concurrenctly: {}", - task->GetFullID()); task->SafelyRun(); } @@ -143,8 +136,8 @@ auto TaskRunner::IsRunning() -> bool { return p_->isRunning(); } auto TaskRunner::RegisterTask(const QString& name, const Task::TaskRunnable& runnable, - const Task::TaskCallback& cb, DataObjectPtr p_pbj) - -> Task::TaskHandler { + const Task::TaskCallback& cb, + DataObjectPtr p_pbj) -> Task::TaskHandler { return p_->RegisterTask(name, runnable, cb, p_pbj); } } // namespace GpgFrontend::Thread diff --git a/src/core/typedef/GpgTypedef.h b/src/core/typedef/GpgTypedef.h index 599c5c59..730bd4ee 100644 --- a/src/core/typedef/GpgTypedef.h +++ b/src/core/typedef/GpgTypedef.h @@ -58,6 +58,8 @@ using GpgKeyLinkList = std::list<GpgKey>; ///< using KeyLinkListPtr = std::unique_ptr<GpgKeyLinkList>; ///< using KeyPtr = std::unique_ptr<GpgKey>; ///< using KeyPtrArgsList = const std::initializer_list<KeyPtr>; ///< +using GpgKeyList = QList<GpgKey>; ///< +using GpgKeyIDList = QList<QString>; ///< using GpgSignMode = gpgme_sig_mode_t; diff --git a/src/core/utils/AsyncUtils.cpp b/src/core/utils/AsyncUtils.cpp index 3c007fb6..7d746bbc 100644 --- a/src/core/utils/AsyncUtils.cpp +++ b/src/core/utils/AsyncUtils.cpp @@ -42,12 +42,10 @@ auto RunGpgOperaAsync(const GpgOperaRunnable& runnable, -> Thread::Task::TaskHandler { const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gnupg_version", minial_version); - GF_CORE_LOG_DEBUG("got gnupg version from rt: {}, operation: {}", - gnupg_version, operation); if (GFCompareSoftwareVersion(gnupg_version, minial_version) < 0) { - GF_CORE_LOG_ERROR("operaton {} not support for gnupg version: {}", - operation, gnupg_version); + qCWarning(core) << "operation" << operation + << " not support for gnupg version: " << gnupg_version; callback(GPG_ERR_NOT_SUPPORTED, TransferParams()); return Thread::Task::TaskHandler(nullptr); } @@ -82,12 +80,10 @@ auto RunGpgOperaSync(const GpgOperaRunnable& runnable, const QString& operation, -> std::tuple<GpgError, DataObjectPtr> { const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gnupg_version", minial_version); - GF_CORE_LOG_DEBUG("got gnupg version from rt: {}, operation: {}", - gnupg_version, operation); if (GFCompareSoftwareVersion(gnupg_version, minial_version) < 0) { - GF_CORE_LOG_ERROR("operaton {} not support for gnupg version: {}", - operation, gnupg_version); + qCWarning(core) << "operation" << operation + << " not support for gnupg version: " << gnupg_version; return {GPG_ERR_NOT_SUPPORTED, TransferParams()}; } @@ -125,8 +121,8 @@ auto RunIOOperaAsync(const OperaRunnable& runnable, } auto RunOperaAsync(const OperaRunnable& runnable, - const OperationCallback& callback, const QString& operation) - -> Thread::Task::TaskHandler { + const OperationCallback& callback, + const QString& operation) -> Thread::Task::TaskHandler { auto handler = Thread::TaskRunnerGetter::GetInstance() .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default) diff --git a/src/core/utils/BuildInfoUtils.cpp b/src/core/utils/BuildInfoUtils.cpp index a7d914ef..65a0b43a 100644 --- a/src/core/utils/BuildInfoUtils.cpp +++ b/src/core/utils/BuildInfoUtils.cpp @@ -5,9 +5,12 @@ namespace GpgFrontend { +auto GetProjectName() -> QString { return {PROJECT_NAME}; } + auto GetProjectVersion() -> QString { - return QString("v") + VERSION_MAJOR + "." + VERSION_MINOR + "." + - VERSION_PATCH; + return (QStringList{} << "v" << VERSION_MAJOR << "." << VERSION_MINOR << "." + << VERSION_PATCH) + .join(""); } auto GetProjectBuildVersion() -> QString { return BUILD_VERSION; } diff --git a/src/core/utils/BuildInfoUtils.h b/src/core/utils/BuildInfoUtils.h index 07b0bb21..dfc9efe3 100644 --- a/src/core/utils/BuildInfoUtils.h +++ b/src/core/utils/BuildInfoUtils.h @@ -37,6 +37,13 @@ namespace GpgFrontend { * * @return QString */ +auto GPGFRONTEND_CORE_EXPORT GetProjectName() -> QString; + +/** + * @brief + * + * @return QString + */ auto GPGFRONTEND_CORE_EXPORT GetProjectVersion() -> QString; /** diff --git a/src/core/utils/CommonUtils.cpp b/src/core/utils/CommonUtils.cpp index d1704312..941ea39f 100644 --- a/src/core/utils/CommonUtils.cpp +++ b/src/core/utils/CommonUtils.cpp @@ -82,13 +82,13 @@ auto GFStrDup(const QString& str) -> char* { return c_str; } -auto GPGFRONTEND_CORE_EXPORT GFUnStrDup(char* str) -> QString { +auto GFUnStrDup(char* str) -> QString { auto qt_str = QString::fromUtf8(str); SecureFree(static_cast<void*>(const_cast<char*>(str))); return qt_str; } -auto GPGFRONTEND_CORE_EXPORT GFUnStrDup(const char* str) -> QString { +auto GFUnStrDup(const char* str) -> QString { return GFUnStrDup(const_cast<char*>(str)); } diff --git a/src/core/utils/CommonUtils.h b/src/core/utils/CommonUtils.h index 6ef38fad..bd546a11 100644 --- a/src/core/utils/CommonUtils.h +++ b/src/core/utils/CommonUtils.h @@ -48,21 +48,21 @@ auto GPGFRONTEND_CORE_EXPORT BeautifyFingerprint(QString fingerprint) * @param b * @return int */ -auto GPGFRONTEND_CORE_EXPORT GFCompareSoftwareVersion(const QString& a, - const QString& b) -> int; +auto GPGFRONTEND_CORE_EXPORT GFCompareSoftwareVersion(const QString &a, + const QString &b) -> int; /** * @brief * * @return char* */ -auto GPGFRONTEND_CORE_EXPORT GFStrDup(const QString&) -> char*; +auto GFStrDup(const QString &) -> char *; /** * @brief * * @return QString */ -auto GPGFRONTEND_CORE_EXPORT GFUnStrDup(const char*) -> QString; +auto GFUnStrDup(const char *) -> QString; } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/utils/GpgUtils.cpp b/src/core/utils/GpgUtils.cpp index 0d00b13e..1d81b272 100644 --- a/src/core/utils/GpgUtils.cpp +++ b/src/core/utils/GpgUtils.cpp @@ -50,9 +50,9 @@ auto GetGpgmeErrorString(gpgme_error_t err) -> QString { auto CheckGpgError(GpgError err) -> GpgError { auto err_code = gpg_err_code(err); if (err_code != GPG_ERR_NO_ERROR) { - GF_CORE_LOG_ERROR( - "gpg operation failed [error code: {}], source: {} description: {}", - err_code, gpgme_strsource(err), GetGpgmeErrorString(err)); + qCWarning(core) << "gpg operation failed [error code: " << err_code + << "], source: " << gpgme_strsource(err) + << " description: " << GetGpgmeErrorString(err); } return err_code; } @@ -61,13 +61,15 @@ auto CheckGpgError2ErrCode(GpgError err, GpgError predict) -> GpgErrorCode { auto err_code = gpg_err_code(err); if (err_code != gpg_err_code(predict)) { if (err_code == GPG_ERR_NO_ERROR) { - GF_CORE_LOG_WARN("[Warning {}] Source: {} description: {} predict: {}", - gpg_err_code(err), gpgme_strsource(err), - GetGpgmeErrorString(err), GetGpgmeErrorString(predict)); + qCInfo(core) << "[Warning " << gpg_err_code(err) + << "] Source: " << gpgme_strsource(err) + << " description: " << GetGpgmeErrorString(err) + << " predict: " << GetGpgmeErrorString(predict); } else { - GF_CORE_LOG_ERROR("[Error {}] Source: {} description: {} predict: {}", - gpg_err_code(err), gpgme_strsource(err), - GetGpgmeErrorString(err), GetGpgmeErrorString(predict)); + qCWarning(core) << "[Error " << gpg_err_code(err) + << "] Source: " << gpgme_strsource(err) + << " description: " << GetGpgmeErrorString(err) + << " predict: " << GetGpgmeErrorString(predict); } } return err_code; @@ -79,8 +81,9 @@ auto DescribeGpgErrCode(GpgError err) -> GpgErrorDesc { auto CheckGpgError(GpgError err, const QString& /*comment*/) -> GpgError { if (gpg_err_code(err) != GPG_ERR_NO_ERROR) { - GF_CORE_LOG_WARN("[Error {}] Source: {} description: {}", gpg_err_code(err), - gpgme_strsource(err), GetGpgmeErrorString(err)); + qCWarning(core) << "[Error " << gpg_err_code(err) + << "] Source: " << gpgme_strsource(err) + << " description: " << GetGpgmeErrorString(err); } return err; } diff --git a/src/core/utils/IOUtils.cpp b/src/core/utils/IOUtils.cpp index 0be11755..409cff19 100644 --- a/src/core/utils/IOUtils.cpp +++ b/src/core/utils/IOUtils.cpp @@ -49,7 +49,7 @@ auto GetFileChecksum(const QString& file_name, auto ReadFile(const QString& file_name, QByteArray& data) -> bool { QFile file(file_name); if (!file.open(QIODevice::ReadOnly)) { - GF_CORE_LOG_ERROR("failed to open file: {}", file_name); + qCWarning(core) << "failed to open file: " << file_name; return false; } data = file.readAll(); @@ -60,7 +60,7 @@ auto ReadFile(const QString& file_name, QByteArray& data) -> bool { auto WriteFile(const QString& file_name, const QByteArray& data) -> bool { QFile file(file_name); if (!file.open(QIODevice::WriteOnly)) { - GF_CORE_LOG_ERROR("failed to open file for writing: {}", file_name); + qCWarning(core) << "failed to open file for writing: " << file_name; return false; } file.write(data); @@ -100,20 +100,17 @@ auto CalculateHash(const QString& file_path) -> QString { << Qt::endl; // md5 - ss << "- " - << "MD5" << QCoreApplication::tr(": ") + ss << "- " << "MD5" << QCoreApplication::tr(": ") << GetFileChecksum(file_path, QCryptographicHash::Md5).toHex() << Qt::endl; // sha1 - ss << "- " - << "SHA1" << QCoreApplication::tr(": ") + ss << "- " << "SHA1" << QCoreApplication::tr(": ") << GetFileChecksum(file_path, QCryptographicHash::Sha1).toHex() << Qt::endl; // sha1 - ss << "- " - << "SHA256" << QCoreApplication::tr(": ") + ss << "- " << "SHA256" << QCoreApplication::tr(": ") << GetFileChecksum(file_path, QCryptographicHash::Sha256).toHex() << Qt::endl; @@ -147,8 +144,8 @@ auto CreateTempFileAndWriteData(const GFBuffer& data) -> QString { return temp_file; } -auto TargetFilePreCheck(const QString& path, bool read) - -> std::tuple<bool, QString> { +auto TargetFilePreCheck(const QString& path, + bool read) -> std::tuple<bool, QString> { QFileInfo const file_info(path); if (read) { @@ -184,16 +181,16 @@ auto CalculateBinaryChacksum(const QString& path) -> QString { // check file info and access rights QFileInfo info(path); if (!info.exists() || !info.isFile() || !info.isReadable()) { - GF_CORE_LOG_ERROR("get info for file {} error, exists: {}", info.filePath(), - info.exists()); + qCWarning(core) << "get info for file: " << info.filePath() + << " error, exists: " << info.exists(); return {}; } // open and read file QFile f(info.filePath()); if (!f.open(QIODevice::ReadOnly)) { - GF_CORE_LOG_ERROR("open {} to calculate checksum error: {}", - path.toStdString(), f.errorString().toStdString()); + qCWarning(core) << "open " << path + << "to calculate checksum error: " << f.errorString(); return {}; } @@ -204,8 +201,8 @@ auto CalculateBinaryChacksum(const QString& path) -> QString { while (!f.atEnd()) { QByteArray const buffer = f.read(buffer_size); if (buffer.isEmpty()) { - GF_CORE_LOG_ERROR("error reading file {} during checksum calculation", - path.toStdString()); + qCWarning(core) << "error reading file: " << path + << " during checksum calculation"; return {}; } hash_sha.addData(buffer); diff --git a/src/core/utils/LocalizedUtils.cpp b/src/core/utils/LocalizedUtils.cpp index e5c9b434..f38b004b 100644 --- a/src/core/utils/LocalizedUtils.cpp +++ b/src/core/utils/LocalizedUtils.cpp @@ -28,8 +28,6 @@ #include "LocalizedUtils.h" -#include "core/utils/LogUtils.h" - namespace GpgFrontend { auto GetLocalizedDateByTimestamp(time_t timestamp) -> QString { diff --git a/src/core/utils/LogUtils.cpp b/src/core/utils/LogUtils.cpp deleted file mode 100644 index fbf0c8d3..00000000 --- a/src/core/utils/LogUtils.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "LogUtils.h" - -#include "core/function/LoggerManager.h" - -namespace GpgFrontend { - -auto GetDefaultLogger() -> std::shared_ptr<spdlog::logger> { - return LoggerManager::GetDefaultLogger(); -} - -auto GetCoreLogger() -> std::shared_ptr<spdlog::logger> { - return LoggerManager::GetInstance().GetLogger("core"); -} - -auto GetLogger(const QString& id) -> std::shared_ptr<spdlog::logger> { - return LoggerManager::GetInstance().GetLogger(id); -} - -void SetDefaultLogLevel(spdlog::level::level_enum level) { - return LoggerManager::SetDefaultLogLevel(level); -} - -void RegisterAsyncLogger(const QString& id, spdlog::level::level_enum level) { - LoggerManager::GetInstance().RegisterAsyncLogger(id, level); -} - -void RegisterSyncLogger(const QString& id, spdlog::level::level_enum level) { - LoggerManager::GetInstance().RegisterSyncLogger(id, level); -} - -} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/utils/LogUtils.h b/src/core/utils/LogUtils.h deleted file mode 100644 index e8dc6f3b..00000000 --- a/src/core/utils/LogUtils.h +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -// spdlog library configuration -#undef SPDLOG_ACTIVE_LEVEL -#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE -#include <spdlog/spdlog.h> - -// logger fmt -#include "core/GpgFrontendCoreExport.h" - -template <> -struct fmt::formatter<QString> { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template <typename FormatContext> - auto format(const QString& qstr, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - QByteArray utf8_array = qstr.toUtf8(); - return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); - } -}; - -template <> -struct fmt::formatter<QByteArray> { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template <typename FormatContext> - auto format(const QByteArray& qarray, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - return fmt::format_to(ctx.out(), "{}", qarray.constData()); - } -}; - -namespace GpgFrontend { - -/** - * @brief - * - * @return std::shared_ptr<spdlog::logger> - */ -auto GPGFRONTEND_CORE_EXPORT GetDefaultLogger() - -> std::shared_ptr<spdlog::logger>; - -/** - * @brief - * - * @return std::shared_ptr<spdlog::logger> - */ -auto GPGFRONTEND_CORE_EXPORT GetCoreLogger() -> std::shared_ptr<spdlog::logger>; - -/** - * @brief - * - * @return std::shared_ptr<spdlog::logger> - */ -auto GPGFRONTEND_CORE_EXPORT GetLogger(const QString&) - -> std::shared_ptr<spdlog::logger>; - -/** - * @brief Set the Default Log Level object - * - * @return auto - */ -void GPGFRONTEND_CORE_EXPORT SetDefaultLogLevel(spdlog::level::level_enum); - -/** - * @brief - * - * @return auto - */ -void GPGFRONTEND_CORE_EXPORT RegisterAsyncLogger(const QString&, - spdlog::level::level_enum); - -/** - * @brief - * - * @return auto - */ -void GPGFRONTEND_CORE_EXPORT RegisterSyncLogger(const QString&, - spdlog::level::level_enum); - -} // namespace GpgFrontend - -#define GF_DEFAULT_LOG_TRACE(...) \ - SPDLOG_LOGGER_TRACE(GpgFrontend::GetDefaultLogger(), __VA_ARGS__) -#define GF_DEFAULT_LOG_DEBUG(...) \ - SPDLOG_LOGGER_DEBUG(GpgFrontend::GetDefaultLogger(), __VA_ARGS__) -#define GF_DEFAULT_LOG_INFO(...) \ - SPDLOG_LOGGER_INFO(GpgFrontend::GetDefaultLogger(), __VA_ARGS__) -#define GF_DEFAULT_LOG_WARN(...) \ - SPDLOG_LOGGER_WARN(GpgFrontend::GetDefaultLogger(), __VA_ARGS__) -#define GF_DEFAULT_LOG_ERROR(...) \ - SPDLOG_LOGGER_ERROR(GpgFrontend::GetDefaultLogger(), __VA_ARGS__) - -#define GF_CORE_LOG_TRACE(...) \ - SPDLOG_LOGGER_TRACE(GpgFrontend::GetCoreLogger(), __VA_ARGS__) -#define GF_CORE_LOG_DEBUG(...) \ - SPDLOG_LOGGER_DEBUG(GpgFrontend::GetCoreLogger(), __VA_ARGS__) -#define GF_CORE_LOG_INFO(...) \ - SPDLOG_LOGGER_INFO(GpgFrontend::GetCoreLogger(), __VA_ARGS__) -#define GF_CORE_LOG_WARN(...) \ - SPDLOG_LOGGER_WARN(GpgFrontend::GetCoreLogger(), __VA_ARGS__) -#define GF_CORE_LOG_ERROR(...) \ - SPDLOG_LOGGER_ERROR(GpgFrontend::GetCoreLogger(), __VA_ARGS__) - -#define GF_LOG_TRACE(ID, ...) \ - SPDLOG_LOGGER_TRACE(GpgFrontend::GetLogger(ID), __VA_ARGS__) -#define GF_LOG_DEBUG(ID, ...) \ - SPDLOG_LOGGER_DEBUG(GpgFrontend::GetLogger(ID), __VA_ARGS__) -#define GF_LOG_INFO(ID, ...) \ - SPDLOG_LOGGER_INFO(GpgFrontend::GetLogger(ID), __VA_ARGS__) -#define GF_LOG_WARN(ID, ...) \ - SPDLOG_LOGGER_WARN(GpgFrontend::GetLogger(ID), __VA_ARGS__) -#define GF_LOG_ERROR(ID, ...) \ - SPDLOG_LOGGER_ERROR(GpgFrontend::GetLogger(ID), __VA_ARGS__) diff --git a/src/init.cpp b/src/init.cpp index da89be1f..666d6701 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -33,12 +33,10 @@ #include "core/function/gpg/GpgAdvancedOperator.h" #include "core/module/ModuleInit.h" #include "core/thread/TaskRunnerGetter.h" -#include "core/utils/LogUtils.h" #include "ui/GpgFrontendUIInit.h" // main #include "GpgFrontendContext.h" -#include "main.h" namespace GpgFrontend { @@ -54,22 +52,6 @@ int setenv(const char *name, const char *value, int overwrite) { } #endif -void InitLoggingSystem(const GFCxtSPtr &ctx) { -#ifdef DEBUG - RegisterSyncLogger("core", ctx->log_level); - RegisterSyncLogger("main", ctx->log_level); - RegisterSyncLogger("module", ctx->log_level); - RegisterSyncLogger("ui", ctx->log_level); - RegisterSyncLogger("test", ctx->log_level); -#else - RegisterAsyncLogger("core", ctx->log_level); - RegisterAsyncLogger("main", ctx->log_level); - RegisterAsyncLogger("module", ctx->log_level); - RegisterAsyncLogger("ui", ctx->log_level); - RegisterAsyncLogger("test", ctx->log_level); -#endif -} - void InitGlobalPathEnv() { // read settings bool use_custom_gnupg_install_path = @@ -87,13 +69,12 @@ void InitGlobalPathEnv() { // add custom gnupg install path into env $PATH if (use_custom_gnupg_install_path && !custom_gnupg_install_path.isEmpty()) { QString path_value = getenv("PATH"); - GF_MAIN_LOG_DEBUG("Current System PATH: {}", path_value); + setenv("PATH", (QDir(custom_gnupg_install_path).absolutePath() + ":" + path_value) .toUtf8(), 1); QString modified_path_value = getenv("PATH"); - GF_MAIN_LOG_DEBUG("Modified System PATH: {}", modified_path_value); } if (GlobalSettingStation::GetInstance() @@ -102,7 +83,6 @@ void InitGlobalPathEnv() { .toBool()) { qputenv("GPGME_DEBUG", QString("9:%1").arg(QDir::currentPath() + "/gpgme.log").toUtf8()); - GF_CORE_LOG_DEBUG("GPGME_DEBUG ENV: {}", qgetenv("GPGME_DEBUG")); } } @@ -112,19 +92,11 @@ void InitGlobalBasicEnv(const GFCxtWPtr &p_ctx, bool gui_mode) { return; } - // init default locale of application - InitLocale(); - - // initialize logging system - SetDefaultLogLevel(ctx->log_level); - InitLoggingSystem(ctx); - // change path to search for related InitGlobalPathEnv(); // should load module system first Module::ModuleInitArgs module_init_args; - module_init_args.log_level = ctx->log_level; Module::LoadGpgFrontendModules(module_init_args); // then preload ui @@ -149,12 +121,16 @@ void InitLocale() { // read from settings file auto lang = settings.value("basic/lang").toString(); - GF_UI_LOG_INFO("current system default locale: {}", QLocale().name()); - GF_UI_LOG_INFO("locale settings from config: {}", lang); + qInfo() << "current system default locale: " << QLocale().name(); + qInfo() << "locale settings from config: " << lang; auto target_locale = lang.trimmed().isEmpty() ? QLocale::system() : QLocale(lang); - GF_UI_LOG_INFO("application's target locale: {}", target_locale.name()); + qInfo() << "application's target locale: " << target_locale.name(); + + // initialize locale environment + qDebug("locale info: %s", + setlocale(LC_CTYPE, target_locale.amText().toUtf8())); QLocale::setDefault(target_locale); } @@ -33,13 +33,6 @@ namespace GpgFrontend { /** - * @brief - * - * @param args - */ -void InitLoggingSystem(const GFCxtSPtr &); - -/** * @brief init global PATH env * */ diff --git a/src/main.cpp b/src/main.cpp index a99f3e30..e2690f4f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,14 +30,18 @@ * \mainpage GpgFrontend Develop Document Main Page */ +#include <qcommandlineparser.h> +#include <qloggingcategory.h> + +// #include "GpgFrontendContext.h" +#include "core/utils/MemoryUtils.h" + +// #include "app.h" #include "cmd.h" #include "init.h" -// -#include "core/utils/MemoryUtils.h" - /** * * @param argc @@ -45,15 +49,31 @@ * @return */ auto main(int argc, char* argv[]) -> int { + // initialize qt resources + Q_INIT_RESOURCE(gpgfrontend); + GpgFrontend::GFCxtSPtr const ctx = GpgFrontend::SecureCreateSharedObject<GpgFrontend::GpgFrontendContext>( argc, argv); ctx->InitApplication(); - auto rtn = 0; +#ifdef RELEASE + QLoggingCategory::setFilterRules("*.debug=false\n*.info=false\n"); + qSetMessagePattern( + "[%{time yyyyMMdd h:mm:ss.zzz}] [%{category}] " + "[%{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-" + "critical}C%{endif}%{if-fatal}F%{endif}] [%{threadid}] - " + "%{message}"); +#else + QLoggingCategory::setFilterRules("*.debug=false"); + qSetMessagePattern( + "[%{time yyyyMMdd h:mm:ss.zzz}] [%{category}] " + "[%{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-" + "critical}C%{endif}%{if-fatal}F%{endif}] [%{threadid}] %{file}:%{line} - " + "%{message}"); +#endif - // initialize qt resources - Q_INIT_RESOURCE(gpgfrontend); + auto rtn = 0; QCommandLineParser parser; parser.addHelpOption(); @@ -67,14 +87,12 @@ auto main(int argc, char* argv[]) -> int { parser.process(*ctx->GetApp()); - ctx->log_level = spdlog::level::info; - if (parser.isSet("v")) { return GpgFrontend::PrintVersion(); } if (parser.isSet("l")) { - ctx->log_level = GpgFrontend::ParseLogLevel(parser.value("l")); + GpgFrontend::ParseLogLevel(parser.value("l")); } if (parser.isSet("t")) { diff --git a/src/module/mods/gpg_info/CMakeLists.txt b/src/module/mods/gpg_info/CMakeLists.txt deleted file mode 100644 index 6660f5cb..00000000 --- a/src/module/mods/gpg_info/CMakeLists.txt +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (C) 2021 Saturneric <[email protected]> -# -# This file is part of GpgFrontend. -# -# GpgFrontend 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. -# -# GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. -# -# The initial version of the source code is inherited from -# the gpg4usb project, which is under GPL-3.0-or-later. -# -# All the source code of GpgFrontend was modified and released by -# Saturneric <[email protected]> starting on May 12, 2021. -# -# SPDX-License-Identifier: GPL-3.0-or-later - -# com.bktus.gpgfrontend.module.integrated.gnupg_info_gathering - -aux_source_directory(. INTEGRATED_MODULE_SOURCE) - -# define libgpgfrontend_module -add_library(mod_gpg_info SHARED ${INTEGRATED_MODULE_SOURCE}) -set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GFModuleExport.h") -generate_export_header(mod_gpg_info - BASE_NAME "GF_MODULE" - EXPORT_FILE_NAME "${_export_file}") - -target_include_directories(mod_gpg_info PRIVATE - ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) - -# set output directory -set_target_properties(mod_gpg_info PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mods - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mods) - -if (XCODE_BUILD) - set_target_properties(mod_gpg_info - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") -endif () - -if (LINUX AND LINUX_INSTALL_SOFTWARE) - install(TARGETS mod_gpg_info - LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/mods/") -endif() - -# link sdk -target_link_libraries(mod_gpg_info PRIVATE - gpgfrontend_module_sdk) - -if(GPGFRONTEND_QT5_BUILD) - # link Qt core - target_link_libraries(mod_gpg_info PRIVATE Qt5::Core) -else() - # link Qt core - target_link_libraries(mod_gpg_info PRIVATE Qt6::Core) -endif() - -# property -set_property(TARGET mod_gpg_info PROPERTY AUTOMOC ON) - -# using std c++ 17 -target_compile_features(mod_gpg_info PRIVATE cxx_std_17)
\ No newline at end of file diff --git a/src/module/mods/gpg_info/GFModuleExport.h b/src/module/mods/gpg_info/GFModuleExport.h deleted file mode 100644 index a1fc1053..00000000 --- a/src/module/mods/gpg_info/GFModuleExport.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef GF_MODULE_EXPORT_H -#define GF_MODULE_EXPORT_H - -#ifdef GF_MODULE_STATIC_DEFINE -# define GF_MODULE_EXPORT -# define GF_MODULE_NO_EXPORT -#else -# ifndef GF_MODULE_EXPORT -# ifdef mod_gpg_info_EXPORTS - /* We are building this library */ -# define GF_MODULE_EXPORT __attribute__((visibility("default"))) -# else - /* We are using this library */ -# define GF_MODULE_EXPORT __attribute__((visibility("default"))) -# endif -# endif - -# ifndef GF_MODULE_NO_EXPORT -# define GF_MODULE_NO_EXPORT __attribute__((visibility("hidden"))) -# endif -#endif - -#ifndef GF_MODULE_DEPRECATED -# define GF_MODULE_DEPRECATED __attribute__ ((__deprecated__)) -#endif - -#ifndef GF_MODULE_DEPRECATED_EXPORT -# define GF_MODULE_DEPRECATED_EXPORT GF_MODULE_EXPORT GF_MODULE_DEPRECATED -#endif - -#ifndef GF_MODULE_DEPRECATED_NO_EXPORT -# define GF_MODULE_DEPRECATED_NO_EXPORT GF_MODULE_NO_EXPORT GF_MODULE_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef GF_MODULE_NO_DEPRECATED -# define GF_MODULE_NO_DEPRECATED -# endif -#endif - -#endif /* GF_MODULE_EXPORT_H */ diff --git a/src/module/mods/gpg_info/GnuPGInfoGatheringModule.cpp b/src/module/mods/gpg_info/GnuPGInfoGatheringModule.cpp deleted file mode 100644 index 8d400c89..00000000 --- a/src/module/mods/gpg_info/GnuPGInfoGatheringModule.cpp +++ /dev/null @@ -1,526 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "GnuPGInfoGatheringModule.h" - -#include <GFSDKBasic.h> -#include <GFSDKBuildInfo.h> -#include <GFSDKLog.h> -#include <spdlog/spdlog.h> - -// qt -#include <QCryptographicHash> -#include <QFileInfo> -#include <QJsonDocument> -#include <QString> - -// c++ -#include <optional> - -#include "GpgInfo.h" - -template <> -struct fmt::formatter<QString> { - // Parses format specifications. - constexpr auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template <typename FormatContext> - auto format(const QString &qstr, FormatContext &ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - QByteArray utf8_array = qstr.toUtf8(); - return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); - } -}; - -template <> -struct fmt::formatter<QByteArray> { - // Parses format specifications. - constexpr auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template <typename FormatContext> - auto format(const QByteArray &qarray, FormatContext &ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - return fmt::format_to(ctx.out(), "{}", qarray.constData()); - } -}; - -extern auto CalculateBinaryChacksum(const QString &path) - -> std::optional<QString>; - -extern void GetGpgComponentInfos(void *, int, const char *, const char *); - -extern void GetGpgDirectoryInfos(void *, int, const char *, const char *); - -extern void GetGpgOptionInfos(void *, int, const char *, const char *); - -using Context = struct { - QString gpgme_version; - QString gpgconf_path; - GpgComponentInfo component_info; -}; - -auto GFGetModuleGFSDKVersion() -> const char * { - return GFModuleStrDup(GF_SDK_VERSION_STR); -} - -auto GFGetModuleQtEnvVersion() -> const char * { - return GFModuleStrDup(QT_VERSION_STR); -} - -auto GFGetModuleID() -> const char * { - return GFModuleStrDup("com.bktus.gpgfrontend.module.gnupg_info_gathering"); -} - -auto GFGetModuleVersion() -> const char * { return GFModuleStrDup("1.0.0"); } - -auto GFGetModuleMetaData() -> GFModuleMetaData * { - auto *p_meta = static_cast<GFModuleMetaData *>( - GFAllocateMemory(sizeof(GFModuleMetaData))); - auto *h_meta = p_meta; - - p_meta->key = "Name"; - p_meta->value = "GatherGnupgInfo"; - p_meta->next = static_cast<GFModuleMetaData *>( - GFAllocateMemory(sizeof(GFModuleMetaData))); - p_meta = p_meta->next; - - p_meta->key = "Description"; - p_meta->value = "Try gathering gnupg informations"; - p_meta->next = static_cast<GFModuleMetaData *>( - GFAllocateMemory(sizeof(GFModuleMetaData))); - p_meta = p_meta->next; - - p_meta->key = "Author"; - p_meta->value = "Saturneric"; - p_meta->next = nullptr; - return h_meta; -} - -auto GFRegisterModule() -> int { - GFModuleLogDebug("gnupg info gathering module registering"); - return 0; -} - -auto GFActiveModule() -> int { - GFModuleLogDebug("gnupg info gathering module activating"); - GFModuleListenEvent(GFGetModuleID(), - GFModuleStrDup("REQUEST_GATHERING_GNUPG_INFO")); - return 0; -} - -auto GFExecuteModule(GFModuleEvent *event) -> int { - GFModuleLogDebug( - fmt::format("gnupg info gathering module executing, event id: {}", - event->id) - .c_str()); - - GFModuleLogDebug("start to load extra info at module gnupginfogathering..."); - - const auto *const gpgme_version = GFModuleRetrieveRTValueOrDefault( - GFModuleStrDup("core"), GFModuleStrDup("gpgme.version"), - GFModuleStrDup("0.0.0")); - GFModuleLogDebug( - fmt::format("got gpgme version from rt: {}", gpgme_version).c_str()); - - const auto *const gpgconf_path = GFModuleRetrieveRTValueOrDefault( - GFModuleStrDup("core"), GFModuleStrDup("gpgme.ctx.gpgconf_path"), - GFModuleStrDup("")); - GFModuleLogDebug( - fmt::format("got gpgconf path from rt: {}", gpgconf_path).c_str()); - - auto context = Context{gpgme_version, gpgconf_path}; - - // get all components - const char *argv[] = {GFModuleStrDup("--list-components")}; - GFExecuteCommandSync(gpgconf_path, 1, argv, GetGpgComponentInfos, &context); - GFModuleLogDebug("load gnupg component info done."); - -#ifdef QT5_BUILD - QVector<GFCommandExecuteContext> exec_contexts; -#else - QList<GFCommandExecuteContext> exec_contexts; -#endif - - const char **argv_0 = - static_cast<const char **>(GFAllocateMemory(sizeof(const char *))); - argv_0[0] = GFModuleStrDup("--list-dirs"); - - exec_contexts.push_back( - {gpgconf_path, 1, argv_0, GetGpgDirectoryInfos, nullptr}); - - char **components_c_array; - int ret = GFModuleListRTChildKeys( - GFGetModuleID(), GFModuleStrDup("gnupg.components"), &components_c_array); - if (components_c_array == nullptr || ret == 0) return -1; - - QStringList components; - auto *p_a = components_c_array; - for (int i = 0; i < ret; i++) components.append(QString::fromUtf8(p_a[i])); - - for (const auto &component : components) { - const auto *component_info_json = GFModuleRetrieveRTValueOrDefault( - GFGetModuleID(), - GFModuleStrDup(QString("gnupg.components.%1").arg(component).toUtf8()), - nullptr); - - if (component_info_json == nullptr) continue; - - auto jsonlized_component_info = - QJsonDocument::fromJson(component_info_json); - assert(jsonlized_component_info.isObject()); - - auto component_info = GpgComponentInfo(jsonlized_component_info.object()); - GFModuleLogDebug(fmt::format("gpgconf check options ready, " - "component: {}", - component_info.name) - .c_str()); - - if (component_info.name == "gpgme" || component_info.name == "gpgconf") { - continue; - } - - auto *context = new (GFAllocateMemory(sizeof(Context))) - Context{gpgme_version, gpgconf_path, component_info}; - - const char **argv_0 = - static_cast<const char **>(GFAllocateMemory(sizeof(const char *) * 2)); - argv_0[0] = GFModuleStrDup("--list-options"), - argv_0[1] = GFModuleStrDup(component_info.name.toUtf8()); - exec_contexts.push_back( - {gpgconf_path, 2, argv_0, GetGpgOptionInfos, context}); - } - - GFExecuteCommandBatchSync(static_cast<int32_t>(exec_contexts.size()), - exec_contexts.constData()); - GFModuleUpsertRTValueBool(GFGetModuleID(), - GFModuleStrDup("gnupg.gathering_done"), 1); - - char **event_argv = - static_cast<char **>(GFAllocateMemory(sizeof(char **) * 1)); - event_argv[0] = GFModuleStrDup("0"); - - GFModuleTriggerModuleEventCallback(event, GFGetModuleID(), 1, event_argv); - - GFModuleLogDebug("gnupg external info gathering done"); - return 0; -} - -auto GFDeactiveModule() -> int { return 0; } - -auto GFUnregisterModule() -> int { - GFModuleLogDebug("gnupg info gathering module unregistering"); - return 0; -} - -auto CalculateBinaryChacksum(const QString &path) -> std::optional<QString> { - // check file info and access rights - QFileInfo info(path); - if (!info.exists() || !info.isFile() || !info.isReadable()) { - GFModuleLogError(fmt::format("get info for file {} error, exists: {}", - info.filePath(), info.exists()) - .c_str()); - return {}; - } - - // open and read file - QFile f(info.filePath()); - if (!f.open(QIODevice::ReadOnly)) { - GFModuleLogError(fmt::format("open {} to calculate checksum error: {}", - path.toStdString(), - f.errorString().toStdString()) - .c_str()); - return {}; - } - - QCryptographicHash hash_sha(QCryptographicHash::Sha256); - - // read data by chunks - const qint64 buffer_size = 8192; // Define a suitable buffer size - while (!f.atEnd()) { - QByteArray const buffer = f.read(buffer_size); - if (buffer.isEmpty()) { - GFModuleLogError(fmt::format("error reading file {} during " - "checksum calculation", - path.toStdString()) - .c_str()); - return {}; - } - hash_sha.addData(buffer); - } - - // close the file - f.close(); - - // return the first 6 characters of the SHA-256 hash - // of the file - return QString(hash_sha.result().toHex()).left(6); -} - -void GetGpgComponentInfos(void *data, int exit_code, const char *out, - const char *err) { - auto *context = reinterpret_cast<Context *>(data); - auto p_out = QString::fromUtf8(out); - auto p_err = QString::fromUtf8(err); - - GFModuleLogDebug(fmt::format("gpgconf components exit_code: {} " - "process stdout size: {}", - exit_code, p_out.size()) - .c_str()); - - if (exit_code != 0) { - GFModuleLogError(fmt::format("gpgconf execute error, process " - "stderr: {}, " - "process stdout: {}", - p_err, p_out) - .c_str()); - return; - } - - std::vector<GpgComponentInfo> component_infos; - GpgComponentInfo c_i_gpgme; - c_i_gpgme.name = "gpgme"; - c_i_gpgme.desc = "GPG Made Easy"; - c_i_gpgme.version = context->gpgme_version; - c_i_gpgme.path = "Embedded In"; - c_i_gpgme.binary_checksum = "/"; - - GpgComponentInfo c_i_gpgconf; - c_i_gpgconf.name = "gpgconf"; - c_i_gpgconf.desc = "GPG Configure"; - c_i_gpgconf.version = "/"; - c_i_gpgconf.path = context->gpgconf_path; - auto gpgconf_binary_checksum = CalculateBinaryChacksum(context->gpgconf_path); - c_i_gpgconf.binary_checksum = - (gpgconf_binary_checksum.has_value() ? gpgconf_binary_checksum.value() - : QString("/")); - - component_infos.push_back(c_i_gpgme); - component_infos.push_back(c_i_gpgconf); - - auto const jsonlized_gpgme_component_info = c_i_gpgme.Json(); - auto const jsonlized_gpgconf_component_info = c_i_gpgconf.Json(); - GFModuleUpsertRTValue( - GFGetModuleID(), GFModuleStrDup("gnupg.components.gpgme"), - GFModuleStrDup(QJsonDocument(jsonlized_gpgme_component_info).toJson())); - GFModuleUpsertRTValue( - GFGetModuleID(), GFModuleStrDup("gnupg.components.gpgconf"), - GFModuleStrDup(QJsonDocument(jsonlized_gpgconf_component_info).toJson())); - - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - - if (info_split_list.size() != 3) continue; - - auto component_name = info_split_list[0].trimmed(); - auto component_desc = info_split_list[1].trimmed(); - auto component_path = info_split_list[2].trimmed(); - -#ifdef WINDOWS - // replace some special substrings on windows - // platform - component_path.replace("%3a", ":"); -#endif - - auto binary_checksum = CalculateBinaryChacksum(component_path); - - GFModuleLogDebug( - fmt::format("gnupg component name: {} desc: " - "{} checksum: {} path: {} ", - component_name, component_desc, - binary_checksum.has_value() ? binary_checksum.value() : "/", - component_path) - .c_str()); - - QString version = "/"; - - if (component_name == "gpg") { - version = GFModuleRetrieveRTValueOrDefault( - GFModuleStrDup("core"), GFModuleStrDup("gpgme.ctx.gnupg_version"), - GFModuleStrDup("2.0.0")); - } - if (component_name == "gpg-agent") { - GFModuleUpsertRTValue(GFGetModuleID(), - GFModuleStrDup("gnupg.gpg_agent_path"), - GFModuleStrDup(QString(component_path).toUtf8())); - } - if (component_name == "dirmngr") { - GFModuleUpsertRTValue(GFGetModuleID(), - GFModuleStrDup("gnupg.dirmngr_path"), - GFModuleStrDup(QString(component_path).toUtf8())); - } - if (component_name == "keyboxd") { - GFModuleUpsertRTValue(GFGetModuleID(), - GFModuleStrDup("gnupg.keyboxd_path"), - GFModuleStrDup(QString(component_path).toUtf8())); - } - - { - GpgComponentInfo c_i; - c_i.name = component_name; - c_i.desc = component_desc; - c_i.version = version; - c_i.path = component_path; - c_i.binary_checksum = - (binary_checksum.has_value() ? binary_checksum.value() - : QString("/")); - - auto const jsonlized_component_info = c_i.Json(); - GFModuleUpsertRTValue( - GFGetModuleID(), - GFModuleStrDup( - QString("gnupg.components.%1").arg(component_name).toUtf8()), - GFModuleStrDup(QJsonDocument(jsonlized_component_info).toJson())); - - component_infos.push_back(c_i); - } - - GFModuleLogDebug("load gnupg component info actually done."); - } -} - -void GetGpgDirectoryInfos(void *, int exit_code, const char *out, - const char *err) { - if (exit_code != 0) return; - - auto p_out = QString::fromUtf8(out); - auto p_err = QString::fromUtf8(err); - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - GFModuleLogDebug(fmt::format("gpgconf direcrotries info line: " - "{} info size: {}", - line, info_split_list.size()) - .c_str()); - - if (info_split_list.size() != 2) continue; - - auto configuration_name = info_split_list[0].trimmed(); - auto configuration_value = info_split_list[1].trimmed(); - -#ifdef WINDOWS - // replace some special substrings on windows - // platform - configuration_value.replace("%3a", ":"); -#endif - - // record gnupg home path - if (configuration_name == "homedir") { - GFModuleUpsertRTValue(GFGetModuleID(), GFModuleStrDup("gnupg.home_path"), - GFModuleStrDup(configuration_value.toUtf8())); - } - - GFModuleUpsertRTValue( - GFGetModuleID(), - GFModuleStrDup( - QString("gnupg.dirs.%1").arg(configuration_name).toUtf8()), - GFModuleStrDup(configuration_value.toUtf8())); - } -} - -void GetGpgOptionInfos(void *data, int exit_code, const char *out, - const char *err) { - if (exit_code != 0) return; - - auto p_out = QString::fromUtf8(out); - auto p_err = QString::fromUtf8(err); - auto *context = reinterpret_cast<Context *>(data); - auto component_name = context->component_info.name; - - GFModuleLogDebug(fmt::format("gpgconf {} avaliable options " - "exit_code: {} process stdout " - "size: {} ", - component_name, exit_code, p_out.size()) - .c_str()); - - std::vector<GpgOptionsInfo> options_infos; - - auto line_split_list = p_out.split("\n"); - - for (const auto &line : line_split_list) { - auto info_split_list = line.split(":"); - - GFModuleLogDebug(fmt::format("component {} avaliable options " - "line: {} info size: {}", - component_name, line, info_split_list.size()) - .c_str()); - - if (info_split_list.size() < 10) continue; - - // The format of each line is: - // name:flags:level:description:type:alt-type:argname:default:argdef:value - - auto option_name = info_split_list[0].trimmed(); - auto option_flags = info_split_list[1].trimmed(); - auto option_level = info_split_list[2].trimmed(); - auto option_desc = info_split_list[3].trimmed(); - auto option_type = info_split_list[4].trimmed(); - auto option_alt_type = info_split_list[5].trimmed(); - auto option_argname = info_split_list[6].trimmed(); - auto option_default = info_split_list[7].trimmed(); - auto option_argdef = info_split_list[8].trimmed(); - auto option_value = info_split_list[9].trimmed(); - - GpgOptionsInfo info; - info.name = option_name; - info.flags = option_flags; - info.level = option_level; - info.description = option_desc; - info.type = option_type; - info.alt_type = option_alt_type; - info.argname = option_argname; - info.default_value = option_default; - info.argdef = option_argdef; - info.value = option_value; - - auto const jsonlized_option_info = info.Json(); - GFModuleUpsertRTValue( - GFGetModuleID(), - GFModuleStrDup(QString("gnupg.components.%1.options.%2") - .arg(component_name) - .arg(option_name) - .toUtf8()), - GFModuleStrDup(QJsonDocument(jsonlized_option_info).toJson())); - options_infos.push_back(info); - } - - context->~Context(); - GFFreeMemory(context); -} diff --git a/src/module/mods/gpg_info/GpgInfo.cpp b/src/module/mods/gpg_info/GpgInfo.cpp deleted file mode 100644 index 680f4a8a..00000000 --- a/src/module/mods/gpg_info/GpgInfo.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "GpgInfo.h" - -GpgOptionsInfo::GpgOptionsInfo(const QJsonObject &j) { - if (const auto v = j["name"]; v.isString()) name = v.toString(); - if (const auto v = j["flags"]; v.isString()) flags = v.toString(); - if (const auto v = j["level"]; v.isString()) level = v.toString(); - if (const auto v = j["description"]; v.isString()) description = v.toString(); - if (const auto v = j["type"]; v.isString()) type = v.toString(); - if (const auto v = j["alt_type"]; v.isString()) alt_type = v.toString(); - if (const auto v = j["argname"]; v.isString()) argname = v.toString(); - if (const auto v = j["default_value"]; v.isString()) { - default_value = v.toString(); - } - if (const auto v = j["argdef"]; v.isString()) argdef = v.toString(); - if (const auto v = j["value"]; v.isString()) value = v.toString(); -} - -auto GpgOptionsInfo::Json() const -> QJsonObject { - QJsonObject j; - j["name"] = name; - j["flags"] = flags; - j["level"] = level; - j["description"] = description; - j["type"] = type; - j["alt_type"] = alt_type; - j["argname"] = argname; - j["default_value"] = default_value; - j["argdef"] = argdef; - j["value"] = value; - return j; -} - -auto GpgComponentInfo::Json() const -> QJsonObject { - QJsonObject j; - j["name"] = name; - j["desc"] = desc; - j["version"] = version; - j["path"] = path; - j["binary_checksum"] = binary_checksum; - return j; -} - -GpgComponentInfo::GpgComponentInfo(const QJsonObject &j) { - if (const auto v = j["name"]; v.isString()) name = v.toString(); - if (const auto v = j["desc"]; v.isString()) desc = v.toString(); - if (const auto v = j["version"]; v.isString()) version = v.toString(); - if (const auto v = j["path"]; v.isString()) path = v.toString(); - if (const auto v = j["binary_checksum"]; v.isString()) { - binary_checksum = v.toString(); - } -} diff --git a/src/module/mods/gpg_info/GpgInfo.h b/src/module/mods/gpg_info/GpgInfo.h deleted file mode 100644 index 1aacc207..00000000 --- a/src/module/mods/gpg_info/GpgInfo.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include <QJsonObject> -#include <QString> -#include <map> - -/** - * @brief Use to record some info about gnupg - * - */ -class GpgInfo { - public: - QString GnuPGHomePath; ///< value of ---homedir - - std::map<QString, std::vector<QString>> ComponentsInfo; ///< - std::map<QString, std::vector<QString>> ConfigurationsInfo; ///< - std::map<QString, std::vector<QString>> OptionsInfo; ///< - std::map<QString, std::vector<QString>> AvailableOptionsInfo; ///< -}; - -/** - * @brief Use to record some info about gnupg components - * - */ -struct GpgComponentInfo { - QString name; - QString desc; - QString version; - QString path; - QString binary_checksum; - - GpgComponentInfo() = default; - - explicit GpgComponentInfo(const QJsonObject &j); - - [[nodiscard]] auto Json() const -> QJsonObject; -}; - -/** - * The format of each line is: - * name:flags:level:description:type:alt-type:argname:default:argdef:value - */ -struct GpgOptionsInfo { - QString name; - QString flags; - QString level; - QString description; - QString type; - QString alt_type; - QString argname; - QString default_value; - QString argdef; - QString value; - - GpgOptionsInfo() = default; - - explicit GpgOptionsInfo(const QJsonObject &j); - - [[nodiscard]] auto Json() const -> QJsonObject; -}; diff --git a/src/module/mods/gpg_info/QtLoggerFmt.h b/src/module/mods/gpg_info/QtLoggerFmt.h deleted file mode 100644 index 23997465..00000000 --- a/src/module/mods/gpg_info/QtLoggerFmt.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include <spdlog/spdlog.h> - -#include <QString> - -template <> -struct fmt::formatter<QString> { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template <typename FormatContext> - auto format(const QString& qstr, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - QByteArray utf8_array = qstr.toUtf8(); - return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); - } -}; - -template <> -struct fmt::formatter<QByteArray> { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template <typename FormatContext> - auto format(const QByteArray& qarray, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - return fmt::format_to(ctx.out(), "{}", qarray.constData()); - } -}; diff --git a/src/module/mods/ver_check/CMakeLists.txt b/src/module/mods/ver_check/CMakeLists.txt deleted file mode 100644 index b07a499a..00000000 --- a/src/module/mods/ver_check/CMakeLists.txt +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (C) 2021 Saturneric <[email protected]> -# -# This file is part of GpgFrontend. -# -# GpgFrontend 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. -# -# GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. -# -# The initial version of the source code is inherited from -# the gpg4usb project, which is under GPL-3.0-or-later. -# -# All the source code of GpgFrontend was modified and released by -# Saturneric <[email protected]> starting on May 12, 2021. -# -# SPDX-License-Identifier: GPL-3.0-or-later - -# com.bktus.gpgfrontend.module.integrated.version_checking - -aux_source_directory(. INTEGRATED_MODULE_SOURCE) - -# define libgpgfrontend_module -add_library(mod_ver_check SHARED ${INTEGRATED_MODULE_SOURCE}) -set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GFModuleExport.h") -generate_export_header(mod_ver_check - BASE_NAME "GF_MODULE" - EXPORT_FILE_NAME "${_export_file}") - -target_include_directories(mod_ver_check PRIVATE - ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) - -# set output directory -set_target_properties(mod_ver_check PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mods - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/mods) - -if (XCODE_BUILD) - set_target_properties(mod_ver_check - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") -endif () - -if (LINUX AND LINUX_INSTALL_SOFTWARE) - install(TARGETS mod_ver_check - LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/mods/") -endif() - -# link sdk -target_link_libraries(mod_ver_check PRIVATE - gpgfrontend_module_sdk) - -if(GPGFRONTEND_QT5_BUILD) - # link Qt - target_link_libraries(mod_ver_check PUBLIC Qt5::Core Qt5::Network) -else() - # link Qt - target_link_libraries(mod_ver_check PUBLIC Qt6::Core Qt6::Network) -endif() - -# property -set_property(TARGET mod_ver_check PROPERTY AUTOMOC ON) - -# using std c++ 17 -target_compile_features(mod_ver_check PRIVATE cxx_std_17)
\ No newline at end of file diff --git a/src/module/mods/ver_check/GFModuleExport.h b/src/module/mods/ver_check/GFModuleExport.h deleted file mode 100644 index ce663b5f..00000000 --- a/src/module/mods/ver_check/GFModuleExport.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef GF_MODULE_EXPORT_H -#define GF_MODULE_EXPORT_H - -#ifdef GF_MODULE_STATIC_DEFINE -# define GF_MODULE_EXPORT -# define GF_MODULE_NO_EXPORT -#else -# ifndef GF_MODULE_EXPORT -# ifdef mod_ver_check_EXPORTS - /* We are building this library */ -# define GF_MODULE_EXPORT __attribute__((visibility("default"))) -# else - /* We are using this library */ -# define GF_MODULE_EXPORT __attribute__((visibility("default"))) -# endif -# endif - -# ifndef GF_MODULE_NO_EXPORT -# define GF_MODULE_NO_EXPORT __attribute__((visibility("hidden"))) -# endif -#endif - -#ifndef GF_MODULE_DEPRECATED -# define GF_MODULE_DEPRECATED __attribute__ ((__deprecated__)) -#endif - -#ifndef GF_MODULE_DEPRECATED_EXPORT -# define GF_MODULE_DEPRECATED_EXPORT GF_MODULE_EXPORT GF_MODULE_DEPRECATED -#endif - -#ifndef GF_MODULE_DEPRECATED_NO_EXPORT -# define GF_MODULE_DEPRECATED_NO_EXPORT GF_MODULE_NO_EXPORT GF_MODULE_DEPRECATED -#endif - -#if 0 /* DEFINE_NO_DEPRECATED */ -# ifndef GF_MODULE_NO_DEPRECATED -# define GF_MODULE_NO_DEPRECATED -# endif -#endif - -#endif /* GF_MODULE_EXPORT_H */ diff --git a/src/module/mods/ver_check/QtLoggerFmt.h b/src/module/mods/ver_check/QtLoggerFmt.h deleted file mode 100644 index 23997465..00000000 --- a/src/module/mods/ver_check/QtLoggerFmt.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include <spdlog/spdlog.h> - -#include <QString> - -template <> -struct fmt::formatter<QString> { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template <typename FormatContext> - auto format(const QString& qstr, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - QByteArray utf8_array = qstr.toUtf8(); - return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); - } -}; - -template <> -struct fmt::formatter<QByteArray> { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template <typename FormatContext> - auto format(const QByteArray& qarray, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - return fmt::format_to(ctx.out(), "{}", qarray.constData()); - } -}; diff --git a/src/module/mods/ver_check/SoftwareVersion.cpp b/src/module/mods/ver_check/SoftwareVersion.cpp deleted file mode 100644 index cd864195..00000000 --- a/src/module/mods/ver_check/SoftwareVersion.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "SoftwareVersion.h" - -#include <GFSDKBasic.h> -#include <GFSDKExtra.h> -#include <GFSDKLog.h> -#include <spdlog/spdlog.h> - -#include <QString> - -template <> -struct fmt::formatter<QString> { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template <typename FormatContext> - auto format(const QString& qstr, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - QByteArray utf8_array = qstr.toUtf8(); - return fmt::format_to(ctx.out(), "{}", utf8_array.constData()); - } -}; - -template <> -struct fmt::formatter<QByteArray> { - // Parses format specifications. - constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); - } - - // Formats the QString qstr and writes it to the output. - template <typename FormatContext> - auto format(const QByteArray& qarray, FormatContext& ctx) const - -> decltype(ctx.out()) { - // Convert QString to UTF-8 QString (to handle Unicode characters - // correctly) - return fmt::format_to(ctx.out(), "{}", qarray.constData()); - } -}; - -auto SoftwareVersion::NeedUpgrade() const -> bool { - GFModuleLogDebug( - fmt::format( - "compair version current {} latest {}, result {}", current_version, - latest_version, - GFCompareSoftwareVersion(GFModuleStrDup(current_version.toUtf8()), - GFModuleStrDup(latest_version.toUtf8()))) - .c_str()); - - GFModuleLogDebug(fmt::format("load done: {}, pre-release: {}, draft: {}", - loading_done, - latest_prerelease_version_from_remote, - latest_draft_from_remote) - .c_str()); - return loading_done && !latest_prerelease_version_from_remote && - !latest_draft_from_remote && - GFCompareSoftwareVersion(GFModuleStrDup(current_version.toUtf8()), - GFModuleStrDup(latest_version.toUtf8())) < 0; -} - -auto SoftwareVersion::VersionWithdrawn() const -> bool { - return loading_done && !current_version_publish_in_remote && - current_version_is_a_prerelease && !current_version_is_drafted; -} - -auto SoftwareVersion::CurrentVersionReleased() const -> bool { - return loading_done && current_version_publish_in_remote; -}
\ No newline at end of file diff --git a/src/module/mods/ver_check/SoftwareVersion.h b/src/module/mods/ver_check/SoftwareVersion.h deleted file mode 100644 index 6b05d413..00000000 --- a/src/module/mods/ver_check/SoftwareVersion.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include <QString> - -/** - * @brief - * - */ -struct SoftwareVersion { - QString latest_version; ///< - QString current_version; ///< - bool latest_prerelease_version_from_remote = false; ///< - bool latest_draft_from_remote = false; ///< - bool current_version_is_a_prerelease = false; ///< - bool current_version_is_drafted = false; ///< - bool loading_done = false; ///< - bool current_version_publish_in_remote = false; ///< - QString publish_date; ///< - QString release_note; ///< - - /** - * @brief - * - * @return true - * @return false - */ - [[nodiscard]] auto InfoValid() const -> bool { return loading_done; } - - /** - * @brief - * - * @return true - * @return false - */ - [[nodiscard]] auto NeedUpgrade() const -> bool; - - /** - * @brief - * - * @return true - * @return false - */ - [[nodiscard]] auto VersionWithdrawn() const -> bool; - - /** - * @brief - * - * @return true - * @return false - */ - [[nodiscard]] auto CurrentVersionReleased() const -> bool; - - private: - static auto version_compare(const QString& a, const QString& b) -> int; -}; diff --git a/src/module/mods/ver_check/VersionCheckTask.cpp b/src/module/mods/ver_check/VersionCheckTask.cpp deleted file mode 100644 index 5ea9c48e..00000000 --- a/src/module/mods/ver_check/VersionCheckTask.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "VersionCheckTask.h" - -#include <GFSDKBasic.h> -#include <GFSDKExtra.h> -#include <GFSDKLog.h> - -#include <QMetaType> -#include <QtNetwork> - -VersionCheckTask::VersionCheckTask() - : network_manager_(new QNetworkAccessManager(this)), - current_version_(GFProjectVersion()) { - qRegisterMetaType<SoftwareVersion>("SoftwareVersion"); - version_.current_version = current_version_; -} - -auto VersionCheckTask::Run() -> int { - GFModuleLogDebug( - fmt::format("current project version: {}", current_version_).c_str()); - QString latest_version_url = - "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; - - QNetworkRequest latest_request(latest_version_url); - latest_request.setHeader(QNetworkRequest::UserAgentHeader, - GFHttpRequestUserAgent()); - - latest_reply_ = network_manager_->get(latest_request); - connect(latest_reply_, &QNetworkReply::finished, this, - &VersionCheckTask::slot_parse_latest_version_info); - return 0; -} - -void VersionCheckTask::slot_parse_latest_version_info() { - if (latest_reply_ == nullptr) { - version_.latest_version = current_version_; - version_.loading_done = false; - } else if (latest_reply_->error() != QNetworkReply::NoError) { - GFModuleLogError(fmt::format("latest version request error: ", - latest_reply_->errorString()) - .c_str()); - version_.latest_version = current_version_; - } else { - latest_reply_bytes_ = latest_reply_->readAll(); - auto latest_reply_json = QJsonDocument::fromJson(latest_reply_bytes_); - - if (latest_reply_json.isObject()) { - QString latest_version = latest_reply_json["tag_name"].toString(); - - QRegularExpression re(R"(^[vV](\d+\.)?(\d+\.)?(\*|\d+))"); - auto version_match = re.match(latest_version); - if (version_match.hasMatch()) { - latest_version = version_match.captured(0); - GFModuleLogInfo(fmt::format("latest released version from github: {}", - latest_version) - .c_str()); - } else { - latest_version = current_version_; - GFModuleLogWarn( - fmt::format("latest version unknown, set to current version: {}", - current_version_) - .c_str()); - } - - bool prerelease = latest_reply_json["prerelease"].toBool(); - bool draft = latest_reply_json["draft"].toBool(); - auto publish_date = latest_reply_json["published_at"].toString(); - auto release_note = latest_reply_json["body"].toString(); - version_.latest_version = latest_version; - version_.latest_prerelease_version_from_remote = prerelease; - version_.latest_draft_from_remote = draft; - version_.publish_date = publish_date; - version_.release_note = release_note; - } else { - GFModuleLogWarn(fmt::format("cannot parse data got from github: {}", - latest_reply_bytes_) - .c_str()); - } - } - - if (latest_reply_ != nullptr) { - latest_reply_->deleteLater(); - } - - try { - QString current_version_url = - "https://api.github.com/repos/saturneric/gpgfrontend/releases/tags/" + - current_version_; - GFModuleLogDebug( - fmt::format("current version info query url: {}", current_version_url) - .c_str()); - - QNetworkRequest current_request(current_version_url); - current_request.setHeader(QNetworkRequest::UserAgentHeader, - GFHttpRequestUserAgent()); - - current_reply_ = network_manager_->get(current_request); - - connect(current_reply_, &QNetworkReply::finished, this, - &VersionCheckTask::slot_parse_current_version_info); - } catch (...) { - GFModuleLogError("current version request create error"); - } -} - -void VersionCheckTask::slot_parse_current_version_info() { - if (current_reply_ == nullptr) { - // loading done - version_.loading_done = false; - - } else if (current_reply_->error() != QNetworkReply::NoError) { - GFModuleLogError(fmt::format("current version request network error: {}", - current_reply_->errorString()) - .c_str()); - - // loading done - version_.loading_done = true; - version_.current_version_publish_in_remote = false; - } else { - version_.current_version_publish_in_remote = true; - current_reply_bytes_ = current_reply_->readAll(); - auto current_reply_json = QJsonDocument::fromJson(current_reply_bytes_); - - if (current_reply_json.isObject()) { - bool current_prerelease = current_reply_json["prerelease"].toBool(); - bool current_draft = current_reply_json["draft"].toBool(); - version_.latest_prerelease_version_from_remote = current_prerelease; - version_.latest_draft_from_remote = current_draft; - // loading done - version_.loading_done = true; - } else { - GFModuleLogWarn(fmt::format("cannot parse data got from github: {}", - current_reply_bytes_) - .c_str()); - } - } - - GFModuleLogDebug(fmt::format("current version parse done: {}", - version_.current_version_publish_in_remote) - .c_str()); - - if (current_reply_ != nullptr) current_reply_->deleteLater(); - emit SignalUpgradeVersion(version_); -} diff --git a/src/module/mods/ver_check/VersionCheckTask.h b/src/module/mods/ver_check/VersionCheckTask.h deleted file mode 100644 index df801570..00000000 --- a/src/module/mods/ver_check/VersionCheckTask.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include <core/thread/Task.h> - -#include "SoftwareVersion.h" - -class QNetworkReply; -class QNetworkAccessManager; - -/** - * @brief - * - */ -class VersionCheckTask : public QObject { - Q_OBJECT - public: - /** - * @brief Construct a new Version Check Thread object - * - */ - VersionCheckTask(); - - /** - * @brief - * - * @return int - */ - auto Run() -> int; - - signals: - - /** - * @brief - * - * @param version - */ - void SignalUpgradeVersion(SoftwareVersion version); - - private slots: - - /** - * @brief - * - */ - void slot_parse_latest_version_info(); - - /** - * @brief - * - */ - void slot_parse_current_version_info(); - - private: - QByteArray latest_reply_bytes_; ///< - QByteArray current_reply_bytes_; ///< - QNetworkReply* latest_reply_ = nullptr; ///< latest version info reply - QNetworkReply* current_reply_ = nullptr; ///< current version info reply - QNetworkAccessManager* network_manager_; ///< - QString current_version_; - SoftwareVersion version_; -}; diff --git a/src/module/mods/ver_check/VersionCheckingModule.cpp b/src/module/mods/ver_check/VersionCheckingModule.cpp deleted file mode 100644 index 35d3b82e..00000000 --- a/src/module/mods/ver_check/VersionCheckingModule.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "VersionCheckingModule.h" - -#include <GFSDKBasic.h> -#include <GFSDKBuildInfo.h> -#include <GFSDKExtra.h> -#include <GFSDKLog.h> -#include <spdlog/spdlog.h> - -#include <QMetaType> -#include <QtNetwork> - -#include "SoftwareVersion.h" -#include "VersionCheckTask.h" - -extern void VersionCheckDone(const SoftwareVersion& version); - -auto GFGetModuleGFSDKVersion() -> const char* { - return GFModuleStrDup(GF_SDK_VERSION_STR); -} - -auto GFGetModuleQtEnvVersion() -> const char* { - return GFModuleStrDup(QT_VERSION_STR); -} - -auto GFGetModuleID() -> const char* { - return GFModuleStrDup("com.bktus.gpgfrontend.module.version_checking"); -} - -auto GFGetModuleVersion() -> const char* { return GFModuleStrDup("1.0.0"); } - -auto GFGetModuleMetaData() -> GFModuleMetaData* { - auto* p_meta = static_cast<GFModuleMetaData*>( - GFAllocateMemory(sizeof(GFModuleMetaData))); - auto* h_meta = p_meta; - - p_meta->key = "Name"; - p_meta->value = "VersionChecking"; - p_meta->next = static_cast<GFModuleMetaData*>( - GFAllocateMemory(sizeof(GFModuleMetaData))); - p_meta = p_meta->next; - - p_meta->key = "Description"; - p_meta->value = "Try checking gpgfrontend version"; - p_meta->next = static_cast<GFModuleMetaData*>( - GFAllocateMemory(sizeof(GFModuleMetaData))); - p_meta = p_meta->next; - - p_meta->key = "Author"; - p_meta->value = "Saturneric"; - p_meta->next = nullptr; - - return h_meta; -} - -auto GFRegisterModule() -> int { - GFModuleLogInfo("version checking module registering"); - return 0; -} - -auto GFActiveModule() -> int { - GFModuleLogInfo("version checking module activating"); - - GFModuleListenEvent(GFGetModuleID(), GFModuleStrDup("APPLICATION_LOADED")); - GFModuleListenEvent(GFGetModuleID(), - GFModuleStrDup("CHECK_APPLICATION_VERSION")); - return 0; -} - -auto GFExecuteModule(GFModuleEvent* event) -> int { - GFModuleLogInfo( - fmt::format("version checking module executing, event id: {}", event->id) - .c_str()); - - auto* task = new VersionCheckTask(); - QObject::connect( - task, &VersionCheckTask::SignalUpgradeVersion, QThread::currentThread(), - [event](const SoftwareVersion& version) { - VersionCheckDone(version); - - char** event_argv = - static_cast<char**>(GFAllocateMemory(sizeof(char**) * 1)); - event_argv[0] = GFModuleStrDup("0"); - - GFModuleTriggerModuleEventCallback(event, GFGetModuleID(), 1, - event_argv); - }); - QObject::connect(task, &VersionCheckTask::SignalUpgradeVersion, task, - &QObject::deleteLater); - task->Run(); - - return 0; -} - -auto GFDeactiveModule() -> int { return 0; } - -auto GFUnregisterModule() -> int { return 0; } - -void VersionCheckDone(const SoftwareVersion& version) { - GFModuleLogDebug("filling software information info in rt..."); - - GFModuleUpsertRTValue(GFGetModuleID(), - GFModuleStrDup("version.current_version"), - GFModuleStrDup(version.current_version.toUtf8())); - GFModuleUpsertRTValue(GFGetModuleID(), - GFModuleStrDup("version.latest_version"), - GFModuleStrDup(version.latest_version.toUtf8())); - GFModuleUpsertRTValueBool( - GFGetModuleID(), GFModuleStrDup("version.current_version_is_drafted"), - version.current_version_is_drafted ? 1 : 0); - GFModuleUpsertRTValueBool( - GFGetModuleID(), - GFModuleStrDup("version.current_version_is_a_prerelease"), - version.current_version_is_a_prerelease ? 1 : 0); - GFModuleUpsertRTValueBool( - GFGetModuleID(), - GFModuleStrDup("version.current_version_publish_in_remote"), - version.current_version_publish_in_remote ? 1 : 0); - GFModuleUpsertRTValueBool( - GFGetModuleID(), - GFModuleStrDup("version.latest_prerelease_version_from_remote"), - version.latest_prerelease_version_from_remote ? 1 : 0); - GFModuleUpsertRTValueBool(GFGetModuleID(), - GFModuleStrDup("version.need_upgrade"), - version.NeedUpgrade() ? 1 : 0); - GFModuleUpsertRTValueBool(GFGetModuleID(), - GFModuleStrDup("version.current_version_released"), - version.CurrentVersionReleased() ? 1 : 0); - GFModuleUpsertRTValueBool( - GFGetModuleID(), GFModuleStrDup("version.current_a_withdrawn_version"), - version.VersionWithdrawn() ? 1 : 0); - GFModuleUpsertRTValueBool(GFGetModuleID(), - GFModuleStrDup("version.loading_done"), - version.loading_done ? 1 : 0); - - GFModuleLogDebug("software information filled in rt"); -} diff --git a/src/module/sdk/GFSDKBuildInfo.h b/src/module/sdk/GFSDKBuildInfo.h deleted file mode 100644 index a64d95c5..00000000 --- a/src/module/sdk/GFSDKBuildInfo.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#define GF_SDK_VERSION_MAJOR "2" -#define GF_SDK_VERSION_MINOR "1" -#define GF_SDK_VERSION_PATCH "3" - -#define GF_SDK_VERSION_STR \ - GF_SDK_VERSION_MAJOR "." GF_SDK_VERSION_MINOR "." GF_SDK_VERSION_PATCH diff --git a/src/module/sdk/GFSDKLog.cpp b/src/module/sdk/GFSDKLog.cpp deleted file mode 100644 index 603cc325..00000000 --- a/src/module/sdk/GFSDKLog.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "GFSDKLog.h" - -#include "core/utils/LogUtils.h" - -#define MODULE_LOG_TRACE(...) GF_LOG_TRACE("module", __VA_ARGS__) -#define MODULE_LOG_DEBUG(...) GF_LOG_DEBUG("module", __VA_ARGS__) -#define MODULE_LOG_INFO(...) GF_LOG_INFO("module", __VA_ARGS__) -#define MODULE_LOG_WARN(...) GF_LOG_WARN("module", __VA_ARGS__) -#define MODULE_LOG_ERROR(...) GF_LOG_ERROR("module", __VA_ARGS__) - -void GFModuleLogTrace(const char* l) { MODULE_LOG_TRACE(l); } - -void GFModuleLogDebug(const char* l) { MODULE_LOG_DEBUG(l); } - -void GFModuleLogInfo(const char* l) { MODULE_LOG_INFO(l); } - -void GFModuleLogWarn(const char* l) { MODULE_LOG_WARN(l); } - -void GFModuleLogError(const char* l) { MODULE_LOG_ERROR(l); } diff --git a/src/module/sdk/GFSDKUI.cpp b/src/module/sdk/GFSDKUI.cpp deleted file mode 100644 index 63859763..00000000 --- a/src/module/sdk/GFSDKUI.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */
\ No newline at end of file diff --git a/src/pinentry/CMakeLists.txt b/src/pinentry/CMakeLists.txt deleted file mode 100644 index cce5fcfb..00000000 --- a/src/pinentry/CMakeLists.txt +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright (C) 2021 Saturneric <[email protected]> -# -# This file is part of GpgFrontend. -# -# GpgFrontend 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. -# -# GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. -# -# The initial version of the source code is inherited from -# the gpg4usb project, which is under GPL-3.0-or-later. -# -# All the source code of GpgFrontend was modified and released by -# Saturneric <[email protected]> starting on May 12, 2021. -# -# SPDX-License-Identifier: GPL-3.0-or-later - -aux_source_directory(. PINENTRY_SOURCE) - -# capslock -list(APPEND PINENTRY_SOURCE "capslock/capslock.cpp") -if (MINGW) - list(APPEND PINENTRY_SOURCE "capslock/capslock_win.cpp") -else() - list(APPEND PINENTRY_SOURCE "capslock/capslock_unix.cpp") -endif() - -add_library(gpgfrontend_pinentry SHARED ${PINENTRY_SOURCE}) - -target_link_libraries(gpgfrontend_pinentry PUBLIC gpgfrontend_core) - -if(GPGFRONTEND_QT5_BUILD) - # link Qt core - target_link_libraries(gpgfrontend_pinentry PUBLIC Qt5::Widgets) -else() - # link Qt core - target_link_libraries(gpgfrontend_pinentry PUBLIC Qt6::Widgets) -endif() - -if (XCODE_BUILD) - set_target_properties(gpgfrontend_pinentry - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") -endif () - -# spdlog -target_link_libraries(gpgfrontend_pinentry PRIVATE spdlog) - -# using std c++ 17 -target_compile_features(gpgfrontend_pinentry PUBLIC cxx_std_17) diff --git a/src/pinentry/accessibility.cpp b/src/pinentry/accessibility.cpp deleted file mode 100644 index f139832a..00000000 --- a/src/pinentry/accessibility.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* accessibility.cpp - Helpers for making pinentry accessible - * Copyright (C) 2021 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include "accessibility.h" - -#include <QString> -#include <QWidget> - -namespace Accessibility { - -void setDescription(QWidget *w, const QString &text) { - if (w) { -#ifndef QT_NO_ACCESSIBILITY - w->setAccessibleDescription(text); -#endif - } -} - -void setName(QWidget *w, const QString &text) { - if (w) { -#ifndef QT_NO_ACCESSIBILITY - w->setAccessibleName(text); -#endif - } -} - -} // namespace Accessibility diff --git a/src/pinentry/accessibility.h b/src/pinentry/accessibility.h deleted file mode 100644 index 9ef912d6..00000000 --- a/src/pinentry/accessibility.h +++ /dev/null @@ -1,40 +0,0 @@ -/* accessibility.h - Helpers for making pinentry accessible - * Copyright (C) 2021 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __PINENTRY_QT_ACCESSIBILITY_H__ -#define __PINENTRY_QT_ACCESSIBILITY_H__ - -class QString; -class QWidget; - -namespace Accessibility -{ - -/* Wrapper for QWidget::setAccessibleDescription which does nothing if - QT_NO_ACCESSIBILITY is defined. */ -void setDescription(QWidget *w, const QString &text); - -/* Wrapper for QWidget::setAccessibleName which does nothing if - QT_NO_ACCESSIBILITY is defined. */ -void setName(QWidget *w, const QString &text); - -} // namespace Accessibility - -#endif // __PINENTRY_QT_ACCESSIBILITY_H__ diff --git a/src/pinentry/capslock/capslock.cpp b/src/pinentry/capslock/capslock.cpp deleted file mode 100644 index a730c220..00000000 --- a/src/pinentry/capslock/capslock.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* capslock.cpp - Helper to check whether Caps Lock is on - * Copyright (C) 2021 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <QDebug> -#include <QGuiApplication> - -#include "capslock.h" - -CapsLockWatcher::Private::Private(CapsLockWatcher *q) : q{q} { -#ifdef PINENTRY_QT_WAYLAND - if (qApp->platformName() == QLatin1String("wayland")) { - watchWayland(); - } -#endif -} - -CapsLockWatcher::CapsLockWatcher(QObject *parent) - : QObject{parent}, d{new Private{this}} { - if (qApp->platformName() == QLatin1String("wayland")) { -#ifndef PINENTRY_QT_WAYLAND - qWarning() << "CapsLockWatcher was compiled without support for Wayland"; -#endif - } -} diff --git a/src/pinentry/capslock/capslock.h b/src/pinentry/capslock/capslock.h deleted file mode 100644 index 138f88cc..00000000 --- a/src/pinentry/capslock/capslock.h +++ /dev/null @@ -1,77 +0,0 @@ -/* capslock.h - Helper to check whether Caps Lock is on - * Copyright (C) 2021 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __PINENTRY_QT_CAPSLOCK_H__ -#define __PINENTRY_QT_CAPSLOCK_H__ - -#include <QObject> -#include <memory> - -enum class LockState { Unknown = -1, Off, On }; - -LockState capsLockState(); - -#ifdef PINENTRY_QT_WAYLAND -namespace KWayland { -namespace Client { -class Registry; -class Seat; -} // namespace Client -} // namespace KWayland -#endif - -class CapsLockWatcher : public QObject { - Q_OBJECT - - public: - explicit CapsLockWatcher(QObject *parent = nullptr); - - Q_SIGNALS: - void stateChanged(bool locked); - - private: - class Private; - std::unique_ptr<Private> d; -}; - -class CapsLockWatcher::Private { - public: - explicit Private(CapsLockWatcher *); -#ifdef PINENTRY_QT_WAYLAND - void watchWayland(); -#endif - - private: -#ifdef PINENTRY_QT_WAYLAND - void registry_seatAnnounced(quint32, quint32); - void seat_hasKeyboardChanged(bool); - void keyboard_modifiersChanged(quint32); -#endif - - private: - CapsLockWatcher *const q; - -#ifdef PINENTRY_QT_WAYLAND - KWayland::Client::Registry *registry = nullptr; - KWayland::Client::Seat *seat = nullptr; -#endif -}; - -#endif // __PINENTRY_QT_CAPSLOCK_H__ diff --git a/src/pinentry/capslock/capslock_unix.cpp b/src/pinentry/capslock/capslock_unix.cpp deleted file mode 100644 index e4f4cd17..00000000 --- a/src/pinentry/capslock/capslock_unix.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* capslock_unix.cpp - Helper to check whether Caps Lock is on - * Copyright (C) 2021 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "capslock.h" - -#ifdef PINENTRY_QT_WAYLAND -#include <KWayland/Client/connection_thread.h> -#include <KWayland/Client/keyboard.h> -#include <KWayland/Client/registry.h> -#include <KWayland/Client/seat.h> -#endif - -#include <QGuiApplication> - -#ifdef PINENTRY_QT_X11 -#include <X11/XKBlib.h> - -#include <QX11Info> -#undef Status -#endif - -#include <QDebug> - -#ifdef PINENTRY_QT_WAYLAND -using namespace KWayland::Client; -#endif - -#ifdef PINENTRY_QT_WAYLAND -static bool watchingWayland = false; -#endif - -LockState capsLockState() { - static bool reportUnsupportedPlatform = true; -#ifdef PINENTRY_QT_X11 - if (qApp->platformName() == QLatin1String("xcb")) { - unsigned int state; - XkbGetIndicatorState(QX11Info::display(), XkbUseCoreKbd, &state); - return (state & 0x01) == 1 ? LockState::On : LockState::Off; - } -#endif -#ifdef PINENTRY_QT_WAYLAND - if (qApp->platformName() == QLatin1String("wayland")) { - if (!watchingWayland && reportUnsupportedPlatform) { - qDebug() << "Use CapsLockWatcher for checking for Caps Lock on Wayland"; - } - } else -#endif - if (reportUnsupportedPlatform) { - qWarning() << "Checking for Caps Lock not possible on unsupported platform:" - << qApp->platformName(); - } - reportUnsupportedPlatform = false; - return LockState::Unknown; -} - -#ifdef PINENTRY_QT_WAYLAND -void CapsLockWatcher::Private::watchWayland() { - watchingWayland = true; - auto connection = ConnectionThread::fromApplication(q); - if (!connection) { - qWarning() << "Failed to get connection to Wayland server from QPA"; - return; - } - registry = new Registry{q}; - registry->create(connection); - if (!registry->isValid()) { - qWarning() << "Failed to create valid KWayland registry"; - return; - } - registry->setup(); - - connect(registry, &Registry::seatAnnounced, q, - [this](quint32 name, quint32 version) { - registry_seatAnnounced(name, version); - }); -} - -void CapsLockWatcher::Private::registry_seatAnnounced(quint32 name, - quint32 version) { - Q_ASSERT(registry); - seat = registry->createSeat(name, version, q); - if (!seat->isValid()) { - qWarning() << "Failed to create valid KWayland seat"; - return; - } - - connect(seat, &Seat::hasKeyboardChanged, q, - [this](bool hasKeyboard) { seat_hasKeyboardChanged(hasKeyboard); }); -} - -void CapsLockWatcher::Private::seat_hasKeyboardChanged(bool hasKeyboard) { - Q_ASSERT(seat); - - if (!hasKeyboard) { - qDebug() << "Seat has no keyboard"; - return; - } - - auto keyboard = seat->createKeyboard(q); - if (!keyboard->isValid()) { - qWarning() << "Failed to create valid KWayland keyboard"; - return; - } - - connect(keyboard, &Keyboard::modifiersChanged, q, - [this](quint32, quint32, quint32 locked, quint32) { - keyboard_modifiersChanged(locked); - }); -} - -void CapsLockWatcher::Private::keyboard_modifiersChanged(quint32 locked) { - const bool capsLockIsLocked = (locked & 2u) != 0; - qDebug() << "Caps Lock is locked:" << capsLockIsLocked; - Q_EMIT q->stateChanged(capsLockIsLocked); -} -#endif diff --git a/src/pinentry/capslock/capslock_win.cpp b/src/pinentry/capslock/capslock_win.cpp deleted file mode 100644 index 46bc7043..00000000 --- a/src/pinentry/capslock/capslock_win.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* capslock_win.cpp - Helper to check whether Caps Lock is on - * Copyright (C) 2021 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ -#include <windows.h> - -#include "capslock.h" - -LockState capsLockState() { - return (GetKeyState(VK_CAPITAL) & 1) ? LockState::On : LockState::Off; -} diff --git a/src/pinentry/pinentry.cpp b/src/pinentry/pinentry.cpp deleted file mode 100644 index 5f233f5d..00000000 --- a/src/pinentry/pinentry.cpp +++ /dev/null @@ -1,570 +0,0 @@ -/* pinentry.c - The PIN entry support library - * Copyright (C) 2002, 2003, 2007, 2008, 2010, 2015, 2016, 2021 g10 Code GmbH - * - * This file is part of PINENTRY. - * - * PINENTRY 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 2 of the License, or - * (at your option) any later version. - * - * PINENTRY 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifndef WINDOWS -#include <errno.h> -#endif -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> -#ifndef WINDOWS -#include <sys/utsname.h> -#endif -#ifndef WINDOWS -#include <locale.h> -#endif -#include <limits.h> -#ifdef WINDOWS -#include <windows.h> -#endif - -#include <assuan.h> - -#include "core/utils/MemoryUtils.h" -#include "pinentry.h" - -#ifdef WINDOWS -#define getpid() GetCurrentProcessId() -#endif - -/* Keep the name of our program here. */ -static char this_pgmname[50]; - -struct pinentry pinentry; - -static const char *flavor_flag; - -/* Because gtk_init removes the --display arg from the command lines - * and our command line parser is called after gtk_init (so that it - * does not see gtk specific options) we don't have a way to get hold - * of the --display option. Our solution is to remember --display in - * the call to pinentry_have_display and set it then in our - * parser. */ -static char *remember_display; - -static void pinentry_reset(int use_defaults) { - /* GPG Agent sets these options once when it starts the pinentry. - Don't reset them. */ - int grab = pinentry.grab; - char *ttyname = pinentry.ttyname; - char *ttytype = pinentry.ttytype_l; - char *ttyalert = pinentry.ttyalert; - char *lc_ctype = pinentry.lc_ctype; - char *lc_messages = pinentry.lc_messages; - int allow_external_password_cache = pinentry.allow_external_password_cache; - char *default_ok = pinentry.default_ok; - char *default_cancel = pinentry.default_cancel; - char *default_prompt = pinentry.default_prompt; - char *default_pwmngr = pinentry.default_pwmngr; - char *default_cf_visi = pinentry.default_cf_visi; - char *default_tt_visi = pinentry.default_tt_visi; - char *default_tt_hide = pinentry.default_tt_hide; - char *default_capshint = pinentry.default_capshint; - char *touch_file = pinentry.touch_file; - unsigned long owner_pid = pinentry.owner_pid; - int owner_uid = pinentry.owner_uid; - char *owner_host = pinentry.owner_host; - int constraints_enforce = pinentry.constraints_enforce; - char *constraints_hint_short = pinentry.constraints_hint_short; - char *constraints_hint_long = pinentry.constraints_hint_long; - char *constraints_error_title = pinentry.constraints_error_title; - - /* These options are set from the command line. Don't reset - them. */ - int debug = pinentry.debug; - char *display = pinentry.display; - int parent_wid = pinentry.parent_wid; - - pinentry_color_t color_fg = pinentry.color_fg; - int color_fg_bright = pinentry.color_fg_bright; - pinentry_color_t color_bg = pinentry.color_bg; - pinentry_color_t color_so = pinentry.color_so; - int color_so_bright = pinentry.color_so_bright; - pinentry_color_t color_ok = pinentry.color_ok; - int color_ok_bright = pinentry.color_ok_bright; - pinentry_color_t color_qualitybar = pinentry.color_qualitybar; - int color_qualitybar_bright = pinentry.color_qualitybar_bright; - - int timeout = pinentry.timeout; - - char *invisible_char = pinentry.invisible_char; - - /* Free any allocated memory. */ - if (use_defaults) { - free(pinentry.ttyname); - free(pinentry.ttytype_l); - free(pinentry.ttyalert); - free(pinentry.lc_ctype); - free(pinentry.lc_messages); - free(pinentry.default_ok); - free(pinentry.default_cancel); - free(pinentry.default_prompt); - free(pinentry.default_pwmngr); - free(pinentry.default_cf_visi); - free(pinentry.default_tt_visi); - free(pinentry.default_tt_hide); - free(pinentry.default_capshint); - free(pinentry.touch_file); - free(pinentry.owner_host); - free(pinentry.display); - free(pinentry.constraints_hint_short); - free(pinentry.constraints_hint_long); - free(pinentry.constraints_error_title); - } - - free(pinentry.title); - free(pinentry.description); - free(pinentry.error); - free(pinentry.prompt); - free(pinentry.ok); - free(pinentry.notok); - free(pinentry.cancel); - GpgFrontend::SecureFree(pinentry.pin); - free(pinentry.repeat_passphrase); - free(pinentry.repeat_error_string); - free(pinentry.quality_bar); - free(pinentry.quality_bar_tt); - free(pinentry.formatted_passphrase_hint); - free(pinentry.keyinfo); - free(pinentry.specific_err_info); - - /* Reset the pinentry structure. */ - memset(&pinentry, 0, sizeof(pinentry)); - - /* Restore options without a default we want to preserve. */ - pinentry.invisible_char = invisible_char; - - /* Restore other options or set defaults. */ - - if (use_defaults) { - /* Pinentry timeout in seconds. */ - pinentry.timeout = 60; - - /* Global grab. */ - pinentry.grab = 1; - - pinentry.color_fg = PINENTRY_COLOR_DEFAULT; - pinentry.color_fg_bright = 0; - pinentry.color_bg = PINENTRY_COLOR_DEFAULT; - pinentry.color_so = PINENTRY_COLOR_DEFAULT; - pinentry.color_so_bright = 0; - pinentry.color_ok = PINENTRY_COLOR_DEFAULT; - pinentry.color_ok_bright = 0; - pinentry.color_qualitybar = PINENTRY_COLOR_DEFAULT; - pinentry.color_qualitybar_bright = 0; - - pinentry.owner_uid = -1; - } else /* Restore the options. */ - { - pinentry.grab = grab; - pinentry.ttyname = ttyname; - pinentry.ttytype_l = ttytype; - pinentry.ttyalert = ttyalert; - pinentry.lc_ctype = lc_ctype; - pinentry.lc_messages = lc_messages; - pinentry.allow_external_password_cache = allow_external_password_cache; - pinentry.default_ok = default_ok; - pinentry.default_cancel = default_cancel; - pinentry.default_prompt = default_prompt; - pinentry.default_pwmngr = default_pwmngr; - pinentry.default_cf_visi = default_cf_visi; - pinentry.default_tt_visi = default_tt_visi; - pinentry.default_tt_hide = default_tt_hide; - pinentry.default_capshint = default_capshint; - pinentry.touch_file = touch_file; - pinentry.owner_pid = owner_pid; - pinentry.owner_uid = owner_uid; - pinentry.owner_host = owner_host; - pinentry.constraints_enforce = constraints_enforce; - pinentry.constraints_hint_short = constraints_hint_short; - pinentry.constraints_hint_long = constraints_hint_long; - pinentry.constraints_error_title = constraints_error_title; - - pinentry.debug = debug; - pinentry.display = display; - pinentry.parent_wid = parent_wid; - - pinentry.color_fg = color_fg; - pinentry.color_fg_bright = color_fg_bright; - pinentry.color_bg = color_bg; - pinentry.color_so = color_so; - pinentry.color_so_bright = color_so_bright; - pinentry.color_ok = color_ok; - pinentry.color_ok_bright = color_ok_bright; - pinentry.color_qualitybar = color_qualitybar; - pinentry.color_qualitybar_bright = color_qualitybar_bright; - - pinentry.timeout = timeout; - } -} - -static gpg_error_t pinentry_assuan_reset_handler(assuan_context_t ctx, - char *line) { - (void)ctx; - (void)line; - - pinentry_reset(0); - - return 0; -} - -/* Return a malloced copy of the commandline for PID. If this is not - * possible NULL is returned. */ -#ifndef WINDOWS -static char *get_cmdline(unsigned long pid) { - char buffer[200]; - FILE *fp; - size_t i, n; - - snprintf(buffer, sizeof buffer, "/proc/%lu/cmdline", pid); - - fp = fopen(buffer, "rb"); - if (!fp) return NULL; - n = fread(buffer, 1, sizeof buffer - 1, fp); - if (n < sizeof buffer - 1 && ferror(fp)) { - /* Some error occurred. */ - fclose(fp); - return NULL; - } - fclose(fp); - if (n == 0) return NULL; - /* Arguments are delimited by Nuls. We should do proper quoting but - * that can be a bit complicated, thus we simply replace the Nuls by - * spaces. */ - for (i = 0; i < n; i++) - if (!buffer[i] && i < n - 1) buffer[i] = ' '; - buffer[i] = 0; /* Make sure the last byte is the string terminator. */ - - return strdup(buffer); -} -#endif /*!WINDOWS*/ - -/* Atomically ask the kernel for information about process PID. - * Return a malloc'ed copy of the process name as long as the process - * uid matches UID. If it cannot determine that the process has uid - * UID, it returns NULL. - * - * This is not as informative as get_cmdline, but it verifies that the - * process does belong to the user in question. - */ -#ifndef WINDOWS -static char *get_pid_name_for_uid(unsigned long pid, int uid) { - char buffer[400]; - FILE *fp; - size_t end, n; - char *uidstr; - - snprintf(buffer, sizeof buffer, "/proc/%lu/status", pid); - - fp = fopen(buffer, "rb"); - if (!fp) return NULL; - n = fread(buffer, 1, sizeof buffer - 1, fp); - if (n < sizeof buffer - 1 && ferror(fp)) { - /* Some error occurred. */ - fclose(fp); - return NULL; - } - fclose(fp); - if (n == 0) return NULL; - buffer[n] = 0; - /* Fixme: Is it specified that "Name" is always the first line? For - * robustness I would prefer to have a real parser here. -wk */ - if (strncmp(buffer, "Name:\t", 6)) return NULL; - end = strcspn(buffer + 6, "\n") + 6; - buffer[end] = 0; - - /* check that uid matches what we expect */ - uidstr = strstr(buffer + end + 1, "\nUid:\t"); - if (!uidstr) return NULL; - if (atoi(uidstr + 6) != uid) return NULL; - - return strdup(buffer + 6); -} -#endif /*!WINDOWS*/ - -const char *pinentry_get_pgmname(void) { return this_pgmname; } - -/* Return a malloced string with the title. The caller mus free the - * string. If no title is available or the title string has an error - * NULL is returned. */ -char *pinentry_get_title(pinentry_t pe) { - char *title; - - if (pe->title) title = strdup(pe->title); -#ifndef WINDOWS - else if (pe->owner_pid) { - char buf[200]; - struct utsname utsbuf; - char *pidname = NULL; - char *cmdline = NULL; - - if (pe->owner_host && !uname(&utsbuf) && - !strcmp(utsbuf.nodename, pe->owner_host)) { - pidname = get_pid_name_for_uid(pe->owner_pid, pe->owner_uid); - if (pidname) cmdline = get_cmdline(pe->owner_pid); - } - - if (pe->owner_host && (cmdline || pidname)) - snprintf(buf, sizeof buf, "[%lu]@%s (%s)", pe->owner_pid, pe->owner_host, - cmdline ? cmdline : pidname); - else if (pe->owner_host) - snprintf(buf, sizeof buf, "[%lu]@%s", pe->owner_pid, pe->owner_host); - else - snprintf(buf, sizeof buf, "[%lu] <unknown host>", pe->owner_pid); - free(pidname); - free(cmdline); - title = strdup(buf); - } -#endif /*!WINDOWS*/ - else - title = strdup(this_pgmname); - - return title; -} - -/* Run a quality inquiry for PASSPHRASE of LENGTH. (We need LENGTH - because not all backends might be able to return a proper - C-string.). Returns: A value between -100 and 100 to give an - estimate of the passphrase's quality. Negative values are use if - the caller won't even accept that passphrase. Note that we expect - just one data line which should not be escaped in any represent a - numeric signed decimal value. Extra data is currently ignored but - should not be send at all. */ -int pinentry_inq_quality(const QString &passphrase) { - int score = 0; - - score += std::min(40, static_cast<int>(passphrase.length()) * 2); - - bool has_upper = false; - bool has_lower = false; - bool has_digit = false; - bool has_special = false; - for (const auto ch : passphrase) { - if (ch.isUpper()) has_upper = true; - if (ch.isLower()) has_lower = true; - if (ch.isDigit()) has_digit = true; - if (!ch.isLetterOrNumber()) has_special = true; - } - - int const variety_count = - static_cast<int>(has_upper) + static_cast<int>(has_lower) + - static_cast<int>(has_digit) + static_cast<int>(has_special); - score += variety_count * 10; - - for (auto i = 0; i < passphrase.length() - 1; ++i) { - if (passphrase[i] == passphrase[i + 1]) { - score -= 5; - } - } - - QHash<QChar, int> char_count; - for (const auto ch : passphrase) { - char_count[ch]++; - } - for (auto &p : char_count) { - if (p > 1) { - score -= (p - 1) * 3; - } - } - - QString const lower_password = passphrase.toLower(); - if (lower_password.contains("password") || - lower_password.contains("123456")) { - score -= 30; - } - - return std::max(-100, std::min(100, score)); -} - -/* Run a genpin inquiry */ -char *pinentry_inq_genpin(pinentry_t pin) { - assuan_context_t ctx = (assuan_context_t)pin->ctx_assuan; - const char prefix[] = "INQUIRE GENPIN"; - char *line; - size_t linelen; - int gotvalue = 0; - char *value = NULL; - int rc; - - if (!ctx) return 0; /* Can't run the callback. */ - - rc = assuan_write_line(ctx, prefix); - if (rc) { - fprintf(stderr, "ASSUAN WRITE LINE failed: rc=%d\n", rc); - return 0; - } - - for (;;) { - do { - rc = assuan_read_line(ctx, &line, &linelen); - if (rc) { - fprintf(stderr, "ASSUAN READ LINE failed: rc=%d\n", rc); - free(value); - return 0; - } - } while (*line == '#' || !linelen); - if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D' && - (!line[3] || line[3] == ' ')) - break; /* END command received*/ - if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N' && - (!line[3] || line[3] == ' ')) - break; /* CAN command received*/ - if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' && - (!line[3] || line[3] == ' ')) - break; /* ERR command received*/ - if (line[0] != 'D' || line[1] != ' ' || linelen < 3 || gotvalue) continue; - gotvalue = 1; - value = strdup(line + 2); - } - - return value; -} - -/* Try to make room for at least LEN bytes in the pinentry. Returns - new buffer on success and 0 on failure or when the old buffer is - sufficient. */ -char *pinentry_setbufferlen(pinentry_t pin, int len) { - char *newp; - - if (pin->pin_len) - assert(pin->pin); - else - assert(!pin->pin); - - if (len < 2048) len = 2048; - - if (len <= pin->pin_len) return pin->pin; - - newp = GpgFrontend::SecureReallocAsType<char>(pin->pin, len); - if (newp) { - pin->pin = newp; - pin->pin_len = len; - } else { - GpgFrontend::SecureFree(pin->pin); - pin->pin = 0; - pin->pin_len = 0; - } - return newp; -} - -static void pinentry_setbuffer_clear(pinentry_t pin) { - if (!pin->pin) { - assert(pin->pin_len == 0); - return; - } - - assert(pin->pin_len > 0); - - GpgFrontend::SecureFree(pin->pin); - pin->pin = NULL; - pin->pin_len = 0; -} - -static struct assuan_malloc_hooks assuan_malloc_hooks = { - GpgFrontend::SecureMalloc, GpgFrontend::SecureRealloc, - GpgFrontend::SecureFree}; - -/* Simple test to check whether DISPLAY is set or the option --display - was given. Used to decide whether the GUI or curses should be - initialized. */ -int pinentry_have_display(int argc, char **argv) { - int found = 0; - - for (; argc; argc--, argv++) { - if (!strcmp(*argv, "--display")) { - if (argv[1] && !remember_display) { - remember_display = strdup(argv[1]); - if (!remember_display) { -#ifndef WINDOWS - fprintf(stderr, "%s: %s\n", this_pgmname, strerror(errno)); -#endif - exit(EXIT_FAILURE); - } - } - found = 1; - break; - } else if (!strncmp(*argv, "--display=", 10)) { - if (!remember_display) { - remember_display = strdup(*argv + 10); - if (!remember_display) { -#ifndef WINDOWS - fprintf(stderr, "%s: %s\n", this_pgmname, strerror(errno)); -#endif - exit(EXIT_FAILURE); - } - } - found = 1; - break; - } - } - -#ifndef WINDOWS - { - const char *s; - s = getenv("DISPLAY"); - if (s && *s) found = 1; - } -#endif - - return found; -} - -/* Set the optional flag used with getinfo. */ -void pinentry_set_flavor_flag(const char *string) { flavor_flag = string; } - -/* Note, that it is sufficient to allocate the target string D as - long as the source string S, i.e.: strlen(s)+1; */ -static void strcpy_escaped(char *d, const char *s) { - while (*s) { - if (*s == '%' && s[1] && s[2]) { - s++; - *d++ = xtoi_2(s); - s += 2; - } else - *d++ = *s++; - } - *d = 0; -} - -/* Return a staically allocated string with information on the mode, - * uid, and gid of DEVICE. On error "?" is returned if DEVICE is - * NULL, "-" is returned. */ -static const char *device_stat_string(const char *device) { -#ifdef HAVE_STAT - static char buf[40]; - struct stat st; - - if (!device || !*device) return "-"; - - if (stat(device, &st)) return "?"; /* Error */ - snprintf(buf, sizeof buf, "%lo/%lu/%lu", (unsigned long)st.st_mode, - (unsigned long)st.st_uid, (unsigned long)st.st_gid); - return buf; -#else - return "-"; -#endif -}
\ No newline at end of file diff --git a/src/pinentry/pinentry.h b/src/pinentry/pinentry.h deleted file mode 100644 index 143a8855..00000000 --- a/src/pinentry/pinentry.h +++ /dev/null @@ -1,339 +0,0 @@ -/* pinentry.h - The interface for the PIN entry support library. - * Copyright (C) 2002, 2003, 2010, 2015, 2021 g10 Code GmbH - * - * This file is part of PINENTRY. - * - * PINENTRY 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 2 of the License, or - * (at your option) any later version. - * - * PINENTRY 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef PINENTRY_H -#define PINENTRY_H - -#include <cstdint> - -#ifdef __cplusplus -extern "C" { -#if 0 -} -#endif -#endif - -typedef enum { - PINENTRY_COLOR_NONE, - PINENTRY_COLOR_DEFAULT, - PINENTRY_COLOR_BLACK, - PINENTRY_COLOR_RED, - PINENTRY_COLOR_GREEN, - PINENTRY_COLOR_YELLOW, - PINENTRY_COLOR_BLUE, - PINENTRY_COLOR_MAGENTA, - PINENTRY_COLOR_CYAN, - PINENTRY_COLOR_WHITE -} pinentry_color_t; - -struct pinentry { - /* The window title, or NULL. (Assuan: "SETTITLE TITLE".) */ - char *title; - /* The description to display, or NULL. (Assuan: "SETDESC - DESC".) */ - char *description; - /* The error message to display, or NULL. (Assuan: "SETERROR - MESSAGE".) */ - char *error; - /* The prompt to display, or NULL. (Assuan: "SETPROMPT - prompt".) */ - char *prompt; - /* The OK button text to display, or NULL. (Assuan: "SETOK - OK".) */ - char *ok; - /* The Not-OK button text to display, or NULL. This is the text for - the alternative option shown by the third button. (Assuan: - "SETNOTOK NOTOK".) */ - char *notok; - /* The Cancel button text to display, or NULL. (Assuan: "SETCANCEL - CANCEL".) */ - char *cancel; - - /* The buffer to store the secret into. */ - char *pin; - /* The length of the buffer. */ - int pin_len; - /* Whether the pin was read from an external cache (1) or entered by - the user (0). */ - int pin_from_cache; - - /* The name of the X display to use if X is available and supported. - (Assuan: "OPTION display DISPLAY".) */ - char *display; - /* The name of the terminal node to open if X not available or - supported. (Assuan: "OPTION ttyname TTYNAME".) */ - char *ttyname; - /* The type of the terminal. (Assuan: "OPTION ttytype TTYTYPE".) */ - char *ttytype_l; - /* Set the alert mode (none, beep or flash). */ - char *ttyalert; - /* The LC_CTYPE value for the terminal. (Assuan: "OPTION lc-ctype - LC_CTYPE".) */ - char *lc_ctype; - /* The LC_MESSAGES value for the terminal. (Assuan: "OPTION - lc-messages LC_MESSAGES".) */ - char *lc_messages; - - /* True if debug mode is requested. */ - int debug; - - /* The number of seconds before giving up while waiting for user input. */ - int timeout; - - /* True if caller should grab the keyboard. (Assuan: "OPTION grab" - or "OPTION no-grab".) */ - int grab; - - /* The PID of the owner or 0 if not known. The owner is the process - * which actually triggered the the pinentry. For example gpg. */ - unsigned long owner_pid; - - /* The numeric uid (user ID) of the owner process or -1 if not - * known. */ - int owner_uid; - - /* The malloced hostname of the owner or NULL. */ - char *owner_host; - - /* The window ID of the parent window over which the pinentry window - should be displayed. (Assuan: "OPTION parent-wid WID".) */ - int parent_wid; - - /* The name of an optional file which will be touched after a curses - entry has been displayed. (Assuan: "OPTION touch-file - FILENAME".) */ - char *touch_file; - - /* The frontend should set this to -1 if the user canceled the - request, and to the length of the PIN stored in pin - otherwise. */ - int result; - - /* The frontend should set this if the NOTOK button was pressed. */ - int canceled; - - /* The frontend should set this to true if an error with the local - conversion occurred. */ - int locale_err; - - /* The frontend should set this to a gpg-error so that commands are - able to return specific error codes. This is an ugly hack due to - the fact that pinentry_cmd_handler_t returns the length of the - passphrase or a negative error code. */ - int specific_err; - - /* The frontend may store a string with the error location here. */ - const char *specific_err_loc; - - /* The frontend may store a malloced string here to emit an ERROR - * status code with this extra info along with SPECIFIC_ERR. */ - char *specific_err_info; - - /* The frontend should set this to true if the window close button - has been used. This flag is used in addition to a regular return - value. */ - int close_button; - - /* The caller should set this to true if only one button is - required. This is useful for notification dialogs where only a - dismiss button is required. */ - int one_button; - - /* Whether this is a CONFIRM pinentry. */ - int confirm; - - /* If true a second prompt for the passphrase is shown and the user - is expected to enter the same passphrase again. Pinentry checks - that both match. (Assuan: "SETREPEAT".) */ - char *repeat_passphrase; - - /* The string to show if a repeated passphrase does not match. - (Assuan: "SETREPEATERROR ERROR".) */ - char *repeat_error_string; - - /* The string to show if a repeated passphrase does match. - (Assuan: "SETREPEATOK STRING".) */ - char *repeat_ok_string; - - /* Set to true if the passphrase has been entered a second time and - matches the first passphrase. */ - int repeat_okay; - - /* If this is not NULL, a passphrase quality indicator is shown. - There will also be an inquiry back to the caller to get an - indication of the quality for the passphrase entered so far. The - string is used as a label for the quality bar. (Assuan: - "SETQUALITYBAR LABEL".) */ - char *quality_bar; - - /* The tooltip to be shown for the qualitybar. Malloced or NULL. - (Assuan: "SETQUALITYBAR_TT TOOLTIP".) */ - char *quality_bar_tt; - - /* If this is not NULL, a generate action should be shown. - There will be an inquiry back to the caller to get such a - PIN. generate action. Malloced or NULL. - (Assuan: "SETGENPIN LABEL" .) */ - char *genpin_label; - - /* The tooltip to be shown for the generate action. Malloced or NULL. - (Assuan: "SETGENPIN_TT TOOLTIP".) */ - char *genpin_tt; - - /* Specifies whether passphrase formatting should be enabled. - (Assuan: "OPTION formatted-passphrase") */ - int formatted_passphrase; - - /* A hint to be shown near the passphrase input field if passphrase - formatting is enabled. Malloced or NULL. - (Assuan: "OPTION formatted-passphrase-hint=HINT".) */ - char *formatted_passphrase_hint; - - /* For the curses pinentry, the color of error messages. */ - pinentry_color_t color_fg; - int color_fg_bright; - pinentry_color_t color_bg; - pinentry_color_t color_so; - int color_so_bright; - pinentry_color_t color_ok; - int color_ok_bright; - pinentry_color_t color_qualitybar; - int color_qualitybar_bright; - - /* Malloced and i18ned default strings or NULL. These strings may - include an underscore character to indicate an accelerator key. - A double underscore represents a plain one. */ - /* (Assuan: "OPTION default-ok OK"). */ - char *default_ok; - /* (Assuan: "OPTION default-cancel CANCEL"). */ - char *default_cancel; - /* (Assuan: "OPTION default-prompt PROMPT"). */ - char *default_prompt; - /* (Assuan: "OPTION default-pwmngr - SAVE_PASSWORD_WITH_PASSWORD_MANAGER?"). */ - char *default_pwmngr; - /* (Assuan: "OPTION default-cf-visi - Do you really want to make your passphrase visible?"). */ - char *default_cf_visi; - /* (Assuan: "OPTION default-tt-visi - Make passphrase visible?"). */ - char *default_tt_visi; - /* (Assuan: "OPTION default-tt-hide - Hide passphrase"). */ - char *default_tt_hide; - /* (Assuan: "OPTION default-capshint - Caps Lock is on"). */ - char *default_capshint; - - /* Whether we are allowed to read the password from an external - cache. (Assuan: "OPTION allow-external-password-cache") */ - int allow_external_password_cache; - - /* We only try the cache once. */ - int tried_password_cache; - - /* A stable identifier for the key. (Assuan: "SETKEYINFO - KEYINFO".) */ - char *keyinfo; - - /* Whether we may cache the password (according to the user). */ - int may_cache_password; - - /* NOTE: If you add any additional fields to this structure, be sure - to update the initializer in pinentry/pinentry.c!!! */ - - /* For the quality indicator and genpin we need to do an inquiry. - Thus we need to save the assuan ctx. */ - void *ctx_assuan; - - /* An UTF-8 string with an invisible character used to override the - default in some pinentries. Only the first character is - used. */ - char *invisible_char; - - /* Whether the passphrase constraints are enforced by gpg-agent. - (Assuan: "OPTION constraints-enforce") */ - int constraints_enforce; - - /* A short translated hint for the user with the constraints for new - passphrases to be displayed near the passphrase input field. - Malloced or NULL. - (Assuan: "OPTION constraints-hint-short=At least 8 characters".) */ - char *constraints_hint_short; - - /* A longer translated hint for the user with the constraints for new - passphrases to be displayed for example as tooltip. Malloced or NULL. - (Assuan: "OPTION constraints-hint-long=The passphrase must ...".) */ - char *constraints_hint_long; - - /* A short translated title for an error dialog informing the user about - unsatisfied passphrase constraints. Malloced or NULL. - (Assuan: "OPTION constraints-error-title=Passphrase Not Allowed".) */ - char *constraints_error_title; -}; -typedef struct pinentry *pinentry_t; - -/* The pinentry command handler type processes the pinentry request - PIN. If PIN->pin is zero, request a confirmation, otherwise a PIN - entry. On confirmation, the function should return TRUE if - confirmed, and FALSE otherwise. On PIN entry, the function should - return -1 if an error occurred or the user cancelled the operation - and 1 otherwise. */ -typedef int (*pinentry_cmd_handler_t)(pinentry_t pin); - -const char *pinentry_get_pgmname(void); - -char *pinentry_get_title(pinentry_t pe); - -/* Run a quality inquiry for PASSPHRASE of LENGTH. */ -int pinentry_inq_quality(const QString &passphrase); - -/* Run a genpin iquriry. Returns a malloced string or NULL */ -char *pinentry_inq_genpin(pinentry_t pin); - -/* Try to make room for at least LEN bytes for the pin in the pinentry - PIN. Returns new buffer on success and 0 on failure. */ -char *pinentry_setbufferlen(pinentry_t pin, int len); - -/* Return true if either DISPLAY is set or ARGV contains the string - "--display". */ -int pinentry_have_display(int argc, char **argv); - -/* Parse the command line options. May exit the program if only help - or version output is requested. */ -void pinentry_parse_opts(int argc, char *argv[]); - -/* Set the optional flag used with getinfo. */ -void pinentry_set_flavor_flag(const char *string); - -#ifdef WINDOWS -/* Windows declares sleep as obsolete, but provides a definition for - _sleep but non for the still existing sleep. */ -#define sleep(a) _sleep((a)) -#endif /*WINDOWS*/ - -#if 0 -{ -#endif -#ifdef __cplusplus -} -#endif - -#endif /* PINENTRY_H */ diff --git a/src/pinentry/pinentry_debug.cpp b/src/pinentry/pinentry_debug.cpp deleted file mode 100644 index 9afbcdb3..00000000 --- a/src/pinentry/pinentry_debug.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* pinentry_debug.h - Logging category for pinentry - * Copyright (C) 2021 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "pinentry_debug.h" - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) -Q_LOGGING_CATEGORY(PINENTRY_LOG, "gpg.pinentry", QtWarningMsg) -#else -Q_LOGGING_CATEGORY(PINENTRY_LOG, "gpg.pinentry") -#endif diff --git a/src/pinentry/pinentry_debug.h b/src/pinentry/pinentry_debug.h deleted file mode 100644 index fc8c808a..00000000 --- a/src/pinentry/pinentry_debug.h +++ /dev/null @@ -1,28 +0,0 @@ -/* pinentry_debug.h - Logging category for pinentry - * Copyright (C) 2021 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __PINENTRY_QT_DEBUG_H__ -#define __PINENTRY_QT_DEBUG_H__ - -#include <QLoggingCategory> - -Q_DECLARE_LOGGING_CATEGORY(PINENTRY_LOG) - -#endif // __PINENTRY_QT_DEBUG_H__ diff --git a/src/pinentry/pinentryconfirm.cpp b/src/pinentry/pinentryconfirm.cpp deleted file mode 100644 index 31d55b5c..00000000 --- a/src/pinentry/pinentryconfirm.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* pinentryconfirm.cpp - A QMessageBox with a timeout - * - * Copyright (C) 2011 Ben Kibbey <[email protected]> - * Copyright (C) 2022 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include "pinentryconfirm.h" - -#include <QAbstractButton> -#include <QApplication> -#include <QFontMetrics> -#include <QGridLayout> -#include <QLabel> -#include <QSpacerItem> - -#include "accessibility.h" -#include "pinentrydialog.h" - -namespace { -QLabel *messageBoxLabel(QMessageBox *messageBox) { - return messageBox->findChild<QLabel *>(QStringLiteral("qt_msgbox_label")); -} -} // namespace - -PinentryConfirm::PinentryConfirm(Icon icon, const QString &title, - const QString &text, StandardButtons buttons, - QWidget *parent, Qt::WindowFlags flags) - : QMessageBox{icon, title, text, buttons, parent, flags} { - _timer.callOnTimeout(this, &PinentryConfirm::slotTimeout); - -#ifndef QT_NO_ACCESSIBILITY - QAccessible::installActivationObserver(this); - accessibilityActiveChanged(QAccessible::isActive()); -#endif - -#if QT_VERSION >= 0x050000 - /* This is in line with PinentryDialog ctor to have a maximizing - * animation when opening. */ - if (qApp->platformName() != QLatin1String("wayland")) { - setWindowState(Qt::WindowMinimized); - QTimer::singleShot(0, this, [this]() { raiseWindow(this); }); - } -#else - activateWindow(); - raise(); -#endif -} - -PinentryConfirm::~PinentryConfirm() { -#ifndef QT_NO_ACCESSIBILITY - QAccessible::removeActivationObserver(this); -#endif -} - -void PinentryConfirm::setTimeout(std::chrono::seconds timeout) { - _timer.setInterval(timeout); -} - -std::chrono::seconds PinentryConfirm::timeout() const { - return std::chrono::duration_cast<std::chrono::seconds>( - _timer.intervalAsDuration()); -} - -bool PinentryConfirm::timedOut() const { return _timed_out; } - -void PinentryConfirm::showEvent(QShowEvent *event) { - static bool resized; - if (!resized) { - QGridLayout *lay = dynamic_cast<QGridLayout *>(layout()); - if (lay) { - QSize textSize = fontMetrics().size(Qt::TextExpandTabs, text(), - fontMetrics().maxWidth()); - QSpacerItem *horizontalSpacer = - new QSpacerItem(textSize.width() + iconPixmap().width(), 0, - QSizePolicy::Minimum, QSizePolicy::Expanding); - lay->addItem(horizontalSpacer, lay->rowCount(), 1, 1, - lay->columnCount() - 1); - } - resized = true; - } - - QMessageBox::showEvent(event); - - if (timeout() > std::chrono::milliseconds::zero()) { - _timer.setSingleShot(true); - _timer.start(); - } -} - -void PinentryConfirm::slotTimeout() { - QAbstractButton *b = button(QMessageBox::Cancel); - _timed_out = true; - - if (b) { - b->animateClick(); - } -} - -#ifndef QT_NO_ACCESSIBILITY -void PinentryConfirm::accessibilityActiveChanged(bool active) { - // Allow text label to get focus if accessibility is active - const auto focusPolicy = active ? Qt::StrongFocus : Qt::ClickFocus; - if (auto label = messageBoxLabel(this)) { - label->setFocusPolicy(focusPolicy); - } -} -#endif diff --git a/src/pinentry/pinentryconfirm.h b/src/pinentry/pinentryconfirm.h deleted file mode 100644 index 7be7c268..00000000 --- a/src/pinentry/pinentryconfirm.h +++ /dev/null @@ -1,63 +0,0 @@ -/* pinentryconfirm.h - A QMessageBox with a timeout - * - * Copyright (C) 2011 Ben Kibbey <[email protected]> - * Copyright (C) 2022 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef PINENTRYCONFIRM_H -#define PINENTRYCONFIRM_H - -#include <QAccessible> -#include <QMessageBox> -#include <QTimer> - -class PinentryConfirm : public QMessageBox -#ifndef QT_NO_ACCESSIBILITY - , public QAccessible::ActivationObserver -#endif -{ - Q_OBJECT -public: - PinentryConfirm(Icon icon, const QString &title, const QString &text, - StandardButtons buttons = NoButton, QWidget *parent = nullptr, - Qt::WindowFlags flags = Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint); - ~PinentryConfirm() override; - - void setTimeout(std::chrono::seconds timeout); - std::chrono::seconds timeout() const; - - bool timedOut() const; - -protected: - void showEvent(QShowEvent *event) override; - -private Q_SLOTS: - void slotTimeout(); - -private: -#ifndef QT_NO_ACCESSIBILITY - void accessibilityActiveChanged(bool active) override; -#endif - -private: - QTimer _timer; - bool _timed_out = false; -}; - -#endif diff --git a/src/pinentry/pinentrydialog.cpp b/src/pinentry/pinentrydialog.cpp deleted file mode 100644 index d63b0015..00000000 --- a/src/pinentry/pinentrydialog.cpp +++ /dev/null @@ -1,634 +0,0 @@ -/* pinentrydialog.cpp - A (not yet) secure Qt 4 dialog for PIN entry. - * Copyright (C) 2002, 2008 Klarälvdalens Datakonsult AB (KDAB) - * Copyright 2007 Ingo Klöcker - * Copyright 2016 Intevation GmbH - * Copyright (C) 2021, 2022 g10 Code GmbH - * - * Written by Steffen Hansen <[email protected]>. - * Modified by Andre Heinecke <[email protected]> - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include "pinentrydialog.h" - -#include <qnamespace.h> - -#include <QAccessible> -#include <QAction> -#include <QApplication> -#include <QCheckBox> -#include <QDebug> -#include <QDialogButtonBox> -#include <QFontMetrics> -#include <QGridLayout> -#include <QHBoxLayout> -#include <QKeyEvent> -#include <QLabel> -#include <QLineEdit> -#include <QMessageBox> -#include <QPainter> -#include <QPalette> -#include <QProgressBar> -#include <QPushButton> -#include <QRegularExpression> -#include <QStyle> -#include <QVBoxLayout> - -#include "accessibility.h" -#include "capslock/capslock.h" -#include "core/utils/MemoryUtils.h" -#include "pinentry.h" -#include "pinlineedit.h" - -void raiseWindow(QWidget *w) { - w->setWindowState((w->windowState() & ~Qt::WindowMinimized) | - Qt::WindowActive); - w->activateWindow(); - w->raise(); -} - -auto applicationIconPixmap(const QIcon &overlayIcon) -> QPixmap { - QPixmap pm = qApp->windowIcon().pixmap(48, 48); - - if (!overlayIcon.isNull()) { - QPainter painter(&pm); - const int emblem_size = 22; - painter.drawPixmap(pm.width() - emblem_size, 0, - overlayIcon.pixmap(emblem_size, emblem_size)); - } - - return pm; -} - -void PinEntryDialog::slotTimeout() { - _timed_out = true; - reject(); -} - -PinEntryDialog::PinEntryDialog(QWidget *parent, const char *name, int timeout, - bool modal, bool enable_quality_bar, - const QString &repeatString, - const QString &visibilityTT, - const QString &hideTT) - : QDialog{parent}, - _have_quality_bar{enable_quality_bar}, - mVisibilityTT{visibilityTT}, - mHideTT{hideTT} { - Q_UNUSED(name) - - if (modal) { - setWindowModality(Qt::ApplicationModal); - setModal(true); - } - - QPalette red_text_palette; - red_text_palette.setColor(QPalette::WindowText, Qt::red); - - auto *const main_layout = new QVBoxLayout{this}; - - auto *const hbox = new QHBoxLayout; - - _icon = new QLabel(this); - _icon->setPixmap(applicationIconPixmap()); - hbox->addWidget(_icon, 0, Qt::AlignVCenter | Qt::AlignLeft); - - auto *const grid = new QGridLayout; - int row = 1; - - _error = new QLabel{this}; - _error->setTextFormat(Qt::PlainText); - _error->setTextInteractionFlags(Qt::TextSelectableByMouse); - _error->setPalette(red_text_palette); - _error->hide(); - grid->addWidget(_error, row, 1, 1, 2); - - row++; - _desc = new QLabel{this}; - _desc->setTextFormat(Qt::PlainText); - _desc->setTextInteractionFlags(Qt::TextSelectableByMouse); - _desc->hide(); - grid->addWidget(_desc, row, 1, 1, 2); - - row++; - mCapsLockHint = new QLabel{this}; - mCapsLockHint->setTextFormat(Qt::PlainText); - mCapsLockHint->setTextInteractionFlags(Qt::TextSelectableByMouse); - mCapsLockHint->setPalette(red_text_palette); - mCapsLockHint->setAlignment(Qt::AlignCenter); - mCapsLockHint->setVisible(false); - grid->addWidget(mCapsLockHint, row, 1, 1, 2); - - row++; - { - _prompt = new QLabel(this); - _prompt->setTextFormat(Qt::PlainText); - _prompt->setTextInteractionFlags(Qt::TextSelectableByMouse); - _prompt->hide(); - grid->addWidget(_prompt, row, 1); - - auto *const l = new QHBoxLayout; - _edit = new PinLineEdit(this); - _edit->setMaxLength(256); - _edit->setMinimumWidth(_edit->fontMetrics().averageCharWidth() * 20 + 48); - _edit->setEchoMode(QLineEdit::Password); - _prompt->setBuddy(_edit); - l->addWidget(_edit, 1); - - if (!repeatString.isNull()) { - mGenerateButton = new QPushButton{this}; - mGenerateButton->setIcon(QIcon(QLatin1String(":password-generate.svg"))); - mGenerateButton->setVisible(false); - l->addWidget(mGenerateButton); - } - grid->addLayout(l, row, 2); - } - - /* Set up the show password action */ - const QIcon visibility_icon = QIcon(QLatin1String(":visibility.svg")); - const QIcon hide_icon = QIcon(QLatin1String(":hint.svg")); -#if QT_VERSION >= 0x050200 - if (!visibility_icon.isNull() && !hide_icon.isNull()) { - mVisiActionEdit = - _edit->addAction(visibility_icon, QLineEdit::TrailingPosition); - mVisiActionEdit->setVisible(false); - mVisiActionEdit->setToolTip(mVisibilityTT); - } else -#endif - { - if (!mVisibilityTT.isNull()) { - row++; - mVisiCB = new QCheckBox{mVisibilityTT, this}; - grid->addWidget(mVisiCB, row, 1, 1, 2, Qt::AlignLeft); - } - } - - row++; - mConstraintsHint = new QLabel{this}; - mConstraintsHint->setTextFormat(Qt::PlainText); - mConstraintsHint->setTextInteractionFlags(Qt::TextSelectableByMouse); - mConstraintsHint->setVisible(false); - grid->addWidget(mConstraintsHint, row, 2); - - row++; - mFormattedPassphraseHintSpacer = new QLabel{this}; - mFormattedPassphraseHintSpacer->setVisible(false); - mFormattedPassphraseHint = new QLabel{this}; - mFormattedPassphraseHint->setTextFormat(Qt::PlainText); - mFormattedPassphraseHint->setTextInteractionFlags(Qt::TextSelectableByMouse); - mFormattedPassphraseHint->setVisible(false); - grid->addWidget(mFormattedPassphraseHintSpacer, row, 1); - grid->addWidget(mFormattedPassphraseHint, row, 2); - - if (!repeatString.isNull()) { - row++; - auto *repeat_label = new QLabel{this}; - repeat_label->setTextFormat(Qt::PlainText); - repeat_label->setTextInteractionFlags(Qt::TextSelectableByMouse); - repeat_label->setText(repeatString); - grid->addWidget(repeat_label, row, 1); - - mRepeat = new PinLineEdit(this); - mRepeat->setMaxLength(256); - mRepeat->setEchoMode(QLineEdit::Password); - repeat_label->setBuddy(mRepeat); - grid->addWidget(mRepeat, row, 2); - - row++; - mRepeatError = new QLabel{this}; - mRepeatError->setTextFormat(Qt::PlainText); - mRepeatError->setTextInteractionFlags(Qt::TextSelectableByMouse); - mRepeatError->setPalette(red_text_palette); - mRepeatError->hide(); - grid->addWidget(mRepeatError, row, 2); - } - - if (enable_quality_bar) { - row++; - _quality_bar_label = new QLabel(this); - _quality_bar_label->setTextFormat(Qt::PlainText); - _quality_bar_label->setTextInteractionFlags(Qt::TextSelectableByMouse); - _quality_bar_label->setAlignment(Qt::AlignVCenter); - grid->addWidget(_quality_bar_label, row, 1); - - _quality_bar = new QProgressBar(this); - _quality_bar->setAlignment(Qt::AlignCenter); - _quality_bar_label->setBuddy(_quality_bar); - grid->addWidget(_quality_bar, row, 2); - } - - hbox->addLayout(grid, 1); - main_layout->addLayout(hbox); - - auto *const buttons = new QDialogButtonBox(this); - buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - _ok = buttons->button(QDialogButtonBox::Ok); - _cancel = buttons->button(QDialogButtonBox::Cancel); - - if (style()->styleHint(QStyle::SH_DialogButtonBox_ButtonsHaveIcons)) { - _ok->setIcon(style()->standardIcon(QStyle::SP_DialogOkButton)); - _cancel->setIcon(style()->standardIcon(QStyle::SP_DialogCancelButton)); - } - - main_layout->addStretch(1); - main_layout->addWidget(buttons); - main_layout->setSizeConstraint(QLayout::SetFixedSize); - - if (timeout > 0) { - _timer = new QTimer(this); - connect(_timer, &QTimer::timeout, this, &PinEntryDialog::slotTimeout); - _timer->start(timeout * 1000); - } - - connect(buttons, &QDialogButtonBox::accepted, this, - &PinEntryDialog::onAccept); - connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); - connect(_edit, &QLineEdit::textChanged, this, &PinEntryDialog::updateQuality); - connect(_edit, &QLineEdit::textChanged, this, &PinEntryDialog::textChanged); - connect(_edit, &PinLineEdit::backspacePressed, this, - &PinEntryDialog::onBackspace); - if (mGenerateButton != nullptr) { - connect(mGenerateButton, &QPushButton::clicked, this, - &PinEntryDialog::generatePin); - } - if (mVisiActionEdit != nullptr) { - connect(mVisiActionEdit, &QAction::triggered, this, - &PinEntryDialog::toggleVisibility); - } - if (mVisiCB != nullptr) { - connect(mVisiCB, &QCheckBox::toggled, this, - &PinEntryDialog::toggleVisibility); - } - if (mRepeat != nullptr) { - connect(mRepeat, &QLineEdit::textChanged, this, - &PinEntryDialog::textChanged); - } - - auto *caps_lock_watcher = new CapsLockWatcher{this}; - connect(caps_lock_watcher, &CapsLockWatcher::stateChanged, this, - [this](bool locked) { mCapsLockHint->setVisible(locked); }); - - connect(qApp, &QApplication::focusChanged, this, - &PinEntryDialog::focusChanged); - connect(qApp, &QApplication::applicationStateChanged, this, - &PinEntryDialog::checkCapsLock); - checkCapsLock(); - - setAttribute(Qt::WA_DeleteOnClose); - setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); - - /* This is mostly an issue on Windows where this results - in the pinentry popping up nicely with an animation and - comes to front. It is not ifdefed for Windows only since - window managers on Linux like KWin can also have this - result in an animation when the pinentry is shown and - not just popping it up. - */ - if (qApp->platformName() != QLatin1String("wayland")) { - setWindowState(Qt::WindowMinimized); - QTimer::singleShot(0, this, [this]() { raiseWindow(this); }); - } else { - raiseWindow(this); - } -} - -void PinEntryDialog::keyPressEvent(QKeyEvent *e) { - const auto return_pressed = - (!e->modifiers() && - (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return)) || - (e->modifiers() & Qt::KeypadModifier && e->key() == Qt::Key_Enter); - if (return_pressed && _edit->hasFocus() && (mRepeat != nullptr)) { - // if the user pressed Return in the first input field, then move the - // focus to the repeat input field and prevent further event processing - // by QDialog (which would trigger the default button) - mRepeat->setFocus(); - e->ignore(); - return; - } - - QDialog::keyPressEvent(e); -} - -void PinEntryDialog::keyReleaseEvent(QKeyEvent *event) { - QDialog::keyReleaseEvent(event); - checkCapsLock(); -} - -void PinEntryDialog::showEvent(QShowEvent *event) { - QDialog::showEvent(event); - _edit->setFocus(); -} - -void PinEntryDialog::setDescription(const QString &txt) { - _desc->setVisible(!txt.isEmpty()); - _desc->setText(txt); - _icon->setPixmap(applicationIconPixmap()); - setError(QString()); -} - -QString PinEntryDialog::description() const { return _desc->text(); } - -void PinEntryDialog::setError(const QString &txt) { - if (!txt.isNull()) { - _icon->setPixmap( - applicationIconPixmap(QIcon{QStringLiteral(":data-error.svg")})); - } - _error->setText(txt); - _error->setVisible(!txt.isEmpty()); -} - -QString PinEntryDialog::error() const { return _error->text(); } - -void PinEntryDialog::setPin(const QString &txt) { _edit->setPin(txt); } - -QString PinEntryDialog::pin() const { return _edit->pin(); } - -void PinEntryDialog::setPrompt(const QString &txt) { - _prompt->setText(txt); - _prompt->setVisible(!txt.isEmpty()); - if (txt.contains("PIN")) _disable_echo_allowed = false; -} - -QString PinEntryDialog::prompt() const { return _prompt->text(); } - -void PinEntryDialog::setOkText(const QString &txt) { - _ok->setText(txt); - _ok->setVisible(!txt.isEmpty()); -} - -void PinEntryDialog::setCancelText(const QString &txt) { - _cancel->setText(txt); - _cancel->setVisible(!txt.isEmpty()); -} - -void PinEntryDialog::setQualityBar(const QString &txt) { - if (_have_quality_bar) { - _quality_bar_label->setText(txt); - } -} - -void PinEntryDialog::setQualityBarTT(const QString &txt) { - if (_have_quality_bar) { - _quality_bar->setToolTip(txt); - } -} - -void PinEntryDialog::setGenpinLabel(const QString &txt) { - if (mGenerateButton == nullptr) { - return; - } - mGenerateButton->setVisible(!txt.isEmpty()); - if (!txt.isEmpty()) { - Accessibility::setName(mGenerateButton, txt); - } -} - -void PinEntryDialog::setGenpinTT(const QString &txt) { - if (mGenerateButton != nullptr) { - mGenerateButton->setToolTip(txt); - } -} - -void PinEntryDialog::setCapsLockHint(const QString &txt) { - mCapsLockHint->setText(txt); -} - -void PinEntryDialog::setFormattedPassphrase( - const PinEntryDialog::FormattedPassphraseOptions &options) { - mFormatPassphrase = options.formatPassphrase; - mFormattedPassphraseHint->setTextFormat(Qt::RichText); - mFormattedPassphraseHint->setText(QLatin1String("<html>") + - options.hint.toHtmlEscaped() + - QLatin1String("</html>")); - Accessibility::setName(mFormattedPassphraseHint, options.hint); - // toggleFormattedPassphrase(); -} - -void PinEntryDialog::setConstraintsOptions(const ConstraintsOptions &options) { - mEnforceConstraints = options.enforce; - mConstraintsHint->setText(options.shortHint); - if (!options.longHint.isEmpty()) { - mConstraintsHint->setToolTip( - QLatin1String("<html>") + - options.longHint.toHtmlEscaped().replace(QLatin1String("\n\n"), - QLatin1String("<br>")) + - QLatin1String("</html>")); - Accessibility::setDescription(mConstraintsHint, options.longHint); - } - mConstraintsErrorTitle = options.errorTitle; - - mConstraintsHint->setVisible(mEnforceConstraints && - !options.shortHint.isEmpty()); -} - -void PinEntryDialog::toggleFormattedPassphrase() { - const bool enable_formatting = - mFormatPassphrase && _edit->echoMode() == QLineEdit::Normal; - _edit->setFormattedPassphrase(enable_formatting); - if (mRepeat != nullptr) { - mRepeat->setFormattedPassphrase(enable_formatting); - const bool hint_about_to_be_hidden = - mFormattedPassphraseHint->isVisible() && !enable_formatting; - if (hint_about_to_be_hidden) { - // set hint spacer to current height of hint label before hiding the hint - mFormattedPassphraseHintSpacer->setMinimumHeight( - mFormattedPassphraseHint->height()); - mFormattedPassphraseHintSpacer->setVisible(true); - } else if (enable_formatting) { - mFormattedPassphraseHintSpacer->setVisible(false); - } - mFormattedPassphraseHint->setVisible(enable_formatting); - } -} - -void PinEntryDialog::onBackspace() { - cancelTimeout(); - - if (_disable_echo_allowed) { - _edit->setEchoMode(QLineEdit::NoEcho); - if (mRepeat != nullptr) { - mRepeat->setEchoMode(QLineEdit::NoEcho); - } - } -} - -void PinEntryDialog::updateQuality(const QString &txt) { - int length; - int percent; - QPalette pal; - - _disable_echo_allowed = false; - - if (!_have_quality_bar) { - return; - } - - length = txt.length(); - percent = length != 0 ? pinentry_inq_quality(txt) : 0; - if (length == 0) { - _quality_bar->reset(); - } else { - pal = _quality_bar->palette(); - if (percent < 0) { - pal.setColor(QPalette::Highlight, QColor("red")); - percent = -percent; - } else { - pal.setColor(QPalette::Highlight, QColor("green")); - } - _quality_bar->setPalette(pal); - _quality_bar->setValue(percent); - } -} - -void PinEntryDialog::setPinentryInfo(struct pinentry peinfo) { - _pinentry_info = - GpgFrontend::SecureCreateUniqueObject<struct pinentry>(peinfo); -} - -void PinEntryDialog::focusChanged(QWidget *old, QWidget *now) { - // Grab keyboard. It might be a little weird to do it here, but it works! - // Previously this code was in showEvent, but that did not work in Qt4. - if (!_pinentry_info || (_pinentry_info->grab != 0)) { - if (_grabbed && (old != nullptr) && (old == _edit || old == mRepeat)) { - old->releaseKeyboard(); - _grabbed = false; - } - if (!_grabbed && (now != nullptr) && (now == _edit || now == mRepeat)) { - now->grabKeyboard(); - _grabbed = true; - } - } -} - -void PinEntryDialog::textChanged(const QString &text) { - Q_UNUSED(text); - - cancelTimeout(); - - if ((mVisiActionEdit != nullptr) && sender() == _edit) { - mVisiActionEdit->setVisible(!_edit->pin().isEmpty()); - } - if (mGenerateButton != nullptr) { - mGenerateButton->setVisible(_edit->pin().isEmpty() -#ifndef QT_NO_ACCESSIBILITY - && !mGenerateButton->accessibleName().isEmpty() -#endif - ); - } -} - -void PinEntryDialog::generatePin() { - // std::unique_ptr<char> pin{pinentry_inq_genpin(_pinentry_info.get())}; - // if (pin) { - // if (_edit->echoMode() == QLineEdit::Password) { - // if (mVisiActionEdit != nullptr) { - // mVisiActionEdit->trigger(); - // } - // if (mVisiCB != nullptr) { - // mVisiCB->setChecked(true); - // } - // } - // const auto pin_str = QString::fromUtf8(pin.get()); - // _edit->setPin(pin_str); - // mRepeat->setPin(pin_str); - // // explicitly focus the first input field and select the generated - // password _edit->setFocus(); _edit->selectAll(); - // } -} - -void PinEntryDialog::toggleVisibility() { - if (sender() != mVisiCB) { - if (_edit->echoMode() == QLineEdit::Password) { - if (mVisiActionEdit != nullptr) { - mVisiActionEdit->setIcon(QIcon(QLatin1String(":hint.svg"))); - mVisiActionEdit->setToolTip(mHideTT); - } - _edit->setEchoMode(QLineEdit::Normal); - if (mRepeat != nullptr) { - mRepeat->setEchoMode(QLineEdit::Normal); - } - } else { - if (mVisiActionEdit != nullptr) { - mVisiActionEdit->setIcon(QIcon(QLatin1String(":visibility.svg"))); - mVisiActionEdit->setToolTip(mVisibilityTT); - } - _edit->setEchoMode(QLineEdit::Password); - if (mRepeat != nullptr) { - mRepeat->setEchoMode(QLineEdit::Password); - } - } - } else { - if (mVisiCB->isChecked()) { - if (mRepeat != nullptr) { - mRepeat->setEchoMode(QLineEdit::Normal); - } - _edit->setEchoMode(QLineEdit::Normal); - } else { - if (mRepeat != nullptr) { - mRepeat->setEchoMode(QLineEdit::Password); - } - _edit->setEchoMode(QLineEdit::Password); - } - } - toggleFormattedPassphrase(); -} - -QString PinEntryDialog::repeatedPin() const { - if (mRepeat != nullptr) { - return mRepeat->pin(); - } - return QString(); -} - -bool PinEntryDialog::timedOut() const { return _timed_out; } - -void PinEntryDialog::setRepeatErrorText(const QString &err) { - if (mRepeatError != nullptr) { - mRepeatError->setText(err); - } -} - -void PinEntryDialog::cancelTimeout() { - if (_timer != nullptr) { - _timer->stop(); - } -} - -void PinEntryDialog::checkCapsLock() { - const auto state = capsLockState(); - if (state != LockState::Unknown) { - mCapsLockHint->setVisible(state == LockState::On); - } -} - -void PinEntryDialog::onAccept() { - cancelTimeout(); - - if ((mRepeat != nullptr) && mRepeat->pin() != _edit->pin()) { -#ifndef QT_NO_ACCESSIBILITY - if (QAccessible::isActive()) { - QMessageBox::information(this, mRepeatError->text(), - mRepeatError->text()); - } else -#endif - { - mRepeatError->setVisible(true); - } - return; - } - - accept(); -} diff --git a/src/pinentry/pinentrydialog.h b/src/pinentry/pinentrydialog.h deleted file mode 100644 index 9cc677e5..00000000 --- a/src/pinentry/pinentrydialog.h +++ /dev/null @@ -1,170 +0,0 @@ -/* pinentrydialog.h - A (not yet) secure Qt 4 dialog for PIN entry. - * Copyright (C) 2002, 2008 Klarälvdalens Datakonsult AB (KDAB) - * Copyright 2007 Ingo Klöcker - * Copyright 2016 Intevation GmbH - * Copyright (C) 2021, 2022 g10 Code GmbH - * - * Written by Steffen Hansen <[email protected]>. - * Modified by Andre Heinecke <[email protected]> - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __PINENTRYDIALOG_H__ -#define __PINENTRYDIALOG_H__ - -#include <QAccessible> -#include <QDialog> -#include <QStyle> -#include <QTimer> - -#include "core/function/SecureMemoryAllocator.h" -#include "pinentry.h" - -class QIcon; -class QLabel; -class QPushButton; -class QLineEdit; -class PinLineEdit; -class QString; -class QProgressBar; -class QCheckBox; -class QAction; - -QPixmap applicationIconPixmap(const QIcon &overlayIcon = {}); - -void raiseWindow(QWidget *w); - -class PinEntryDialog : public QDialog { - Q_OBJECT - - Q_PROPERTY(QString description READ description WRITE setDescription) - Q_PROPERTY(QString error READ error WRITE setError) - Q_PROPERTY(QString pin READ pin WRITE setPin) - Q_PROPERTY(QString prompt READ prompt WRITE setPrompt) - public: - struct FormattedPassphraseOptions { - bool formatPassphrase; - QString hint; - }; - struct ConstraintsOptions { - bool enforce; - QString shortHint; - QString longHint; - QString errorTitle; - }; - - explicit PinEntryDialog(QWidget *parent = 0, const char *name = 0, - int timeout = 0, bool modal = false, - bool enable_quality_bar = false, - const QString &repeatString = QString(), - const QString &visibiltyTT = QString(), - const QString &hideTT = QString()); - - void setDescription(const QString &); - QString description() const; - - void setError(const QString &); - QString error() const; - - void setPin(const QString &); - QString pin() const; - - QString repeatedPin() const; - void setRepeatErrorText(const QString &); - - void setPrompt(const QString &); - QString prompt() const; - - void setOkText(const QString &); - void setCancelText(const QString &); - - void setQualityBar(const QString &); - void setQualityBarTT(const QString &); - - void setGenpinLabel(const QString &); - void setGenpinTT(const QString &); - - void setCapsLockHint(const QString &); - - void setFormattedPassphrase(const FormattedPassphraseOptions &options); - - void setConstraintsOptions(const ConstraintsOptions &options); - - void setPinentryInfo(struct pinentry); - - bool timedOut() const; - - protected Q_SLOTS: - void updateQuality(const QString &); - void slotTimeout(); - void textChanged(const QString &); - void focusChanged(QWidget *old, QWidget *now); - void toggleVisibility(); - void onBackspace(); - void generatePin(); - void toggleFormattedPassphrase(); - - protected: - void keyPressEvent(QKeyEvent *event) override; - void keyReleaseEvent(QKeyEvent *event) override; - void showEvent(QShowEvent *event) override; - - private Q_SLOTS: - void cancelTimeout(); - void checkCapsLock(); - void onAccept(); - - private: - enum PassphraseCheckResult { - PassphraseNotChecked = -1, - PassphraseNotOk = 0, - PassphraseOk - }; - - QLabel *_icon = nullptr; - QLabel *_desc = nullptr; - QLabel *_error = nullptr; - QLabel *_prompt = nullptr; - QLabel *_quality_bar_label = nullptr; - QProgressBar *_quality_bar = nullptr; - PinLineEdit *_edit = nullptr; - PinLineEdit *mRepeat = nullptr; - QLabel *mRepeatError = nullptr; - QPushButton *_ok = nullptr; - QPushButton *_cancel = nullptr; - bool _grabbed = false; - bool _have_quality_bar = false; - bool _timed_out = false; - bool _disable_echo_allowed = true; - bool mEnforceConstraints = false; - bool mFormatPassphrase = false; - - GpgFrontend::SecureUniquePtr<struct pinentry> _pinentry_info = nullptr; - QTimer *_timer = nullptr; - QString mVisibilityTT; - QString mHideTT; - QAction *mVisiActionEdit = nullptr; - QPushButton *mGenerateButton = nullptr; - QCheckBox *mVisiCB = nullptr; - QLabel *mFormattedPassphraseHint = nullptr; - QLabel *mFormattedPassphraseHintSpacer = nullptr; - QLabel *mCapsLockHint = nullptr; - QLabel *mConstraintsHint = nullptr; - QString mConstraintsErrorTitle; -}; - -#endif // __PINENTRYDIALOG_H__ diff --git a/src/pinentry/pinlineedit.cpp b/src/pinentry/pinlineedit.cpp deleted file mode 100644 index 9d172b56..00000000 --- a/src/pinentry/pinlineedit.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* pinlineedit.cpp - Modified QLineEdit widget. - * Copyright (C) 2018 Damien Goutte-Gattat - * Copyright (C) 2021 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include "pinlineedit.h" - -#include <QClipboard> -#include <QGuiApplication> -#include <QKeyEvent> - -static const int FormattedPassphraseGroupSize = 5; -static const QChar FormattedPassphraseSeparator = QChar::Nbsp; - -namespace { -struct Selection { - bool empty() const { return start < 0 || start >= end; } - int length() const { return empty() ? 0 : end - start; } - - int start; - int end; -}; -} // namespace - -class PinLineEdit::Private { - PinLineEdit *const q; - - public: - Private(PinLineEdit *q) : q{q} {} - - QString formatted(QString text) const { - const int dashCount = text.size() / FormattedPassphraseGroupSize; - text.reserve(text.size() + dashCount); - for (int i = FormattedPassphraseGroupSize; i < text.size(); - i += FormattedPassphraseGroupSize + 1) { - text.insert(i, FormattedPassphraseSeparator); - } - return text; - } - - Selection formattedSelection(Selection selection) const { - if (selection.empty()) { - return selection; - } - return {selection.start + selection.start / FormattedPassphraseGroupSize, - selection.end + (selection.end - 1) / FormattedPassphraseGroupSize}; - } - - QString unformatted(QString text) const { - for (int i = FormattedPassphraseGroupSize; i < text.size(); - i += FormattedPassphraseGroupSize) { - text.remove(i, 1); - } - return text; - } - - Selection unformattedSelection(Selection selection) const { - if (selection.empty()) { - return selection; - } - return { - selection.start - selection.start / (FormattedPassphraseGroupSize + 1), - selection.end - selection.end / (FormattedPassphraseGroupSize + 1)}; - } - - void copyToClipboard() { - if (q->echoMode() != QLineEdit::Normal) { - return; - } - - QString text = q->selectedText(); - if (mFormattedPassphrase) { - text.remove(FormattedPassphraseSeparator); - } - if (!text.isEmpty()) { - QGuiApplication::clipboard()->setText(text); - } - } - - int selectionEnd() { -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - return q->selectionEnd(); -#else - return q->selectionStart() + q->selectedText().size(); -#endif - } - - public: - bool mFormattedPassphrase = false; -}; - -PinLineEdit::PinLineEdit(QWidget *parent) - : QLineEdit(parent), d{new Private{this}} { - connect(this, SIGNAL(textEdited(QString)), this, SLOT(textEdited())); -} - -PinLineEdit::~PinLineEdit() = default; - -void PinLineEdit::setFormattedPassphrase(bool on) { - if (on == d->mFormattedPassphrase) { - return; - } - d->mFormattedPassphrase = on; - Selection selection{selectionStart(), d->selectionEnd()}; - if (d->mFormattedPassphrase) { - setText(d->formatted(text())); - selection = d->formattedSelection(selection); - } else { - setText(d->unformatted(text())); - selection = d->unformattedSelection(selection); - } - if (!selection.empty()) { - setSelection(selection.start, selection.length()); - } -} - -void PinLineEdit::copy() const { d->copyToClipboard(); } - -void PinLineEdit::cut() { - if (hasSelectedText()) { - copy(); - del(); - } -} - -void PinLineEdit::setPin(const QString &pin) { - setText(d->mFormattedPassphrase ? d->formatted(pin) : pin); -} - -QString PinLineEdit::pin() const { - if (d->mFormattedPassphrase) { - return d->unformatted(text()); - } else { - return text(); - } -} - -void PinLineEdit::keyPressEvent(QKeyEvent *e) { - if (e == QKeySequence::Copy) { - copy(); - return; - } else if (e == QKeySequence::Cut) { - if (!isReadOnly() && hasSelectedText()) { - copy(); - del(); - } - return; - } else if (e == QKeySequence::DeleteEndOfLine) { - if (!isReadOnly()) { - setSelection(cursorPosition(), text().size()); - copy(); - del(); - } - return; - } else if (e == QKeySequence::DeleteCompleteLine) { - if (!isReadOnly()) { - setSelection(0, text().size()); - copy(); - del(); - } - return; - } - - QLineEdit::keyPressEvent(e); - - if (e->key() == Qt::Key::Key_Backspace) { - emit backspacePressed(); - } -} - -void PinLineEdit::textEdited() { - if (!d->mFormattedPassphrase) { - return; - } - auto currentText = text(); - // first calculate the cursor position in the reformatted text; the cursor - // is put left of the separators, so that backspace works as expected - auto cursorPos = cursorPosition(); - cursorPos -= QStringView{currentText}.left(cursorPos).count( - FormattedPassphraseSeparator); - cursorPos += std::max(cursorPos - 1, 0) / FormattedPassphraseGroupSize; - // then reformat the text - currentText.remove(FormattedPassphraseSeparator); - currentText = d->formatted(currentText); - // finally, set reformatted text and updated cursor position - setText(currentText); - setCursorPosition(cursorPos); -} diff --git a/src/pinentry/pinlineedit.h b/src/pinentry/pinlineedit.h deleted file mode 100644 index 72ac85a5..00000000 --- a/src/pinentry/pinlineedit.h +++ /dev/null @@ -1,60 +0,0 @@ -/* pinlineedit.h - Modified QLineEdit widget. - * Copyright (C) 2018 Damien Goutte-Gattat - * Copyright (C) 2021 g10 Code GmbH - * - * Software engineering by Ingo Klöcker <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _PINLINEEDIT_H_ -#define _PINLINEEDIT_H_ - -#include <QLineEdit> - -class PinLineEdit : public QLineEdit { - Q_OBJECT - - public: - explicit PinLineEdit(QWidget *parent = nullptr); - ~PinLineEdit() override; - - void setPin(const QString &pin); - QString pin() const; - - public Q_SLOTS: - void setFormattedPassphrase(bool on); - void copy() const; - void cut(); - - Q_SIGNALS: - void backspacePressed(); - - protected: - void keyPressEvent(QKeyEvent *) override; - - private: - using QLineEdit::setText; - using QLineEdit::text; - - private Q_SLOTS: - void textEdited(); - - private: - class Private; - std::unique_ptr<Private> d; -}; - -#endif // _PINLINEEDIT_H_ diff --git a/src/pinentry/qti18n.cpp b/src/pinentry/qti18n.cpp deleted file mode 100644 index 198e6cc4..00000000 --- a/src/pinentry/qti18n.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* qti18n.cpp - Load qt translations for pinentry. - * Copyright 2021 g10 Code GmbH - * SPDX-FileCopyrightText: 2015 Lukáš Tinkl <[email protected]> - * SPDX-FileCopyrightText: 2021 Ingo Klöcker <[email protected]> - * - * Copied from k18n under the terms of LGPLv2 or later. - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <QCoreApplication> -#include <QDebug> -#include <QLibraryInfo> -#include <QLocale> -#include <QTranslator> - -static bool loadCatalog(const QString &catalog, const QLocale &locale) { - auto translator = new QTranslator(QCoreApplication::instance()); - - if (!translator->load(locale, catalog, QString(), - QLatin1String(":/i18n_qt"))) { - qDebug() << "Loading the" << catalog << "catalog failed for locale" - << locale; - delete translator; - return false; - } - QCoreApplication::instance()->installTranslator(translator); - return true; -} - -static bool loadCatalog(const QString &catalog, const QLocale &locale, - const QLocale &fallbackLocale) { - // try to load the catalog for locale - if (loadCatalog(catalog, locale)) { - return true; - } - // if this fails, then try the fallback locale (if it's different from locale) - if (fallbackLocale != locale) { - return loadCatalog(catalog, fallbackLocale); - } - return false; -} - -// load global Qt translation, needed in KDE e.g. by lots of builtin dialogs -// (QColorDialog, QFontDialog) that we use -static void loadTranslation(const QString &localeName, - const QString &fallbackLocaleName) { - const QLocale locale{localeName}; - const QLocale fallbackLocale{fallbackLocaleName}; - // first, try to load the qt_ meta catalog - if (loadCatalog(QStringLiteral("qt_"), locale, fallbackLocale)) { - return; - } - // if loading the meta catalog failed, then try loading the four catalogs - // it depends on, i.e. qtbase, qtscript, qtmultimedia, qtxmlpatterns, - // separately - const auto catalogs = { - QStringLiteral("qtbase_"), - /* QStringLiteral("qtscript_"), - QStringLiteral("qtmultimedia_"), - QStringLiteral("qtxmlpatterns_"), */ - }; - for (const auto &catalog : catalogs) { - loadCatalog(catalog, locale, fallbackLocale); - } -} - -static void load() { - // The way Qt translation system handles plural forms makes it necessary to - // have a translation file which contains only plural forms for `en`. That's - // why we load the `en` translation unconditionally, then load the - // translation for the current locale to overload it. - loadCatalog(QStringLiteral("qt_"), QLocale{QStringLiteral("en")}); - - const QLocale locale = QLocale::system(); - if (locale.name() != QStringLiteral("en")) { - loadTranslation(locale.name(), locale.bcp47Name()); - } -} - -Q_COREAPP_STARTUP_FUNCTION(load) diff --git a/src/pinentry/secmem++.h b/src/pinentry/secmem++.h deleted file mode 100644 index 116da880..00000000 --- a/src/pinentry/secmem++.h +++ /dev/null @@ -1,91 +0,0 @@ -/* STL allocator for secmem - * Copyright (C) 2008 Marc Mutz <[email protected]> - * - * 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 2 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 <https://www.gnu.org/licenses/>. - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __SECMEM_SECMEMPP_H__ -#define __SECMEM_SECMEMPP_H__ - -#include "../secmem/secmem.h" -#include <cstddef> - -namespace secmem { - - template <typename T> - class alloc { - public: - // type definitions: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef T value_type; - - // rebind - template <typename U> - struct rebind { - typedef alloc<U> other; - }; - - // address - pointer address( reference value ) const { - return &value; - } - const_pointer address( const_reference value ) const { - return &value; - } - - // (trivial) ctors and dtors - alloc() {} - alloc( const alloc & ) {} - template <typename U> alloc( const alloc<U> & ) {} - // copy ctor is ok - ~alloc() {} - - // de/allocation - size_type max_size() const { - return secmem_get_max_size(); - } - - pointer allocate( size_type n, void * =0 ) { - return static_cast<pointer>( secmem_malloc( n * sizeof(T) ) ); - } - - void deallocate( pointer p, size_type ) { - secmem_free( p ); - } - - // de/construct - void construct( pointer p, const T & value ) { - void * loc = p; - new (loc)T(value); - } - void destruct( pointer p ) { - p->~T(); - } - }; - - // equality comparison - template <typename T1,typename T2> - bool operator==( const alloc<T1> &, const alloc<T2> & ) { return true; } - template <typename T1, typename T2> - bool operator!=( const alloc<T1> &, const alloc<T2> & ) { return false; } - -} - -#endif /* __SECMEM_SECMEMPP_H__ */ diff --git a/src/module/CMakeLists.txt b/src/sdk/CMakeLists.txt index 8d894b00..5f1dc65a 100644 --- a/src/module/CMakeLists.txt +++ b/src/sdk/CMakeLists.txt @@ -27,19 +27,30 @@ set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) # define libgpgfrontend_module_sdk -aux_source_directory(sdk MODULE_SDK_SOURCE) +aux_source_directory(. MODULE_SDK_SOURCE) +aux_source_directory(private MODULE_SDK_SOURCE) add_library(gpgfrontend_module_sdk SHARED ${MODULE_SDK_SOURCE}) -set(_export_file_sdk "${CMAKE_CURRENT_SOURCE_DIR}/sdk/GFSDKExport.h") +set(_export_file_sdk "${CMAKE_CURRENT_SOURCE_DIR}/GFSDKExport.h") generate_export_header(gpgfrontend_module_sdk EXPORT_FILE_NAME "${_export_file_sdk}") target_include_directories(gpgfrontend_module_sdk PRIVATE - ${CMAKE_CURRENT_BINARY_DIR}/gpgfrontend_module_sdk_autogen/include - ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) + ${CMAKE_CURRENT_BINARY_DIR}/gpgfrontend_module_sdk_autogen/include) target_include_directories(gpgfrontend_module_sdk PUBLIC sdk) # link module system -target_link_libraries(gpgfrontend_module_sdk PRIVATE gpgfrontend_core) +target_link_libraries(gpgfrontend_module_sdk PRIVATE gpgfrontend_core gpgfrontend_ui) + +# sdk export headers +file(GLOB _headerPath "${CMAKE_CURRENT_SOURCE_DIR}/*.h") +set_target_properties(gpgfrontend_module_sdk PROPERTIES PUBLIC_HEADER "${_headerPath}") + +if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") + # lib output path + set_target_properties(gpgfrontend_module_sdk PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib) +endif() if (XCODE_BUILD) set_target_properties(gpgfrontend_module_sdk @@ -49,16 +60,4 @@ if (XCODE_BUILD) LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") -endif () - -# tracking modules -set(all_integrated_module_libraries "") -file(GLOB children LIST_DIRECTORIES true "mods/*") -foreach(child ${children}) - if(IS_DIRECTORY ${child}) - get_filename_component(dirName ${child} NAME) - add_subdirectory("mods/${dirName}") - - list(APPEND all_integrated_module_libraries ${dirName}) - endif() -endforeach()
\ No newline at end of file +endif ()
\ No newline at end of file diff --git a/src/module/sdk/GFSDK.h b/src/sdk/GFSDK.h index 77e019af..77e019af 100644 --- a/src/module/sdk/GFSDK.h +++ b/src/sdk/GFSDK.h diff --git a/src/module/sdk/GFSDKBasic.cpp b/src/sdk/GFSDKBasic.cpp index 4d8af6c8..8b884c84 100644 --- a/src/module/sdk/GFSDKBasic.cpp +++ b/src/sdk/GFSDKBasic.cpp @@ -31,29 +31,32 @@ #include "core/function/SecureMemoryAllocator.h" #include "core/function/gpg/GpgCommandExecutor.h" #include "core/utils/BuildInfoUtils.h" -#include "core/utils/CommonUtils.h" +#include "sdk/private/CommonUtils.h" +#include "ui/GpgFrontendUIInit.h" auto GFAllocateMemory(uint32_t size) -> void* { return GpgFrontend::SecureMemoryAllocator::Allocate(size); } +auto GFReallocateMemory(void* ptr, uint32_t size) -> void* { + return GpgFrontend::SecureMemoryAllocator::Reallocate(ptr, size); +} + void GFFreeMemory(void* ptr) { return GpgFrontend::SecureMemoryAllocator::Deallocate(ptr); } auto GFProjectVersion() -> const char* { - return GpgFrontend::GFStrDup(GpgFrontend::GetProjectVersion()); + return GFStrDup(GpgFrontend::GetProjectVersion()); } -auto GFQtEnvVersion() -> const char* { - return GpgFrontend::GFStrDup(QT_VERSION_STR); -} +auto GFQtEnvVersion() -> const char* { return GFStrDup(QT_VERSION_STR); } void GFExecuteCommandSync(const char* cmd, int32_t argc, const char** argv, GFCommandExeucteCallback cb, void* data) { QStringList args; for (int i = 0; i < argc; i++) { - args.append(GpgFrontend::GFUnStrDup(argv[i])); + args.append(GFUnStrDup(argv[i])); } GpgFrontend::GpgCommandExecutor::ExecuteContext const context{ @@ -74,7 +77,7 @@ void GFExecuteCommandBatchSync(int32_t context_size, QStringList args; const char** argv = exec_context.argv; for (int j = 0; j < exec_context.argc; j++) { - args.append(GpgFrontend::GFUnStrDup(argv[j])); + args.append(GFUnStrDup(argv[j])); } contexts.append( @@ -94,7 +97,7 @@ auto StrlenSafe(const char* str, size_t max_len) -> size_t { return end - str; } -auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleStrDup(const char* src) -> char* { +auto GFModuleStrDup(const char* src) -> char* { auto len = StrlenSafe(src, kGfStrlenMax); if (len > kGfStrlenMax) return nullptr; @@ -103,4 +106,15 @@ auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleStrDup(const char* src) -> char* { dst[len] = '\0'; return dst; -}
\ No newline at end of file +} + +auto GFAppActiveLocale() -> char* { return GFStrDup(QLocale().name()); } + +auto GFAppRegisterTranslator(char* data, int size) -> int { + auto b = QByteArray(data, size); + QMetaObject::invokeMethod(QApplication::instance()->thread(), [b]() { + GpgFrontend::UI::InstallTranslatorFromQMData(b); + }); + GFFreeMemory(data); + return 0; +} diff --git a/src/module/sdk/GFSDKBasic.h b/src/sdk/GFSDKBasic.h index 07ff6ed7..93392857 100644 --- a/src/module/sdk/GFSDKBasic.h +++ b/src/sdk/GFSDKBasic.h @@ -59,6 +59,16 @@ auto GPGFRONTEND_MODULE_SDK_EXPORT GFAllocateMemory(uint32_t size) -> void*; /** * @brief * + * @param ptr + * @param size + * @return void* + */ +auto GPGFRONTEND_MODULE_SDK_EXPORT GFReallocateMemory(void* ptr, + uint32_t size) -> void*; + +/** + * @brief + * * @return const char* */ auto GPGFRONTEND_MODULE_SDK_EXPORT GFProjectVersion() -> const char*; @@ -104,4 +114,21 @@ void GPGFRONTEND_MODULE_SDK_EXPORT GFExecuteCommandBatchSync( * @return char* */ auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleStrDup(const char*) -> char*; + +/** + * @brief + * + * @return char* + */ +auto GPGFRONTEND_MODULE_SDK_EXPORT GFAppActiveLocale() -> char*; + +/** + * @brief + * + * @param data + * @param size + * @return auto + */ +auto GPGFRONTEND_MODULE_SDK_EXPORT GFAppRegisterTranslator(char* data, + int size) -> int; }
\ No newline at end of file diff --git a/src/module/sdk/GFSDKBuildInfo.h.in b/src/sdk/GFSDKBuildInfo.h.in index 508c35d4..508c35d4 100644 --- a/src/module/sdk/GFSDKBuildInfo.h.in +++ b/src/sdk/GFSDKBuildInfo.h.in diff --git a/src/module/sdk/GFSDKExport.h b/src/sdk/GFSDKExport.h index a62168bc..a62168bc 100644 --- a/src/module/sdk/GFSDKExport.h +++ b/src/sdk/GFSDKExport.h diff --git a/src/module/sdk/GFSDKExtra.cpp b/src/sdk/GFSDKExtra.cpp index bbfa8575..00e734da 100644 --- a/src/module/sdk/GFSDKExtra.cpp +++ b/src/sdk/GFSDKExtra.cpp @@ -28,15 +28,16 @@ #include "GFSDKExtra.h" -#include "core/utils/BuildInfoUtils.h" -#include "core/utils/CommonUtils.h" +#include <core/utils/BuildInfoUtils.h> +#include <core/utils/CommonUtils.h> + +#include "sdk/private/CommonUtils.h" auto GFCompareSoftwareVersion(const char *current_version, const char *latest_version) -> int { - return GpgFrontend::GFCompareSoftwareVersion( - GpgFrontend::GFUnStrDup(current_version), - GpgFrontend::GFUnStrDup(latest_version)); + return GpgFrontend::GFCompareSoftwareVersion(GFUnStrDup(current_version), + GFUnStrDup(latest_version)); } auto GFHttpRequestUserAgent() -> const char * { - return GpgFrontend::GFStrDup(GpgFrontend::GetHttpRequestUserAgent()); + return GFStrDup(GpgFrontend::GetHttpRequestUserAgent()); }
\ No newline at end of file diff --git a/src/module/sdk/GFSDKExtra.h b/src/sdk/GFSDKExtra.h index 3d7f4226..3d7f4226 100644 --- a/src/module/sdk/GFSDKExtra.h +++ b/src/sdk/GFSDKExtra.h diff --git a/src/module/sdk/GFSDKGpg.cpp b/src/sdk/GFSDKGpg.cpp index 63859763..63859763 100644 --- a/src/module/sdk/GFSDKGpg.cpp +++ b/src/sdk/GFSDKGpg.cpp diff --git a/src/module/sdk/GFSDKGpg.h b/src/sdk/GFSDKGpg.h index 8823bfc5..8823bfc5 100644 --- a/src/module/sdk/GFSDKGpg.h +++ b/src/sdk/GFSDKGpg.h diff --git a/src/main.h b/src/sdk/GFSDKLog.cpp index a394e676..bc1ce7b8 100644 --- a/src/main.h +++ b/src/sdk/GFSDKLog.cpp @@ -26,13 +26,18 @@ * */ -#pragma once +#include "GFSDKLog.h" -#include "core/utils/LogUtils.h" -#include "core/utils/MemoryUtils.h" +#include <qglobal.h> -#define GF_MAIN_LOG_TRACE(...) GF_LOG_TRACE("main", __VA_ARGS__) -#define GF_MAIN_LOG_DEBUG(...) GF_LOG_DEBUG("main", __VA_ARGS__) -#define GF_MAIN_LOG_INFO(...) GF_LOG_INFO("main", __VA_ARGS__) -#define GF_MAIN_LOG_WARN(...) GF_LOG_WARN("main", __VA_ARGS__) -#define GF_MAIN_LOG_ERROR(...) GF_LOG_ERROR("main", __VA_ARGS__)
\ No newline at end of file +Q_LOGGING_CATEGORY(module, "module") + +void GFModuleLogTrace(const char* l) { qCDebug(module) << QString(l); } + +void GFModuleLogDebug(const char* l) { qCDebug(module) << QString(l); } + +void GFModuleLogInfo(const char* l) { qCInfo(module) << QString(l); } + +void GFModuleLogWarn(const char* l) { qCWarning(module) << QString(l); } + +void GFModuleLogError(const char* l) { qCCritical(module) << QString(l); } diff --git a/src/module/sdk/GFSDKLog.h b/src/sdk/GFSDKLog.h index 77e019af..77e019af 100644 --- a/src/module/sdk/GFSDKLog.h +++ b/src/sdk/GFSDKLog.h diff --git a/src/module/sdk/GFSDKModule.cpp b/src/sdk/GFSDKModule.cpp index 00594488..996c9985 100644 --- a/src/module/sdk/GFSDKModule.cpp +++ b/src/sdk/GFSDKModule.cpp @@ -29,70 +29,69 @@ #include "GFSDKModule.h" #include <core/module/ModuleManager.h> -#include <core/utils/CommonUtils.h> +#include <sdk/private/CommonUtils.h> #include "GFSDKBasic.h" void GFModuleListenEvent(const char *module_id, const char *event_id) { return GpgFrontend::Module::ModuleManager::GetInstance().ListenEvent( - GpgFrontend::GFUnStrDup(module_id).toLower(), - GpgFrontend::GFUnStrDup(event_id).toUpper()); + GFUnStrDup(module_id).toLower(), GFUnStrDup(event_id).toUpper()); } auto GFModuleRetrieveRTValueOrDefault(const char *namespace_, const char *key, const char *default_value) -> const char * { - return GpgFrontend::GFStrDup( - GpgFrontend::Module::RetrieveRTValueTypedOrDefault( - GpgFrontend::GFUnStrDup(namespace_), GpgFrontend::GFUnStrDup(key), - GpgFrontend::GFUnStrDup(default_value))); + return GFStrDup(GpgFrontend::Module::RetrieveRTValueTypedOrDefault( + GFUnStrDup(namespace_), GFUnStrDup(key), GFUnStrDup(default_value))); } void GFModuleUpsertRTValue(const char *namespace_, const char *key, const char *vaule) { - GpgFrontend::Module::UpsertRTValue( - GpgFrontend::GFUnStrDup(namespace_).toLower(), - GpgFrontend::GFUnStrDup(key).toLower(), GpgFrontend::GFUnStrDup(vaule)); + GpgFrontend::Module::UpsertRTValue(GFUnStrDup(namespace_).toLower(), + GFUnStrDup(key).toLower(), + GFUnStrDup(vaule)); } void GFModuleUpsertRTValueBool(const char *namespace_, const char *key, int value) { - GpgFrontend::Module::UpsertRTValue( - GpgFrontend::GFUnStrDup(namespace_).toLower(), - GpgFrontend::GFUnStrDup(key).toLower(), value != 0); + GpgFrontend::Module::UpsertRTValue(GFUnStrDup(namespace_).toLower(), + GFUnStrDup(key).toLower(), value != 0); } auto GFModuleListRTChildKeys(const char *namespace_, const char *key, char ***child_keys) -> int32_t { *child_keys = nullptr; auto keys = GpgFrontend::Module::ListRTChildKeys( - GpgFrontend::GFUnStrDup(namespace_).toLower(), - GpgFrontend::GFUnStrDup(key).toLower()); + GFUnStrDup(namespace_).toLower(), GFUnStrDup(key).toLower()); if (keys.empty()) return 0; *child_keys = static_cast<char **>(GFAllocateMemory(sizeof(char **) * keys.size())); - for (int i = 0; i < keys.size(); i++) { - (*child_keys)[i] = GpgFrontend::GFStrDup(keys[i]); + for (decltype(keys.size()) i = 0; i < keys.size(); i++) { + (*child_keys)[i] = GFStrDup(keys[i]); } return static_cast<int32_t>(keys.size()); } void GFModuleTriggerModuleEventCallback(GFModuleEvent *module_event, - const char *module_id, int argc, - char **argv) { - auto data_object = GpgFrontend::TransferParams(); - for (int i = 0; i < argc; i++) { - data_object->AppendObject(GpgFrontend::GFUnStrDup(argv[i])); - } - + const char *module_id, + GFModuleEventParam *p_argv) { + auto argv = ConvertEventParamsToMap(p_argv); auto event = GpgFrontend::Module::ModuleManager::GetInstance().SearchEvent( - GpgFrontend::GFUnStrDup(module_event->trigger_id).toLower()); + GFUnStrDup(module_event->trigger_id).toLower()); if (!event) return; - event.value()->ExecuteCallback(GpgFrontend::GFUnStrDup(module_id), - data_object); -}
\ No newline at end of file + event.value()->ExecuteCallback(GFUnStrDup(module_id), argv); +} + +auto GFModuleRetrieveRTValueOrDefaultBool(const char *namespace_, + const char *key, + int default_value) -> const int { + return static_cast<const int>( + GpgFrontend::Module::RetrieveRTValueTypedOrDefault( + GFUnStrDup(namespace_), GFUnStrDup(key), + static_cast<bool>(default_value))); +} diff --git a/src/module/sdk/GFSDKModule.h b/src/sdk/GFSDKModule.h index 67c1f492..821e3122 100644 --- a/src/module/sdk/GFSDKModule.h +++ b/src/sdk/GFSDKModule.h @@ -79,6 +79,9 @@ auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleRetrieveRTValueOrDefault( const char *namespace_, const char *key, const char *default_value) -> const char *; +auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleRetrieveRTValueOrDefaultBool( + const char *namespace_, const char *key, int default_value) -> const int; + void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleUpsertRTValue(const char *namespace_, const char *key, const char *vaule); @@ -90,5 +93,5 @@ auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleListRTChildKeys( const char *namespace_, const char *key, char ***child_keys) -> int32_t; void GPGFRONTEND_MODULE_SDK_EXPORT GFModuleTriggerModuleEventCallback( - GFModuleEvent *event, const char *module_id, int argc, char **argv); + GFModuleEvent *event, const char *module_id, GFModuleEventParam *argv); };
\ No newline at end of file diff --git a/src/sdk/GFSDKUI.cpp b/src/sdk/GFSDKUI.cpp new file mode 100644 index 00000000..a48f306a --- /dev/null +++ b/src/sdk/GFSDKUI.cpp @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GFSDKUI.h" + +#include <core/utils/CommonUtils.h> + +#include <QMap> +#include <QString> + +#include "sdk/private/CommonUtils.h" +#include "ui/UIModuleManager.h" + +auto MetaDataArrayToQMap(MetaData** meta_data_array, int size) + -> QMap<QString, QString> { + QMap<QString, QString> map; + + for (int i = 0; i < size; ++i) { + QString const key = GFUnStrDup(meta_data_array[i]->key); + QString const value = GFUnStrDup(meta_data_array[i]->value); + map.insert(key, value); + + GpgFrontend::SecureFree(meta_data_array[i]); + } + + GpgFrontend::SecureFree(meta_data_array); + return map; +} + +auto GFUIMountEntry(const char* id, MetaData** meta_data_array, + int meta_data_array_size, EntryFactory factory) -> int { + if (id == nullptr || factory == nullptr) return -1; + + auto meta_data = MetaDataArrayToQMap(meta_data_array, meta_data_array_size); + auto qid = GFUnStrDup(id); + + QMetaObject::invokeMethod( + QApplication::instance()->thread(), [qid, meta_data, factory]() -> int { + return GpgFrontend::UI::UIModuleManager::GetInstance().MountEntry( + qid, meta_data, factory) + ? 0 + : -1; + }); + + return 0; +} diff --git a/src/sdk/GFSDKUI.h b/src/sdk/GFSDKUI.h new file mode 100644 index 00000000..ba9a3490 --- /dev/null +++ b/src/sdk/GFSDKUI.h @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "GFSDKExport.h" + +extern "C" { + +using EntryFactory = void* (*)(const char*); + +struct MetaData { + const char* key; + const char* value; +}; + +auto GPGFRONTEND_MODULE_SDK_EXPORT GFUIMountEntry(const char* id, + MetaData** meta_data_array, + int meta_data_array_size, + EntryFactory factory) -> int; +}
\ No newline at end of file diff --git a/src/module/sdk/GFSDKUtils.cpp b/src/sdk/GFSDKUtils.cpp index fcb510e3..fcb510e3 100644 --- a/src/module/sdk/GFSDKUtils.cpp +++ b/src/sdk/GFSDKUtils.cpp diff --git a/src/module/sdk/GFSDKUtils.h b/src/sdk/GFSDKUtils.h index 7d72e9ee..7d72e9ee 100644 --- a/src/module/sdk/GFSDKUtils.h +++ b/src/sdk/GFSDKUtils.h diff --git a/src/sdk/private/CommonUtils.cpp b/src/sdk/private/CommonUtils.cpp new file mode 100644 index 00000000..31092a3e --- /dev/null +++ b/src/sdk/private/CommonUtils.cpp @@ -0,0 +1,103 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "CommonUtils.h" + +#include <core/utils/MemoryUtils.h> + +#include <cstring> + +#include "GFSDKModule.h" + +auto GFStrDup(const QString& str) -> char* { + auto utf8_str = str.toUtf8(); + auto* c_str = static_cast<char*>( + GpgFrontend::SecureMalloc((utf8_str.size() + 1) * sizeof(char))); + + memcpy(c_str, utf8_str.constData(), utf8_str.size()); + c_str[utf8_str.size()] = '\0'; + return c_str; +} + +auto GFUnStrDup(char* str) -> QString { + auto qt_str = QString::fromUtf8(str); + GpgFrontend::SecureFree(static_cast<void*>(const_cast<char*>(str))); + return qt_str; +} + +auto GFUnStrDup(const char* str) -> QString { + return GFUnStrDup(const_cast<char*>(str)); +} + +auto CharArrayToQMap(char** char_array, int size) -> QMap<QString, QString> { + QMap<QString, QString> map; + for (int i = 0; i < size; i += 2) { + QString const key = GFUnStrDup(char_array[i]); + QString const value = QString::fromUtf8(char_array[i + 1]); + map.insert(key, value); + } + return map; +} + +auto QMapToCharArray(const QMap<QString, QString>& map, int& size) -> char** { + size = map.size() * 2; + char** char_array = new char*[size]; + + int index = 0; + for (auto it = map.begin(); it != map.end(); ++it) { + QByteArray const key = it.key().toUtf8(); + QByteArray const value = it.value().toUtf8(); + + char_array[index] = new char[key.size() + 1]; + std::strcpy(char_array[index], key.constData()); + index++; + + char_array[index] = new char[value.size() + 1]; + std::strcpy(char_array[index], value.constData()); + index++; + } + + return char_array; +} + +auto ConvertEventParamsToMap(GFModuleEventParam* params) + -> QMap<QString, QString> { + QMap<QString, QString> param_map; + GFModuleEventParam* current = params; + GFModuleEventParam* last; + + while (current != nullptr) { + param_map[current->name] = GFUnStrDup(current->value); + + last = current; + current = current->next; + GpgFrontend::SecureFree(last); + } + + return param_map; +}
\ No newline at end of file diff --git a/src/module/mods/gpg_info/GnuPGInfoGatheringModule.h b/src/sdk/private/CommonUtils.h index 35ee4ac3..514bcd5d 100644 --- a/src/module/mods/gpg_info/GnuPGInfoGatheringModule.h +++ b/src/sdk/private/CommonUtils.h @@ -28,29 +28,53 @@ #pragma once -#include <GFSDKModule.h> +struct GFModuleEventParam; -#include "GFModuleExport.h" - -extern "C" { - -auto GF_MODULE_EXPORT GFGetModuleGFSDKVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleQtEnvVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleID() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleMetaData() -> GFModuleMetaData *; +/** + * @brief + * + * @return char* + */ +auto GFStrDup(const QString &) -> char *; -auto GF_MODULE_EXPORT GFRegisterModule() -> int; +/** + * @brief + * + * @param str + * @return QString + */ +auto GFUnStrDup(char *str) -> QString; -auto GF_MODULE_EXPORT GFActiveModule() -> int; +/** + * @brief + * + * @return QString + */ +auto GFUnStrDup(const char *) -> QString; -auto GF_MODULE_EXPORT GFExecuteModule(GFModuleEvent *) -> int; +/** + * @brief + * + * @param char_array + * @param size + * @return QMap<QString, QString> + */ +auto CharArrayToQMap(char **char_array, int size) -> QMap<QString, QString>; -auto GF_MODULE_EXPORT GFDeactiveModule() -> int; +/** + * @brief + * + * @param map + * @param size + * @return char** + */ +auto QMapToCharArray(const QMap<QString, QString> &map, int &size) -> char **; -auto GF_MODULE_EXPORT GFUnregisterModule() -> int; -}; +/** + * @brief + * + * @param params + * @return QMap<QString, QString> + */ +auto ConvertEventParamsToMap(GFModuleEventParam *params) + -> QMap<QString, QString>;
\ No newline at end of file diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index f23cc928..9179f3c0 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -28,16 +28,22 @@ aux_source_directory(./core TEST_SOURCE) aux_source_directory(. TEST_SOURCE) +# define test library add_library(gpgfrontend_test SHARED ${TEST_SOURCE}) +# generate headers set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GpgFrontendTestExport.h") generate_export_header(gpgfrontend_test EXPORT_FILE_NAME "${_export_file}") +# compile definitions +target_compile_definitions(gpgfrontend_test PUBLIC GF_TEST) + +# link options target_link_libraries(gpgfrontend_test PRIVATE gtest) + target_link_libraries(gpgfrontend_test PRIVATE gpgfrontend_core) -target_link_libraries(gpgfrontend_test PRIVATE spdlog) -if (XCODE_BUILD) +if(XCODE_BUILD) set_target_properties(gpgfrontend_test PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} @@ -45,14 +51,13 @@ if (XCODE_BUILD) LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") -endif () - -if(MINGW) - set_target_properties(gtest - PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - ) +endif() + +if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") + # lib output path + set_target_properties(gpgfrontend_test PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib) endif() add_test(AllTestsInGpgFrontend gpgfrontend_test) diff --git a/src/test/GpgFrontendTest.cpp b/src/test/GpgFrontendTest.cpp index 95b4179a..2ad7ada7 100644 --- a/src/test/GpgFrontendTest.cpp +++ b/src/test/GpgFrontendTest.cpp @@ -29,6 +29,7 @@ #include "GpgFrontendTest.h" #include <gtest/gtest.h> +#include <qglobal.h> #include "core/GpgConstants.h" #include "core/function/GlobalSettingStation.h" @@ -37,6 +38,8 @@ #include "core/function/gpg/GpgKeyImportExporter.h" #include "core/utils/IOUtils.h" +Q_LOGGING_CATEGORY(test, "test") + namespace GpgFrontend::Test { auto GenerateRandomString(size_t length) -> QString { @@ -56,8 +59,6 @@ auto GenerateRandomString(size_t length) -> QString { void ConfigureGpgContext() { auto db_path = QDir(QDir::tempPath() + "/" + GenerateRandomString(12)); - GF_TEST_LOG_DEBUG("setting up new database path for test case: {}", - db_path.path()); if (db_path.exists()) db_path.rmdir("."); db_path.mkpath("."); @@ -84,7 +85,7 @@ void ImportPrivateKeys(const QString& data_path, QSettings settings) { GpgKeyImportExporter::GetInstance(kGpgFrontendDefaultChannel) .ImportKey(gf_buffer); } else { - GF_TEST_LOG_ERROR("read from key file failed: {}", key_file); + qCWarning(test) << "read from key file failed: " << key_file; } } } @@ -95,8 +96,8 @@ void SetupGlobalTestEnv() { auto test_config_path = test_path + "/conf/test.ini"; auto test_data_path = test_path + "/data"; - GF_TEST_LOG_INFO("test config file path: {}", test_config_path); - GF_TEST_LOG_INFO("test data file path: {}", test_data_path); + qCInfo(test) << "test config file path: " << test_config_path; + qCInfo(test) << "test data file path: " << test_data_path; ImportPrivateKeys(test_data_path, QSettings(test_config_path, QSettings::IniFormat)); diff --git a/src/test/GpgFrontendTest.h b/src/test/GpgFrontendTest.h index 405eee90..3c1ecbfd 100644 --- a/src/test/GpgFrontendTest.h +++ b/src/test/GpgFrontendTest.h @@ -30,8 +30,13 @@ #include "GpgFrontendTestExport.h" -// Core -#include "core/utils/LogUtils.h" +// declare area of test +#ifdef GF_TEST + +// declare logging category +Q_DECLARE_LOGGING_CATEGORY(test) + +#endif namespace GpgFrontend::Test { @@ -42,10 +47,4 @@ struct GpgFrontendContext { auto GPGFRONTEND_TEST_EXPORT ExecuteAllTestCase(GpgFrontendContext args) -> int; -#define GF_TEST_LOG_TRACE(...) GF_LOG_TRACE("test", __VA_ARGS__) -#define GF_TEST_LOG_DEBUG(...) GF_LOG_DEBUG("test", __VA_ARGS__) -#define GF_TEST_LOG_INFO(...) GF_LOG_INFO("test", __VA_ARGS__) -#define GF_TEST_LOG_WARN(...) GF_LOG_WARN("test", __VA_ARGS__) -#define GF_TEST_LOG_ERROR(...) GF_LOG_ERROR("test", __VA_ARGS__) - } // namespace GpgFrontend::Test diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index e6b41b50..4dcaf73f 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -23,7 +23,6 @@ # # SPDX-License-Identifier: GPL-3.0-or-later - # tracking source files aux_source_directory(. UI_SOURCE) aux_source_directory(dialog/keypair_details UI_SOURCE) @@ -43,46 +42,55 @@ aux_source_directory(function UI_SOURCE) # define libgpgfrontend_ui set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) + add_library(gpgfrontend_ui SHARED ${UI_SOURCE}) + +# generate headers set(_export_file "${CMAKE_CURRENT_SOURCE_DIR}/GpgFrontendUIExport.h") generate_export_header(gpgfrontend_ui EXPORT_FILE_NAME "${_export_file}") +# compile definitions +target_compile_definitions(gpgfrontend_ui PUBLIC GF_UI) + if(GPGFRONTEND_QT5_BUILD) # link Qt target_link_libraries(gpgfrontend_ui - Qt5::Core Qt5::Widgets Qt5::Network Qt5::PrintSupport) + Qt5::Core Qt5::Widgets Qt5::Network Qt5::PrintSupport) else() # link Qt target_link_libraries(gpgfrontend_ui - Qt6::Core Qt6::Widgets Qt6::Network Qt6::PrintSupport) + Qt6::Core Qt6::Widgets Qt6::Network Qt6::PrintSupport) endif() - # link gpgfrontend_core target_link_libraries(gpgfrontend_ui gpgfrontend_core) -# link buddled pinentry -target_link_libraries(gpgfrontend_ui gpgfrontend_pinentry) - # set up pch target_precompile_headers(gpgfrontend_ui PUBLIC GpgFrontendUI.h) # add ui generator include path target_include_directories(gpgfrontend_ui PUBLIC - ${CMAKE_CURRENT_BINARY_DIR}/gpgfrontend_ui_autogen/include - ${CMAKE_SOURCE_DIR}/third_party/spdlog/include) + ${CMAKE_CURRENT_BINARY_DIR}/gpgfrontend_ui_autogen/include) # using std c++ 17 target_compile_features(gpgfrontend_ui PUBLIC cxx_std_17) +if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") + # lib output path + set_target_properties(gpgfrontend_ui PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/lib) +endif() + # for xcode archive build -if (XCODE_BUILD) - set_target_properties(gpgfrontend_ui - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} - XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") -endif () +if(XCODE_BUILD) + set_target_properties(gpgfrontend_ui + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE} + XCODE_ATTRIBUTE_SKIP_INSTALL "Yes" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "${GPGFRONTEND_XOCDE_CODE_SIGN_IDENTITY}") +endif() + target_compile_features(gpgfrontend_ui PUBLIC cxx_std_17)
\ No newline at end of file diff --git a/src/ui/GpgFrontendApplication.cpp b/src/ui/GpgFrontendApplication.cpp index b3c12de6..3ee7ab7d 100644 --- a/src/ui/GpgFrontendApplication.cpp +++ b/src/ui/GpgFrontendApplication.cpp @@ -40,7 +40,7 @@ GpgFrontendApplication::GpgFrontendApplication(int &argc, char *argv[]) #endif // set the extra information of the build - GpgFrontendApplication::setApplicationVersion(GetProjectBuildVersion()); + GpgFrontendApplication::setApplicationVersion(GetProjectVersion()); GpgFrontendApplication::setApplicationName(QString::fromUtf8((PROJECT_NAME))); GpgFrontendApplication::setApplicationDisplayName( QString::fromUtf8((PROJECT_NAME))); @@ -57,7 +57,7 @@ bool GpgFrontendApplication::notify(QObject *receiver, QEvent *event) { try { return QApplication::notify(receiver, event); } catch (const std::exception &ex) { - GF_UI_LOG_ERROR("exception was caught in notify: {}", ex.what()); + qCWarning(ui, "exception was caught in notify: {}", ex.what()); QMessageBox::information( nullptr, tr("Standard Exception Thrown"), tr("Oops, an standard exception was thrown " @@ -66,7 +66,7 @@ bool GpgFrontendApplication::notify(QObject *receiver, QEvent *event) { "be the negligence of the programmer, " "please report this problem if you can.")); } catch (...) { - GF_UI_LOG_ERROR("unknown exception was caught in notify"); + qCWarning(ui, "unknown exception was caught in notify"); QMessageBox::information( nullptr, tr("Unhandled Exception Thrown"), tr("Oops, an unhandled exception was thrown " diff --git a/src/module/sdk/GFSDKUI.h b/src/ui/GpgFrontendUI.cpp index 0702632a..359eb6d2 100644 --- a/src/module/sdk/GFSDKUI.h +++ b/src/ui/GpgFrontendUI.cpp @@ -26,4 +26,6 @@ * */ -#pragma once
\ No newline at end of file +#include "GpgFrontendUI.h" + +Q_LOGGING_CATEGORY(ui, "ui")
\ No newline at end of file diff --git a/src/ui/GpgFrontendUI.h b/src/ui/GpgFrontendUI.h index b3115795..a4793672 100644 --- a/src/ui/GpgFrontendUI.h +++ b/src/ui/GpgFrontendUI.h @@ -33,16 +33,13 @@ */ #include <QtWidgets> -// Core -#include "GpgFrontend.h" -#include "core/GpgFrontendCore.h" -#include "core/utils/LogUtils.h" - // UI #include "ui/GpgFrontendUIExport.h" -#define GF_UI_LOG_TRACE(...) GF_LOG_TRACE("ui", __VA_ARGS__) -#define GF_UI_LOG_DEBUG(...) GF_LOG_DEBUG("ui", __VA_ARGS__) -#define GF_UI_LOG_INFO(...) GF_LOG_INFO("ui", __VA_ARGS__) -#define GF_UI_LOG_WARN(...) GF_LOG_WARN("ui", __VA_ARGS__) -#define GF_UI_LOG_ERROR(...) GF_LOG_ERROR("ui", __VA_ARGS__) +// declare area of ui +#ifdef GF_UI + +// declare logging category +Q_DECLARE_LOGGING_CATEGORY(ui) + +#endif diff --git a/src/ui/GpgFrontendUIInit.cpp b/src/ui/GpgFrontendUIInit.cpp index 046c25d7..b779c335 100644 --- a/src/ui/GpgFrontendUIInit.cpp +++ b/src/ui/GpgFrontendUIInit.cpp @@ -30,6 +30,7 @@ #include <QtNetwork> +#include "UIModuleManager.h" #include "core/GpgConstants.h" #include "core/function/CoreSignalStation.h" #include "core/function/GlobalSettingStation.h" @@ -42,11 +43,12 @@ namespace GpgFrontend::UI { QList<QTranslator*> registered_translators; +QList<QByteArray> loaded_qm_datum; extern void InitUITranslations(); void WaitEnvCheckingProcess() { - GF_UI_LOG_DEBUG("need to waiting for env checking process"); + qCDebug(ui, "need to waiting for env checking process"); // create and show loading window before starting the main window auto* waiting_dialog = new QProgressDialog(); @@ -65,7 +67,6 @@ void WaitEnvCheckingProcess() { QApplication::connect(CoreSignalStation::GetInstance(), &CoreSignalStation::SignalGoodGnupgEnv, waiting_dialog, [=]() { - GF_UI_LOG_DEBUG("gpg env loaded successfuly"); waiting_dialog->finished(0); waiting_dialog->deleteLater(); }); @@ -77,19 +78,19 @@ void WaitEnvCheckingProcess() { &QEventLoop::quit); QApplication::connect(waiting_dialog, &QProgressDialog::canceled, [=]() { - GF_UI_LOG_DEBUG("cancel clicked on waiting dialog"); + qCDebug(ui, "cancel clicked on waiting dialog"); QApplication::quit(); exit(0); }); auto env_state = Module::RetrieveRTValueTypedOrDefault<>("core", "env.state.basic", 0); - GF_UI_LOG_DEBUG("ui is ready to waiting for env initialized, env_state: {}", - env_state); + qCDebug(ui, "ui is ready to waiting for env initialized, env_state: %d", + env_state); // check twice to avoid some unlucky sitations if (env_state == 1) { - GF_UI_LOG_DEBUG("env state turned initialized before the looper start"); + qCDebug(ui, "env state turned initialized before the looper start"); waiting_dialog->finished(0); waiting_dialog->deleteLater(); return; @@ -104,7 +105,13 @@ void WaitEnvCheckingProcess() { looper.exec(); } -void PreInitGpgFrontendUI() { CommonUtils::GetInstance(); } +void PreInitGpgFrontendUI() { + CommonUtils::GetInstance(); + + // declare module ui entry mount points + UIModuleManager::GetInstance().DeclareMountPoint("AboutDialogTabs", "QWidget", + {}); +} void InitGpgFrontendUI(QApplication* /*app*/) { // init locale @@ -151,8 +158,6 @@ void InitGpgFrontendUI(QApplication* /*app*/) { settings.value("proxy/username", QString{}).toString(); QString const proxy_password = settings.value("proxy/password", QString{}).toString(); - GF_UI_LOG_DEBUG("proxy settings: type {}, host {}, port: {}", proxy_type, - proxy_host, proxy_port); QNetworkProxy::ProxyType proxy_type_qt = QNetworkProxy::NoProxy; if (proxy_type == "HTTP") { @@ -181,7 +186,7 @@ void InitGpgFrontendUI(QApplication* /*app*/) { QNetworkProxy::setApplicationProxy(proxy); } catch (...) { - GF_UI_LOG_ERROR("setting operation error: proxy setings"); + qCWarning(ui, "setting operation error: proxy setings"); // no proxy by default QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy); } @@ -202,7 +207,7 @@ auto RunGpgFrontendUI(QApplication* app) -> int { // pre-check, if application need to restart if (CommonUtils::GetInstance()->isApplicationNeedRestart()) { - GF_UI_LOG_DEBUG("application need to restart, before main window init"); + qCDebug(ui, "application need to restart, before main window init."); return kDeepRestartCode; } @@ -210,7 +215,6 @@ auto RunGpgFrontendUI(QApplication* app) -> int { main_window->Init(); // show main windows - GF_UI_LOG_DEBUG("main window is ready to show"); main_window->show(); // start the main event loop @@ -228,13 +232,11 @@ void InitUITranslations() { QCoreApplication::removeTranslator(translator); } registered_translators.clear(); + loaded_qm_datum.clear(); auto* translator = new QTranslator(QCoreApplication::instance()); if (translator->load(QLocale(), QLatin1String("qt"), QLatin1String("_"), QLatin1String(":/i18n_qt"), QLatin1String(".qm"))) { - GF_UI_LOG_DEBUG("load qt translation file done, locale: {}", - QLocale().name()); - QCoreApplication::installTranslator(translator); registered_translators.append(translator); } @@ -242,8 +244,6 @@ void InitUITranslations() { translator = new QTranslator(QCoreApplication::instance()); if (translator->load(QLocale(), QLatin1String("qtbase"), QLatin1String("_"), QLatin1String(":/i18n_qt"), QLatin1String(".qm"))) { - GF_UI_LOG_DEBUG("load qtbase translation file done, locale: {}", - QLocale().name()); QCoreApplication::installTranslator(translator); registered_translators.append(translator); } @@ -252,11 +252,24 @@ void InitUITranslations() { if (translator->load(QLocale(), QLatin1String(PROJECT_NAME), QLatin1String("."), QLatin1String(":/i18n"), QLatin1String(".qm"))) { - GF_UI_LOG_DEBUG("load target translation file done, locale: {}", - QLocale().name()); QCoreApplication::installTranslator(translator); registered_translators.append(translator); } } +auto InstallTranslatorFromQMData(const QByteArray& data) -> bool { + auto* translator = new QTranslator(QCoreApplication::instance()); + + if (translator->load(reinterpret_cast<uchar*>(const_cast<char*>(data.data())), + data.size())) { + QCoreApplication::installTranslator(translator); + registered_translators.append(translator); + loaded_qm_datum.append(data); + + return true; + } + + return false; +} + } // namespace GpgFrontend::UI diff --git a/src/ui/GpgFrontendUIInit.h b/src/ui/GpgFrontendUIInit.h index fd62f3f6..686b3558 100644 --- a/src/ui/GpgFrontendUIInit.h +++ b/src/ui/GpgFrontendUIInit.h @@ -55,4 +55,11 @@ void GPGFRONTEND_UI_EXPORT DestroyGpgFrontendUI(); */ auto GPGFRONTEND_UI_EXPORT RunGpgFrontendUI(QApplication *) -> int; +/** + * @brief + * + */ +auto GPGFRONTEND_UI_EXPORT InstallTranslatorFromQMData(const QByteArray &data) + -> bool; + }; // namespace GpgFrontend::UI diff --git a/src/ui/UIModuleManager.cpp b/src/ui/UIModuleManager.cpp new file mode 100644 index 00000000..1e08010d --- /dev/null +++ b/src/ui/UIModuleManager.cpp @@ -0,0 +1,104 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "UIModuleManager.h" + +#include <utility> + +#include "core/module/ModuleManager.h" + +namespace GpgFrontend::UI { + +UIModuleManager::UIModuleManager(int channel) + : SingletonFunctionObject<UIModuleManager>(channel) {} + +UIModuleManager::~UIModuleManager() = default; + +auto UIModuleManager::DeclareMountPoint( + const QString& id, const QString& entry_type, + QMap<QString, QVariant> meta_data_desc) -> bool { + if (id.isEmpty() || mount_points_.contains(id)) return false; + + UIMountPoint point; + point.id = id; + point.entry_type = entry_type; + point.meta_data_desc = std::move(meta_data_desc); + + mount_points_[id] = point; + + auto grt_key = QString("mount_points.%1").arg(id); + GpgFrontend::Module::UpsertRTValue( + "ui", grt_key, QString(QJsonDocument(point.ToJson()).toJson())); + + return true; +} + +auto UIModuleManager::MountEntry(const QString& id, + QMap<QString, QString> meta_data, + EntryFactory factory) -> bool { + if (id.isEmpty() || !mount_points_.contains(id)) return false; + + if (factory == nullptr) return false; + + MountedUIEntry m_entry; + m_entry.id_ = id; + +#ifdef QT5_BUILD + for (auto it = meta_data.keyValueBegin(); it != meta_data.keyValueEnd(); + ++it) { + meta_data[it->first] = QApplication::translate("GTrC", it->second.toUtf8()); + } +#else + for (const auto& meta : meta_data.asKeyValueRange()) { + meta_data[meta.first] = + QApplication::translate("GTrC", meta.second.toUtf8()); + } +#endif + + m_entry.meta_data_ = std::move(meta_data); + m_entry.factory_ = factory; + + mounted_entries_[id].append(m_entry); + return true; +} + +auto UIModuleManager::QueryMountedEntries(QString id) -> QList<MountedUIEntry> { + if (id.isEmpty() || !mount_points_.contains(id)) return {}; + return mounted_entries_[id]; +} + +auto MountedUIEntry::GetWidget() const -> QWidget* { + return qobject_cast<QWidget*>(static_cast<QObject*>(factory_(id_.toUtf8()))); +} + +auto MountedUIEntry::GetMetaDataByDefault( + const QString& key, QString default_value) const -> QString { + if (!meta_data_.contains(key)) return default_value; + return meta_data_[key]; +} +} // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/UIModuleManager.h b/src/ui/UIModuleManager.h new file mode 100644 index 00000000..88096578 --- /dev/null +++ b/src/ui/UIModuleManager.h @@ -0,0 +1,104 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "GpgFrontendUIExport.h" +#include "core/function/basic/GpgFunctionObject.h" +#include "sdk/GFSDKUI.h" +#include "ui/struct/UIMountPoint.h" + +namespace GpgFrontend::UI { + +struct MountedUIEntry { + QString id_; + QMap<QString, QString> meta_data_; + EntryFactory factory_; + + MountedUIEntry() = default; + + [[nodiscard]] auto GetWidget() const -> QWidget*; + + [[nodiscard]] auto GetMetaDataByDefault(const QString& key, + QString default_value) const + -> QString; +}; + +class GPGFRONTEND_UI_EXPORT UIModuleManager + : public SingletonFunctionObject<UIModuleManager> { + public: + /** + * @brief Construct a new UIModuleManager object + * + * @param channel + */ + explicit UIModuleManager(int channel); + + /** + * @brief Destroy the UIModuleManager object + * + */ + virtual ~UIModuleManager() override; + /** + * @brief + * + * @param id + * @param entry_type + * @param metadata_desc + * @return true + * @return false + */ + auto DeclareMountPoint(const QString& id, const QString& entry_type, + QMap<QString, QVariant> meta_data_desc) -> bool; + + /** + * @brief + * + * @param id + * @param meta_data + * @param entry + * @return true + * @return false + */ + auto MountEntry(const QString& id, QMap<QString, QString> meta_data, + EntryFactory factory) -> bool; + + /** + * @brief + * + * @param id + * @return QList<MountedUIEntry> + */ + auto QueryMountedEntries(QString id) -> QList<MountedUIEntry>; + + private: + QMap<QString, UIMountPoint> mount_points_; + QMap<QString, QList<MountedUIEntry>> mounted_entries_; +}; + +} // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp index 806ceb9e..8f50636b 100644 --- a/src/ui/UserInterfaceUtils.cpp +++ b/src/ui/UserInterfaceUtils.cpp @@ -80,7 +80,6 @@ void ImportUnknownKeyFromKeyserver( auto key_ids = std::make_unique<KeyIdArgsList>(); auto *signature = verify_result.GetSignatures(); while (signature != nullptr) { - GF_UI_LOG_DEBUG("signature fpr: {}", signature->fpr); key_ids->push_back(signature->fpr); signature = signature->next; } @@ -232,8 +231,6 @@ void CommonUtils::WaitForOpera(QWidget *parent, QTimer::singleShot(64, parent, [=]() { opera([dialog]() { if (dialog != nullptr) { - GF_UI_LOG_DEBUG("called operating waiting cb, dialog: {}", - static_cast<void *>(dialog)); dialog->close(); dialog->accept(); } @@ -267,7 +264,7 @@ void CommonUtils::RaiseFailureMessageBox(QWidget *parent, GpgError err) { .arg(desc.second)); } -void CommonUtils::SlotImportKeys(QWidget *parent, const QString &in_buffer) { +void CommonUtils::SlotImportKeys(QWidget *parent, const QByteArray &in_buffer) { auto info = GpgKeyImportExporter::GetInstance().ImportKey(GFBuffer(in_buffer)); emit SignalKeyStatusUpdated(); @@ -313,7 +310,7 @@ void CommonUtils::SlotImportKeyFromKeyServer(QWidget *parent) { void CommonUtils::SlotImportKeyFromClipboard(QWidget *parent) { QClipboard *cb = QApplication::clipboard(); - SlotImportKeys(parent, cb->text(QClipboard::Clipboard)); + SlotImportKeys(parent, cb->text(QClipboard::Clipboard).toLatin1()); } void CommonUtils::SlotExecuteCommand( @@ -328,18 +325,17 @@ void CommonUtils::SlotExecuteCommand( &QEventLoop::quit); connect(cmd_process, &QProcess::errorOccurred, &looper, &QEventLoop::quit); connect(cmd_process, &QProcess::started, - []() -> void { GF_UI_LOG_DEBUG("process started"); }); + []() -> void { qCDebug(ui, "process started"); }); connect(cmd_process, &QProcess::readyReadStandardOutput, [interact_func, cmd_process]() { interact_func(cmd_process); }); connect(cmd_process, &QProcess::errorOccurred, this, - [=]() -> void { GF_UI_LOG_ERROR("error in process"); }); + [=]() -> void { qCWarning(ui, "error in process"); }); connect(cmd_process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, [=](int, QProcess::ExitStatus status) { - if (status == QProcess::NormalExit) - GF_UI_LOG_DEBUG("succeed in executing command: {}", cmd); - else - GF_UI_LOG_WARN("error in executing command: {}", cmd); + if (status != QProcess::NormalExit) { + qCWarning(ui) << "error in executing command: " << cmd; + } }); cmd_process->setProgram(cmd); @@ -365,11 +361,11 @@ void CommonUtils::SlotExecuteGpgCommand( &WaitingDialog::deleteLater); connect(gpg_process, &QProcess::errorOccurred, &looper, &QEventLoop::quit); connect(gpg_process, &QProcess::started, - []() -> void { GF_UI_LOG_DEBUG("gpg process started"); }); + []() -> void { qCDebug(ui, "gpg process started"); }); connect(gpg_process, &QProcess::readyReadStandardOutput, [interact_func, gpg_process]() { interact_func(gpg_process); }); connect(gpg_process, &QProcess::errorOccurred, this, [=]() -> void { - GF_UI_LOG_ERROR("Error in Process"); + qCWarning(ui, "Error in Process"); dialog->close(); QMessageBox::critical(nullptr, tr("Failure"), tr("Failed to execute command.")); @@ -388,7 +384,6 @@ void CommonUtils::SlotExecuteGpgCommand( const auto app_path = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.app_path", QString{}); - GF_UI_LOG_DEBUG("got gnupg app path from rt: {}", app_path); gpg_process->setProgram(app_path); gpg_process->setArguments(arguments); @@ -409,8 +404,6 @@ void CommonUtils::SlotImportKeyFromKeyServer( "please set a default keyserver first")); return; } - GF_UI_LOG_DEBUG("set target key server to default Key Server: {}", - target_keyserver); auto *thread = QThread::create([target_keyserver, key_ids, callback]() { QUrl target_keyserver_url(target_keyserver); @@ -426,8 +419,6 @@ void CommonUtils::SlotImportKeyFromKeyServer( target_keyserver_url.host() + "/pks/lookup?op=get&search=0x" + key_id + "&options=mr"); - GF_UI_LOG_DEBUG("request url: {}", req_url.toString()); - // Waiting for reply auto request = QNetworkRequest(req_url); request.setHeader(QNetworkRequest::UserAgentHeader, @@ -498,21 +489,19 @@ void CommonUtils::slot_update_key_from_server_finished( bool success, QString err_msg, QByteArray buffer, std::shared_ptr<GpgImportInformation> info) { if (!success) { - GF_UI_LOG_ERROR("get err from reply: {}", buffer); + qCWarning(ui) << "get err from reply: " << buffer; QMessageBox::critical(nullptr, tr("Error"), err_msg); return; } // refresh the key database - emit UISignalStation::GetInstance()->SignalKeyDatabaseRefresh(); + emit UISignalStation::GetInstance() -> SignalKeyDatabaseRefresh(); // show details (new KeyImportDetailDialog(std::move(info), this))->exec(); } void CommonUtils::SlotRestartApplication(int code) { - GF_UI_LOG_DEBUG("application need restart, code: {}", code); - if (code == 0) { std::exit(0); } else { @@ -529,34 +518,41 @@ auto CommonUtils::KeyExistsinFavouriteList(const GpgKey &key) -> bool { auto json_data = CacheObject("favourite_key_pair"); if (!json_data.isArray()) json_data.setArray(QJsonArray()); - auto key_array = json_data.array(); - return std::find(key_array.begin(), key_array.end(), key.GetFingerprint()) != - key_array.end(); + auto key_fpr_array = json_data.array(); + return std::find(key_fpr_array.begin(), key_fpr_array.end(), + key.GetFingerprint()) != key_fpr_array.end(); } void CommonUtils::AddKey2Favourtie(const GpgKey &key) { - auto json_data = CacheObject("favourite_key_pair"); - QJsonArray key_array; - if (json_data.isArray()) key_array = json_data.array(); + { + auto json_data = CacheObject("favourite_key_pair"); + QJsonArray key_array; + if (json_data.isArray()) key_array = json_data.array(); + + key_array.push_back(key.GetFingerprint()); + json_data.setArray(key_array); + } - key_array.push_back(key.GetFingerprint()); - json_data.setArray(key_array); + emit SignalFavoritesChanged(); } void CommonUtils::RemoveKeyFromFavourite(const GpgKey &key) { - auto json_data = CacheObject("favourite_key_pair"); - QJsonArray key_array; - if (json_data.isArray()) key_array = json_data.array(); - - QString fingerprint = key.GetFingerprint(); - QJsonArray new_key_array; - for (auto &&item : key_array) { - if (item.isString() && item.toString() != fingerprint) { - new_key_array.append(item); + { + auto json_data = CacheObject("favourite_key_pair"); + QJsonArray key_array; + if (json_data.isArray()) key_array = json_data.array(); + + auto fingerprint = key.GetFingerprint(); + QJsonArray new_key_array; + for (auto &&item : key_array) { + if (item.isString() && item.toString() != fingerprint) { + new_key_array.append(item); + } } + json_data.setArray(new_key_array); } - json_data.setArray(new_key_array); + emit SignalFavoritesChanged(); } /** diff --git a/src/ui/UserInterfaceUtils.h b/src/ui/UserInterfaceUtils.h index 304ba37b..4f42db8c 100644 --- a/src/ui/UserInterfaceUtils.h +++ b/src/ui/UserInterfaceUtils.h @@ -63,8 +63,8 @@ void show_verify_details(QWidget* parent, InfoBoardWidget* info_board, * @param parent * @param verify_res */ -void ImportUnknownKeyFromKeyserver( - QWidget* parent, const GpgVerifyResultAnalyse& verify_res); +void ImportUnknownKeyFromKeyserver(QWidget* parent, + const GpgVerifyResultAnalyse& verify_res); /** * @brief @@ -135,7 +135,7 @@ class CommonUtils : public QWidget { * * @return CommonUtils* */ - static CommonUtils* GetInstance(); + static auto GetInstance() -> CommonUtils*; /** * @brief @@ -214,14 +214,21 @@ class CommonUtils : public QWidget { */ void SignalRestartApplication(int); + /** + * @brief + * + */ + void SignalFavoritesChanged(); + public slots: + /** * @brief * * @param parent * @param in_buffer */ - void SlotImportKeys(QWidget* parent, const QString& in_buffer); + void SlotImportKeys(QWidget* parent, const QByteArray& in_buffer); /** * @brief diff --git a/src/ui/dialog/GeneralDialog.cpp b/src/ui/dialog/GeneralDialog.cpp index 2015322f..91ede794 100644 --- a/src/ui/dialog/GeneralDialog.cpp +++ b/src/ui/dialog/GeneralDialog.cpp @@ -52,21 +52,14 @@ void GpgFrontend::UI::GeneralDialog::slot_restore_settings() noexcept { if (window_state.window_save) { int x = window_state.x; int y = window_state.y; - GF_UI_LOG_DEBUG("stored dialog pos, x: {}, y: {}", x, y); QPoint relative_pos = {x, y}; QPoint pos = parent_rect_.topLeft() + relative_pos; - GF_UI_LOG_DEBUG("relative dialog pos, x: {}, y: {}", relative_pos.x(), - relative_pos.y()); int width = window_state.width; int height = window_state.height; - GF_UI_LOG_DEBUG("stored dialog size, width: {}, height: {}", width, - height); QRect target_rect = {pos.x(), pos.y(), width, height}; - GF_UI_LOG_DEBUG("dialog stored target rect, width: {}, height: {}", width, - height); // check for valid if (width > 0 && height > 0 && screen_rect_.contains(target_rect)) { @@ -76,7 +69,7 @@ void GpgFrontend::UI::GeneralDialog::slot_restore_settings() noexcept { } } catch (...) { - GF_UI_LOG_ERROR("error at restoring settings"); + qCWarning(ui, "error at restoring settings"); } } @@ -86,14 +79,8 @@ void GpgFrontend::UI::GeneralDialog::slot_save_settings() noexcept { update_rect_cache(); - GF_UI_LOG_DEBUG("dialog pos, x: {}, y: {}", rect_.x(), rect_.y()); - GF_UI_LOG_DEBUG("dialog size, width: {}, height: {}", rect_.width(), - rect_.height()); - // window position relative to parent auto relative_pos = rect_.topLeft() - parent_rect_.topLeft(); - GF_UI_LOG_DEBUG("store dialog pos, x: {}, y: {}", relative_pos.x(), - relative_pos.y()); WindowStateSO window_state; window_state.x = relative_pos.x(); @@ -105,18 +92,13 @@ void GpgFrontend::UI::GeneralDialog::slot_save_settings() noexcept { general_windows_state.Store(window_state.Json()); } catch (...) { - GF_UI_LOG_ERROR("general dialog: {}, caught exception", name_); + qCWarning(ui) << "general dialog: " << name_ << ", caught exception"; } } void GpgFrontend::UI::GeneralDialog::setPosCenterOfScreen() { update_rect_cache(); - int screen_width = screen_rect_.width(); - int screen_height = screen_rect_.height(); - GF_UI_LOG_DEBUG("dialog current screen available geometry", screen_width, - screen_height); - // update rect of current dialog rect_ = this->geometry(); this->move(screen_rect_.center() - @@ -131,16 +113,6 @@ void GpgFrontend::UI::GeneralDialog::movePosition2CenterOfParent() { // update cache update_rect_cache(); - // log for debug - GF_UI_LOG_DEBUG("parent pos x: {} y: {}", parent_rect_.x(), parent_rect_.y()); - GF_UI_LOG_DEBUG("parent size width: {}, height: {}", parent_rect_.width(), - parent_rect_.height()); - GF_UI_LOG_DEBUG("parent center pos x: {}, y: {}", parent_rect_.center().x(), - parent_rect_.center().y()); - GF_UI_LOG_DEBUG("dialog pos x: {} y: {}", rect_.x(), rect_.y()); - GF_UI_LOG_DEBUG("dialog size width: {} height: {}", rect_.width(), - rect_.height()); - if (parent_rect_.topLeft() != QPoint{0, 0} && parent_rect_.size() != QSize{0, 0}) { if (rect_.width() <= 0) rect_.setWidth(100); @@ -149,10 +121,6 @@ void GpgFrontend::UI::GeneralDialog::movePosition2CenterOfParent() { QPoint target_position = parent_rect_.center() - QPoint(rect_.width() / 2, rect_.height() / 2); - GF_UI_LOG_DEBUG( - "update position to parent's center, target pos, x:{}, y: {}", - target_position.x(), target_position.y()); - this->move(target_position); } else { setPosCenterOfScreen(); @@ -207,9 +175,6 @@ auto GpgFrontend::UI::GeneralDialog::isRectRestored() -> bool { * */ void GpgFrontend::UI::GeneralDialog::showEvent(QShowEvent *event) { - GF_UI_LOG_DEBUG("General Dialog named {} is about to show, caught show event", - name_); - // default position strategy if (!isRectRestored()) movePosition2CenterOfParent(); diff --git a/src/ui/dialog/SignersPicker.cpp b/src/ui/dialog/SignersPicker.cpp index 9c342cc7..7152bc6e 100644 --- a/src/ui/dialog/SignersPicker.cpp +++ b/src/ui/dialog/SignersPicker.cpp @@ -44,22 +44,23 @@ SignersPicker::SignersPicker(QWidget* parent) connect(cancel_button, &QPushButton::clicked, this, &QDialog::reject); /*Setup KeyList*/ - key_list_ = new KeyList(0U, this); - key_list_->AddListGroupTab( - tr("Signers"), "signers", KeyListRow::ONLY_SECRET_KEY, - KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage, - [](const GpgKey& key, const KeyTable&) -> bool { - return key.IsHasActualSigningCapability(); - }); + key_list_ = + new KeyList(KeyMenuAbility::kCOLUMN_FILTER | KeyMenuAbility::kSEARCH_BAR, + GpgKeyTableColumn::kNAME | GpgKeyTableColumn::kEMAIL_ADDRESS | + GpgKeyTableColumn::kKEY_ID | GpgKeyTableColumn::kUSAGE, + this); + key_list_->AddListGroupTab(tr("Signers"), "signers", + GpgKeyTableDisplayMode::kPRIVATE_KEY, + [](const GpgKey& key) -> bool { + return key.IsHasActualSigningCapability(); + }); key_list_->SlotRefresh(); auto* vbox2 = new QVBoxLayout(); vbox2->addWidget(new QLabel(tr("Select Signer(s)") + ": ")); vbox2->addWidget(key_list_); vbox2->addWidget(new QLabel( - QString( - tr("Please select one or more private keys you use for signing.")) + - "\n" + + tr("Please select one or more private keys you use for signing.") + "\n" + tr("If no key is selected, the default key will be used for signing."))); vbox2->addWidget(confirm_button); vbox2->addWidget(cancel_button); diff --git a/src/ui/dialog/Wizard.cpp b/src/ui/dialog/Wizard.cpp index e65366dd..cb43c966 100644 --- a/src/ui/dialog/Wizard.cpp +++ b/src/ui/dialog/Wizard.cpp @@ -60,7 +60,7 @@ void Wizard::slot_wizard_accepted() { auto settings = GlobalSettingStation::GetInstance().GetSettings(); settings.setValue("wizard/show_wizard", false); } catch (...) { - GF_UI_LOG_ERROR("setting operation error"); + qCWarning(ui, "setting operation error"); } if (field("openHelp").toBool()) { emit SignalOpenHelp("docu.html#content"); diff --git a/src/ui/dialog/controller/GnuPGControllerDialog.cpp b/src/ui/dialog/controller/GnuPGControllerDialog.cpp index 1874e255..b09b7280 100644 --- a/src/ui/dialog/controller/GnuPGControllerDialog.cpp +++ b/src/ui/dialog/controller/GnuPGControllerDialog.cpp @@ -100,9 +100,6 @@ GnuPGControllerDialog::GnuPGControllerDialog(QWidget* parent) this, tr("Open Directory"), {}, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - GF_UI_LOG_DEBUG("key database path selected: {}", - selected_custom_key_database_path); - custom_key_database_path_ = selected_custom_key_database_path; // announce the restart @@ -120,9 +117,6 @@ GnuPGControllerDialog::GnuPGControllerDialog(QWidget* parent) this, tr("Open Directory"), {}, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - GF_UI_LOG_DEBUG("gnupg install path selected: {}", - selected_custom_gnupg_install_path); - custom_gnupg_path_ = selected_custom_gnupg_install_path; // announce the restart @@ -177,8 +171,6 @@ GnuPGControllerDialog::GnuPGControllerDialog(QWidget* parent) void GnuPGControllerDialog::SlotAccept() { apply_settings(); - GF_UI_LOG_DEBUG("gnupg controller apply done"); - GF_UI_LOG_DEBUG("restart needed: {}", get_restart_needed()); if (get_restart_needed() != 0) { emit SignalRestartNeeded(get_restart_needed()); } @@ -198,8 +190,6 @@ void GnuPGControllerDialog::slot_update_custom_key_database_path_label( .GetSettings() .value("gnupg/custom_key_database_path") .toString(); - GF_UI_LOG_DEBUG("selected_custom_key_database_path from settings: {}", - custom_key_database_path); custom_key_database_path_ = custom_key_database_path; } @@ -217,7 +207,6 @@ void GnuPGControllerDialog::slot_update_custom_key_database_path_label( if (ui_->currentKeyDatabasePathLabel->text().isEmpty()) { const auto database_path = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.database_path", QString{}); - GF_UI_LOG_DEBUG("got gpgme.ctx.database_path from rt: {}", database_path); ui_->currentKeyDatabasePathLabel->setText(database_path); } } @@ -236,8 +225,6 @@ void GnuPGControllerDialog::slot_update_custom_gnupg_install_path_label( .GetSettings() .value("gnupg/custom_gnupg_install_path") .toString(); - GF_UI_LOG_DEBUG("custom_gnupg_install_path from settings: {}", - custom_gnupg_install_path); custom_gnupg_path_ = custom_gnupg_install_path; } @@ -256,7 +243,6 @@ void GnuPGControllerDialog::slot_update_custom_gnupg_install_path_label( if (ui_->currentCustomGnuPGInstallPathLabel->text().isEmpty()) { const auto gnupg_path = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.app_path", QString{}); - GF_UI_LOG_DEBUG("got gnupg home path from rt: {}", gnupg_path); auto dir = QFileInfo(gnupg_path).path(); ui_->currentCustomGnuPGInstallPathLabel->setText(dir); } @@ -351,7 +337,6 @@ auto GnuPGControllerDialog::get_restart_needed() const -> int { } void GnuPGControllerDialog::slot_set_restart_needed(int mode) { - GF_UI_LOG_INFO("announce restart needed, mode: {}", mode); this->restart_mode_ = mode; } diff --git a/src/ui/dialog/controller/ModuleControllerDialog.cpp b/src/ui/dialog/controller/ModuleControllerDialog.cpp index 4c727b48..e7c0d5fe 100644 --- a/src/ui/dialog/controller/ModuleControllerDialog.cpp +++ b/src/ui/dialog/controller/ModuleControllerDialog.cpp @@ -62,14 +62,14 @@ ModuleControllerDialog::ModuleControllerDialog(QWidget* parent) connect(ui_->moduleListView, &ModuleListView::SignalSelectModule, this, &ModuleControllerDialog::slot_load_module_details); - connect(ui_->activateOrDeactiveButton, &QPushButton::clicked, this, [=]() { + connect(ui_->activateOrDeactivateButton, &QPushButton::clicked, this, [=]() { auto module_id = ui_->moduleListView->GetCurrentModuleID(); if (module_id.isEmpty()) return; if (!module_manager_->IsModuleActivated(module_id)) { module_manager_->ActiveModule(module_id); } else { - module_manager_->DeactiveModule(module_id); + module_manager_->DeactivateModule(module_id); } QTimer::singleShot(1000, [=]() { slot_load_module_details(module_id); }); @@ -93,19 +93,32 @@ ModuleControllerDialog::ModuleControllerDialog(QWidget* parent) Module::TriggerEvent(event_id); }); + connect(ui_->pushButton_4, &QPushButton::clicked, this, []() { + + }); + connect(ui_->showModsDirButton, &QPushButton::clicked, this, [=]() { QDesktopServices::openUrl(QUrl::fromLocalFile( GlobalSettingStation::GetInstance().GetModulesDir())); }); #ifdef RELEASE - ui_->tabWidget->setTabEnabled(2, false); + ui_->tabWidget->setTabVisible(2, false); #endif + + // give user ability to give up all modules + auto disable_loading_all_modules = + GlobalSettingStation::GetInstance() + .GetSettings() + .value("basic/disable_loading_all_modules", false) + .toBool(); + if (disable_loading_all_modules) { + ui_->tabWidget->setTabEnabled(0, false); + } } void ModuleControllerDialog::slot_load_module_details( Module::ModuleIdentifier module_id) { - GF_UI_LOG_DEBUG("loading module details, module id: {}", module_id); auto module = module_manager_->SearchModule(module_id); SettingsObject so(QString("module.%1.so").arg(module_id)); ModuleSO module_so(so); @@ -122,8 +135,6 @@ void ModuleControllerDialog::slot_load_module_details( module_so.module_id = module_id; module_so.module_hash = module->GetModuleHash(); module_so.auto_activate = false; - GF_UI_LOG_DEBUG("reseting module settings object, module id: {}", - module_id); so.Store(module_so.ToJson()); } @@ -177,8 +188,8 @@ void ModuleControllerDialog::slot_load_module_details( } ui_->moduleInfoTextBrowser->setText(buffer); - ui_->activateOrDeactiveButton->setText(if_activated ? tr("Deactivate") - : tr("Activate")); + ui_->activateOrDeactivateButton->setText(if_activated ? tr("Deactivate") + : tr("Activate")); ui_->autoActivateButton->setText(module_so.auto_activate ? tr("Disable Auto Activate") : tr("Enable Auto Activate")); diff --git a/src/ui/dialog/help/AboutDialog.cpp b/src/ui/dialog/help/AboutDialog.cpp index 0735ddba..14cb76ad 100644 --- a/src/ui/dialog/help/AboutDialog.cpp +++ b/src/ui/dialog/help/AboutDialog.cpp @@ -32,7 +32,7 @@ #include "core/module/ModuleManager.h" #include "core/utils/BuildInfoUtils.h" -#include "ui/dialog/help/GnupgTab.h" +#include "ui/UIModuleManager.h" namespace GpgFrontend::UI { @@ -46,20 +46,18 @@ AboutDialog::AboutDialog(const QString& default_tab_name, QWidget* parent) tab_widget->addTab(info_tab, tr("About GpgFrontend")); - if (Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) { - auto* gnupg_tab = new GnupgTab(); - tab_widget->addTab(gnupg_tab, tr("GnuPG")); - } - tab_widget->addTab(translators_tab, tr("Translators")); - if (Module::IsModuleActivate(kVersionCheckingModuleID)) { - auto* update_tab = new UpdateTab(); - tab_widget->addTab(update_tab, tr("Update")); - } + auto entries = + UIModuleManager::GetInstance().QueryMountedEntries("AboutDialogTabs"); - connect(tab_widget, &QTabWidget::currentChanged, this, - [&](int index) { GF_UI_LOG_DEBUG("current index: {}", index); }); + for (const auto& entry : entries) { + auto* widget = entry.GetWidget(); + if (widget != nullptr) { + tab_widget->addTab(widget, + entry.GetMetaDataByDefault("TabTitle", tr("Unnamed"))); + } + } int default_index = 0; for (int i = 0; i < tab_widget->count(); i++) { @@ -90,15 +88,14 @@ void AboutDialog::showEvent(QShowEvent* ev) { QDialog::showEvent(ev); } InfoTab::InfoTab(QWidget* parent) : QWidget(parent) { const auto gpgme_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.version", QString{"2.0.0"}); - GF_UI_LOG_DEBUG("got gpgme version from rt: {}", gpgme_version); auto pixmap = QPixmap(":/icons/gpgfrontend_logo.png"); pixmap = pixmap.scaled(128, 128); auto text = "<center><h2>" + qApp->applicationName() + "</h2></center>" + - "<center><b>" + "v" + qApp->applicationVersion() + "</b></center>" + - "<center>" + GetProjectBuildGitVersion() + "</center>" + "<br><center>" + + "<center><b>" + GetProjectVersion() + "</b></center>" + "<center>" + + GetProjectBuildGitVersion() + "</center>" + "<br><center>" + tr("GpgFrontend is an easy-to-use, compact, cross-platform, " "and installation-free GnuPG Frontend." "It visualizes most of the common operations of GnuPG." @@ -152,137 +149,4 @@ TranslatorsTab::TranslatorsTab(QWidget* parent) : QWidget(parent) { setLayout(main_layout); } -UpdateTab::UpdateTab(QWidget* parent) : QWidget(parent) { - auto* layout = new QGridLayout(); - - current_version_ = GetProjectVersion(); - - auto* tips_label = new QLabel(); - tips_label->setText( - "<center>" + - tr("It is recommended that you always check the version " - "of GpgFrontend and upgrade to the latest version.") + - "</center><center>" + - tr("New versions not only represent new features, but " - "also often represent functional and security fixes.") + - "</center>"); - tips_label->setWordWrap(true); - - current_version_label_ = new QLabel(); - current_version_label_->setText("<center>" + tr("Current Version") + - tr(": ") + "<b>" + current_version_ + - "</b></center>"); - current_version_label_->setWordWrap(true); - - latest_version_label_ = new QLabel(); - latest_version_label_->setWordWrap(true); - - upgrade_label_ = new QLabel(); - upgrade_label_->setWordWrap(true); - upgrade_label_->setOpenExternalLinks(true); - upgrade_label_->setHidden(true); - - pb_ = new QProgressBar(); - pb_->setRange(0, 0); - pb_->setTextVisible(false); - - layout->addWidget(tips_label, 1, 0, 1, -1); - layout->addWidget(current_version_label_, 2, 0, 1, -1); - layout->addWidget(latest_version_label_, 3, 0, 1, -1); - layout->addWidget(upgrade_label_, 4, 0, 1, -1); - layout->addWidget(pb_, 5, 0, 1, -1); - layout->addItem( - new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Fixed), 2, 1, - 1, 1); - - setLayout(layout); -} - -void UpdateTab::showEvent(QShowEvent* event) { - QWidget::showEvent(event); - GF_UI_LOG_DEBUG("loading version loading info from rt"); - - auto is_loading_done = Module::RetrieveRTValueTypedOrDefault<>( - kVersionCheckingModuleID, "version.loading_done", false); - - if (!is_loading_done) { - Module::ListenRTPublishEvent( - this, kVersionCheckingModuleID, "version.loading_done", - [=](Module::Namespace, Module::Key, int, std::any) { - GF_UI_LOG_DEBUG( - "version_checking module version.loading_done changed, calling " - "slot version upgrade"); - this->slot_show_version_status(); - }); - Module::TriggerEvent("CHECK_APPLICATION_VERSION"); - } else { - slot_show_version_status(); - } -} - -void UpdateTab::slot_show_version_status() { - GF_UI_LOG_DEBUG("loading version info from rt"); - this->pb_->setHidden(true); - - auto is_loading_done = Module::RetrieveRTValueTypedOrDefault<>( - kVersionCheckingModuleID, "version.loading_done", false); - - if (!is_loading_done) { - GF_UI_LOG_DEBUG("version info loading haven't been done yet."); - return; - } - - auto is_need_upgrade = Module::RetrieveRTValueTypedOrDefault<>( - kVersionCheckingModuleID, "version.need_upgrade", false); - - auto is_current_a_withdrawn_version = Module::RetrieveRTValueTypedOrDefault<>( - kVersionCheckingModuleID, "version.current_a_withdrawn_version", false); - - auto is_current_version_released = Module::RetrieveRTValueTypedOrDefault<>( - kVersionCheckingModuleID, "version.current_version_released", false); - - auto latest_version = Module::RetrieveRTValueTypedOrDefault<>( - kVersionCheckingModuleID, "version.latest_version", QString{}); - - latest_version_label_->setText("<center><b>" + - tr("Latest Version From Github") + ": " + - latest_version + "</b></center>"); - - if (is_need_upgrade) { - upgrade_label_->setText( - "<center>" + - tr("The current version is less than the latest version on " - "github.") + - "</center><center>" + tr("Please click") + - " <a " - "href=\"https://www.gpgfrontend.bktus.com/#/downloads\">" + - tr("Here") + "</a> " + tr("to download the latest stable version.") + - "</center>"); - upgrade_label_->show(); - } else if (is_current_a_withdrawn_version) { - upgrade_label_->setText( - "<center>" + - tr("This version has serious problems and has been withdrawn. " - "Please stop using it immediately.") + - "</center><center>" + tr("Please click") + - " <a " - "href=\"https://github.com/saturneric/GpgFrontend/releases\">" + - tr("Here") + "</a> " + tr("to download the latest stable version.") + - "</center>"); - upgrade_label_->show(); - } else if (!is_current_version_released) { - upgrade_label_->setText( - "<center>" + - tr("This version has not been released yet, it may be a beta " - "version. If you are not a tester and care about version " - "stability, please do not use this version.") + - "</center><center>" + tr("Please click") + - " <a " - "href=\"https://www.gpgfrontend.bktus.com/#/downloads\">" + - tr("Here") + "</a> " + tr("to download the latest stable version.") + - "</center>"); - upgrade_label_->show(); - } -} - } // namespace GpgFrontend::UI diff --git a/src/ui/dialog/help/AboutDialog.h b/src/ui/dialog/help/AboutDialog.h index 6d152afb..0b9ca5ae 100644 --- a/src/ui/dialog/help/AboutDialog.h +++ b/src/ui/dialog/help/AboutDialog.h @@ -66,47 +66,6 @@ class TranslatorsTab : public QWidget { }; /** - * @brief Class containing the main tab of about dialog - * - */ -class UpdateTab : public QWidget { - Q_OBJECT - - QLabel* current_version_label_; ///< - QLabel* latest_version_label_; ///< - QLabel* upgrade_label_; ///< - QProgressBar* pb_; ///< - QString current_version_; ///< - - public: - /** - * @brief Construct a new Update Tab object - * - * @param parent - */ - explicit UpdateTab(QWidget* parent = nullptr); - - protected: - void showEvent(QShowEvent* event) override; - - private slots: - /** - * @brief - * - * @param version - */ - void slot_show_version_status(); - - signals: - /** - * @brief - * - * @param data - */ - void SignalReplyFromUpdateServer(QByteArray data); -}; - -/** * @brief Class for handling the about dialog * */ diff --git a/src/ui/dialog/help/GnupgTab.cpp b/src/ui/dialog/help/GnupgTab.cpp deleted file mode 100644 index ac018def..00000000 --- a/src/ui/dialog/help/GnupgTab.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -// -// Created by eric on 2022/7/23. -// - -#include "GnupgTab.h" - -#include "core/module/ModuleManager.h" -#include "ui_GnuPGInfo.h" - -namespace GpgFrontend::UI { - -GnupgTab::GnupgTab(QWidget* parent) - : QWidget(parent), - ui_(GpgFrontend::SecureCreateSharedObject<Ui_GnuPGInfo>()) { - ui_->setupUi(this); - - QStringList components_column_titles; - components_column_titles << tr("Name") << tr("Description") << tr("Version") - << tr("Checksum") << tr("Binary Path"); - - ui_->tabWidget->setTabText(0, tr("Components")); - ui_->tabWidget->setTabText(1, tr("Directories")); - ui_->tabWidget->setTabText(2, tr("Options")); - - ui_->componentDetailsTable->setColumnCount(components_column_titles.length()); - ui_->componentDetailsTable->setHorizontalHeaderLabels( - components_column_titles); - ui_->componentDetailsTable->horizontalHeader()->setStretchLastSection(false); - ui_->componentDetailsTable->setSelectionBehavior( - QAbstractItemView::SelectRows); - - // table items not editable - ui_->componentDetailsTable->setEditTriggers( - QAbstractItemView::NoEditTriggers); - - // no focus (rectangle around table items) - // may be it should focus on whole row - ui_->componentDetailsTable->setFocusPolicy(Qt::NoFocus); - ui_->componentDetailsTable->setAlternatingRowColors(true); - - QStringList directories_column_titles; - directories_column_titles << tr("Directory Type") << tr("Path"); - - ui_->directoriesDetailsTable->setColumnCount( - static_cast<int>(directories_column_titles.length())); - ui_->directoriesDetailsTable->setHorizontalHeaderLabels( - directories_column_titles); - ui_->directoriesDetailsTable->horizontalHeader()->setStretchLastSection( - false); - ui_->directoriesDetailsTable->setSelectionBehavior( - QAbstractItemView::SelectRows); - - // table items not editable - ui_->directoriesDetailsTable->setEditTriggers( - QAbstractItemView::NoEditTriggers); - - // no focus (rectangle around table items) - // may be it should focus on whole row - ui_->directoriesDetailsTable->setFocusPolicy(Qt::NoFocus); - ui_->directoriesDetailsTable->setAlternatingRowColors(true); - - QStringList options_column_titles; - options_column_titles << tr("Component") << tr("Group") << tr("Key") - << tr("Description") << tr("Default Value") - << tr("Value"); - - ui_->optionDetailsTable->setColumnCount(options_column_titles.length()); - ui_->optionDetailsTable->setHorizontalHeaderLabels(options_column_titles); - ui_->optionDetailsTable->horizontalHeader()->setStretchLastSection(false); - ui_->optionDetailsTable->setSelectionBehavior(QAbstractItemView::SelectRows); - - // table items not editable - ui_->optionDetailsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - - // no focus (rectangle around table items) - // may be it should focus on whole row - ui_->optionDetailsTable->setFocusPolicy(Qt::NoFocus); - ui_->optionDetailsTable->setAlternatingRowColors(true); - - if (Module::RetrieveRTValueTypedOrDefault( - "ui", "env.state.gnupg_info_gathering", 0) == 1) { - process_software_info(); - } else { - gather_gnupg_info(); - } -} - -void GnupgTab::process_software_info() { - const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", QString{"2.0.0"}); - GF_UI_LOG_DEBUG("got gnupg version from rt: {}", gnupg_version); - - ui_->gnupgVersionLabel->setText( - QString::fromStdString(fmt::format("Version: {}", gnupg_version))); - - auto components = - Module::ListRTChildKeys(kGnuPGInfoGatheringModuleID, "gnupg.components"); - GF_UI_LOG_DEBUG("got gnupg components from rt, size: {}", components.size()); - - ui_->componentDetailsTable->setRowCount(components.size()); - - int row = 0; - for (auto& component : components) { - auto component_info_json_bytes = Module::RetrieveRTValueTypedOrDefault( - kGnuPGInfoGatheringModuleID, - QString("gnupg.components.%1").arg(component), QString{}); - GF_UI_LOG_DEBUG("got gnupg component {} info from rt", component); - - auto component_info_json = - QJsonDocument::fromJson(component_info_json_bytes.toUtf8()); - if (!component_info_json.isObject()) { - GF_UI_LOG_WARN("illegal gnupg component info, json: {}", - QString(component_info_json_bytes)); - continue; - } - - auto component_info = component_info_json.object(); - if (!component_info.contains("name")) { - GF_UI_LOG_WARN( - "illegal gnupg component info. it doesn't have a name, json: {}", - QString(component_info_json_bytes)); - continue; - } - - auto* tmp0 = new QTableWidgetItem(component_info["name"].toString()); - tmp0->setTextAlignment(Qt::AlignCenter); - ui_->componentDetailsTable->setItem(row, 0, tmp0); - - auto* tmp1 = new QTableWidgetItem(component_info["desc"].toString()); - tmp1->setTextAlignment(Qt::AlignCenter); - ui_->componentDetailsTable->setItem(row, 1, tmp1); - - auto* tmp2 = new QTableWidgetItem(component_info["version"].toString()); - tmp2->setTextAlignment(Qt::AlignCenter); - ui_->componentDetailsTable->setItem(row, 2, tmp2); - - auto* tmp3 = - new QTableWidgetItem(component_info["binary_checksum"].toString()); - tmp3->setTextAlignment(Qt::AlignCenter); - ui_->componentDetailsTable->setItem(row, 3, tmp3); - - auto* tmp4 = new QTableWidgetItem(component_info["path"].toString()); - tmp4->setTextAlignment(Qt::AlignLeft); - ui_->componentDetailsTable->setItem(row, 4, tmp4); - - row++; - } - - ui_->componentDetailsTable->resizeColumnsToContents(); - - auto directories = Module::ListRTChildKeys(kGnuPGInfoGatheringModuleID, - QString("gnupg.dirs")); - - ui_->directoriesDetailsTable->setRowCount( - static_cast<int>(directories.size())); - - row = 0; - for (auto& dir : directories) { - const auto dir_path = Module::RetrieveRTValueTypedOrDefault( - kGnuPGInfoGatheringModuleID, QString("gnupg.dirs.%1").arg(dir), - QString{}); - - if (dir_path.isEmpty()) continue; - - auto* tmp0 = new QTableWidgetItem(dir); - tmp0->setTextAlignment(Qt::AlignCenter); - ui_->directoriesDetailsTable->setItem(row, 0, tmp0); - - auto* tmp1 = new QTableWidgetItem(dir_path); - tmp1->setTextAlignment(Qt::AlignCenter); - ui_->directoriesDetailsTable->setItem(row, 1, tmp1); - - row++; - } - - ui_->directoriesDetailsTable->resizeColumnsToContents(); - - // calculate the total row number of configuration table - row = 0; - for (auto& component : components) { - auto options = Module::ListRTChildKeys( - kGnuPGInfoGatheringModuleID, - QString("gnupg.components.%1.options").arg(component)); - for (auto& option : options) { - const auto option_info_json = - QJsonDocument::fromJson(Module::RetrieveRTValueTypedOrDefault( - kGnuPGInfoGatheringModuleID, - QString("gnupg.components.%1.options.%2") - .arg(component) - .arg(option), - QString{}) - .toUtf8()); - - if (!option_info_json.isObject()) continue; - - auto option_info = option_info_json.object(); - if (!option_info.contains("name") || option_info["flags"] == "1") { - continue; - } - row++; - } - } - - ui_->optionDetailsTable->setRowCount(row); - - row = 0; - QString configuration_group; - for (auto& component : components) { - auto options = Module::ListRTChildKeys( - kGnuPGInfoGatheringModuleID, - QString("gnupg.components.%1.options").arg(component)); - - for (auto& option : options) { - auto option_info_json_bytes = Module::RetrieveRTValueTypedOrDefault( - kGnuPGInfoGatheringModuleID, - QString("gnupg.components.%1.options.%2").arg(component).arg(option), - QString{}); - GF_UI_LOG_DEBUG("got gnupg component's option {} info from rt, info: {}", - component, option_info_json_bytes); - - auto option_info_json = - QJsonDocument::fromJson(option_info_json_bytes.toUtf8()); - - if (!option_info_json.isObject()) { - GF_UI_LOG_WARN("illegal gnupg option info, json: {}", - QString(option_info_json_bytes)); - continue; - } - - auto option_info = option_info_json.object(); - if (!option_info.contains("name")) { - GF_UI_LOG_WARN( - "illegal gnupg configuation info. it doesn't have a name, json: {}", - QString(option_info_json_bytes)); - continue; - } - - if (option_info["flags"] == "1") { - configuration_group = option_info["name"].toString(); - continue; - } - - auto* tmp0 = new QTableWidgetItem(component); - tmp0->setTextAlignment(Qt::AlignCenter); - ui_->optionDetailsTable->setItem(row, 0, tmp0); - - auto* tmp1 = new QTableWidgetItem(configuration_group); - tmp1->setTextAlignment(Qt::AlignCenter); - ui_->optionDetailsTable->setItem(row, 1, tmp1); - - auto* tmp2 = new QTableWidgetItem(option_info["name"].toString()); - tmp2->setTextAlignment(Qt::AlignCenter); - ui_->optionDetailsTable->setItem(row, 2, tmp2); - - auto* tmp3 = new QTableWidgetItem(option_info["description"].toString()); - - tmp3->setTextAlignment(Qt::AlignLeft); - ui_->optionDetailsTable->setItem(row, 3, tmp3); - - auto* tmp4 = - new QTableWidgetItem(option_info["default_value"].toString()); - tmp4->setTextAlignment(Qt::AlignLeft); - ui_->optionDetailsTable->setItem(row, 4, tmp4); - - auto* tmp5 = new QTableWidgetItem(option_info["value"].toString()); - tmp5->setTextAlignment(Qt::AlignLeft); - ui_->optionDetailsTable->setItem(row, 5, tmp5); - - row++; - } - } - - ui_->loadProgressBar->hide(); - ui_->tabWidget->setDisabled(false); -} - -void GnupgTab::gather_gnupg_info() { - // if gnupg_info_gathering module activated - if (Module::IsModuleActivate(kGnuPGInfoGatheringModuleID)) { - GF_CORE_LOG_DEBUG( - "module gnupg_info_gathering is activated, " - "loading external gnupg info..."); - - ui_->loadProgressBar->show(); - ui_->tabWidget->setDisabled(true); - - // gather external gnupg info - Module::TriggerEvent( - "REQUEST_GATHERING_GNUPG_INFO", - [=](const Module::EventIdentifier& /*e*/, - const Module::Event::ListenerIdentifier& l_id, DataObjectPtr o) { - GF_CORE_LOG_DEBUG( - "received event REQUEST_GATHERING_GNUPG_INFO callback " - "from module: {}", - l_id); - - if (l_id == kGnuPGInfoGatheringModuleID) { - Module::UpsertRTValue("ui", "env.state.gnupg_info_gathering", 1); - - // gnupg info gathering process finished - GF_CORE_LOG_INFO("gnupg information gathering finished"); - process_software_info(); - } - }); - } -} - -} // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/dialog/help/GnupgTab.h b/src/ui/dialog/help/GnupgTab.h deleted file mode 100644 index 60abd048..00000000 --- a/src/ui/dialog/help/GnupgTab.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -// -// Created by eric on 2022/7/23. -// - -#pragma once - -#include "core/function/gpg/GpgContext.h" -#include "ui/GpgFrontendUI.h" - -class Ui_GnuPGInfo; -namespace GpgFrontend::UI { -class GnupgTab : public QWidget { - Q_OBJECT - public: - /** - * @brief Construct a new Info Tab object - * - * @param parent - */ - explicit GnupgTab(QWidget* parent = nullptr); - - private: - std::shared_ptr<Ui_GnuPGInfo> ui_; ///< - - /** - * @brief - * - */ - void process_software_info(); - - /** - * @brief - * - */ - void gather_gnupg_info(); -}; -} // namespace GpgFrontend::UI diff --git a/src/ui/dialog/import_export/KeyServerImportDialog.cpp b/src/ui/dialog/import_export/KeyServerImportDialog.cpp index 575a97e4..af00549d 100644 --- a/src/ui/dialog/import_export/KeyServerImportDialog.cpp +++ b/src/ui/dialog/import_export/KeyServerImportDialog.cpp @@ -110,7 +110,7 @@ KeyServerImportDialog::KeyServerImportDialog(QWidget* parent) main_layout->addLayout(buttons_layout, 6, 0, 1, 3); this->setLayout(main_layout); - this->setWindowTitle(tr("Import Keys from Keyserver")); + this->setWindowTitle(tr("Import Keys from key server")); this->setModal(true); movePosition2CenterOfParent(); @@ -132,7 +132,7 @@ auto KeyServerImportDialog::create_combo_box() -> QComboBox* { } combo_box->setCurrentText(key_server.GetTargetServer()); } catch (...) { - GF_UI_LOG_ERROR("setting operation error", "server_list", "default_server"); + qCWarning(ui, "setting operation error server_list default_server"); } return combo_box; @@ -208,16 +208,12 @@ void KeyServerImportDialog::slot_search() { void KeyServerImportDialog::slot_search_finished( QNetworkReply::NetworkError error, QByteArray buffer) { - GF_UI_LOG_DEBUG("search result {} {}", error, buffer.size()); - keys_table_->clearContents(); keys_table_->setRowCount(0); auto stream = QTextStream(buffer); if (error != QNetworkReply::NoError) { - GF_UI_LOG_DEBUG("error from reply: {}", error); - switch (error) { case QNetworkReply::ContentNotFoundError: set_message(tr("Not Key Found"), true); @@ -414,7 +410,6 @@ void KeyServerImportDialog::slot_import_finished( set_loading(false); if (!success) { - GF_UI_LOG_ERROR("error from reply: {}", buffer); set_message(err_msg, true); return; } diff --git a/src/ui/dialog/import_export/KeyUploadDialog.cpp b/src/ui/dialog/import_export/KeyUploadDialog.cpp index 7ab34c49..ed408bab 100644 --- a/src/ui/dialog/import_export/KeyUploadDialog.cpp +++ b/src/ui/dialog/import_export/KeyUploadDialog.cpp @@ -74,7 +74,7 @@ void KeyUploadDialog::SlotUpload() { if (CheckGpgError(err) == GPG_ERR_USER_1 || data_obj == nullptr || !data_obj->Check<GFBuffer>()) { - GF_CORE_LOG_ERROR("data object checking failed"); + qCWarning(ui, "data object checking failed"); QMessageBox::critical(this, tr("Error"), tr("Unknown error occurred")); // Done @@ -139,11 +139,9 @@ void KeyUploadDialog::slot_upload_finished() { this->close(); QByteArray response = reply->readAll(); - GF_UI_LOG_DEBUG("upload response: {}", response); auto error = reply->error(); if (error != QNetworkReply::NoError) { - GF_UI_LOG_DEBUG("error from reply: {}", reply->errorString()); QString message; switch (error) { case QNetworkReply::ContentNotFoundError: diff --git a/src/ui/dialog/key_generate/KeygenDialog.cpp b/src/ui/dialog/key_generate/KeygenDialog.cpp index 7585d6f0..cbaebb13 100644 --- a/src/ui/dialog/key_generate/KeygenDialog.cpp +++ b/src/ui/dialog/key_generate/KeygenDialog.cpp @@ -257,16 +257,12 @@ void KeyGenDialog::slot_authentication_box_changed(int state) { } void KeyGenDialog::slot_activated_key_type(int index) { - GF_UI_LOG_DEBUG("key type index changed: {}", index); - // check assert(gen_key_info_->GetSupportedKeyAlgo().size() > static_cast<size_t>(index)); const auto [name, key_algo, subkey_algo] = gen_key_info_->GetSupportedKeyAlgo()[index]; - GF_UI_LOG_DEBUG("target key algo changed, name: {}, key: {}, subkey: {}", - name, key_algo, subkey_algo); assert(!key_algo.isEmpty()); gen_key_info_->SetAlgo(key_algo); diff --git a/src/ui/dialog/key_generate/SubkeyGenerateDialog.cpp b/src/ui/dialog/key_generate/SubkeyGenerateDialog.cpp index eecf2a1d..25da4291 100644 --- a/src/ui/dialog/key_generate/SubkeyGenerateDialog.cpp +++ b/src/ui/dialog/key_generate/SubkeyGenerateDialog.cpp @@ -305,7 +305,7 @@ void SubkeyGenerateDialog::slot_key_gen_accept() { CommonUtils::RaiseMessageBox(this, err); if (CheckGpgError(err) == GPG_ERR_NO_ERROR) { emit UISignalStation::GetInstance() - ->SignalKeyDatabaseRefresh(); + -> SignalKeyDatabaseRefresh(); } }); }); @@ -358,8 +358,6 @@ void SubkeyGenerateDialog::slot_authentication_box_changed(int state) { } void SubkeyGenerateDialog::slot_activated_key_type(int index) { - GF_UI_LOG_DEBUG("key type index changed: {}", index); - // check assert(gen_key_info_->GetSupportedSubkeyAlgo().size() > static_cast<size_t>(index)); diff --git a/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp b/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp index 74f827aa..08564bec 100644 --- a/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp +++ b/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp @@ -34,6 +34,7 @@ #include "core/function/gpg/GpgKeyImportExporter.h" #include "core/function/gpg/GpgKeyOpera.h" #include "core/model/GpgKey.h" +#include "core/module/ModuleManager.h" #include "core/typedef/GpgTypedef.h" #include "core/utils/GpgUtils.h" #include "core/utils/IOUtils.h" @@ -96,6 +97,16 @@ KeyPairOperaTab::KeyPairOperaTab(const QString& key_id, QWidget* parent) key_server_opera_button->setDisabled(forbid_all_gnupg_connection); advance_h_box_layout->addWidget(key_server_opera_button); + if (Module::IsModuleActivate(kPaperKeyModuleID)) { + if (!m_key_.IsPrivateKey() || !m_key_.IsHasMasterKey()) { + auto* import_paper_key_button = new QPushButton(tr("Import A Paper Key")); + import_paper_key_button->setStyleSheet("text-align:center;"); + connect(import_paper_key_button, &QPushButton::clicked, this, + &KeyPairOperaTab::slot_import_paper_key); + vbox_p_k->addWidget(import_paper_key_button); + } + } + if (m_key_.IsPrivateKey() && m_key_.IsHasMasterKey()) { auto* revoke_cert_opera_button = new QPushButton(tr("Revoke Certificate Operation")); @@ -168,6 +179,17 @@ void KeyPairOperaTab::CreateOperaMenu() { connect(export_shortest_secret_key, &QAction::triggered, this, &KeyPairOperaTab::slot_export_short_private_key); + if (Module::IsModuleActivate(kPaperKeyModuleID)) { + auto* export_secret_key_as_paper_key = + new QAction(tr("Export Secret Key As A Paper Key"), this); + connect(export_secret_key_as_paper_key, &QAction::triggered, this, + &KeyPairOperaTab::slot_export_paper_key); + if (!m_key_.IsPrivateKey()) { + export_secret_key_as_paper_key->setDisabled(true); + } + secret_key_export_opera_menu_->addAction(export_secret_key_as_paper_key); + } + secret_key_export_opera_menu_->addAction(export_full_secret_key); secret_key_export_opera_menu_->addAction(export_shortest_secret_key); @@ -366,7 +388,6 @@ void KeyPairOperaTab::slot_modify_tofu_policy() { this, tr("Modify TOFU Policy(Default is Auto)"), tr("Policy for the Key Pair:"), items, 0, false, &ok); if (ok && !item.isEmpty()) { - GF_UI_LOG_DEBUG("selected policy: {}", item); gpgme_tofu_policy_t tofu_policy = GPGME_TOFU_POLICY_AUTO; if (item == tr("Policy Auto")) { tofu_policy = GPGME_TOFU_POLICY_AUTO; @@ -433,11 +454,115 @@ void KeyPairOperaTab::slot_import_revoke_cert() { QFile rev_file(rev_file_info.absoluteFilePath()); -#ifdef QT5_BUILD if (!rev_file.open(QIODevice::ReadOnly)) { + QMessageBox::critical( + this, tr("Error"), + tr("Cannot open this file. Please make sure that this " + "is a regular file and it's readable.")); + return; + } + + emit UISignalStation::GetInstance() -> SignalKeyRevoked(m_key_.GetId()); + CommonUtils::GetInstance()->SlotImportKeys(nullptr, rev_file.readAll()); +} + +void KeyPairOperaTab::slot_export_paper_key() { + if (!Module::IsModuleActivate(kPaperKeyModuleID)) return; + + int ret = QMessageBox::information( + this, tr("Exporting private key as a Paper key"), + "<h3>" + tr("You are about to export your") + "<font color=\"red\">" + + tr(" PRIVATE KEY ") + "</font>!</h3>\n" + + tr("This is NOT your Public Key, so DON'T give it away.") + "<br />" + + tr("A PaperKey is a human-readable printout of your private key, " + "which can be used to recover your key if you lose access to " + "your " + "digital copy. ") + + "<br />" + tr("Keep it in a safe place.") + "<br />" + + tr("Do you REALLY want to export your PRIVATE KEY?"), + QMessageBox::Cancel | QMessageBox::Ok); + + // export key, if ok was clicked + if (ret == QMessageBox::Ok) { + auto [err, gf_buffer] = GpgKeyImportExporter::GetInstance().ExportKey( + m_key_, true, false, true); + if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { + CommonUtils::RaiseMessageBox(this, err); + return; + } + + // generate a file name +#ifndef WINDOWS + auto file_string = m_key_.GetName() + "<" + m_key_.GetEmail() + ">(" + + m_key_.GetId() + ")_paper_key.txt"; +#else + auto file_string = m_key_.GetName() + "[" + m_key_.GetEmail() + "](" + + m_key_.GetId() + ")_paper_key.txt"; +#endif + std::replace(file_string.begin(), file_string.end(), ' ', '_'); + + auto file_name = QFileDialog::getSaveFileName( + this, tr("Export Key To File"), file_string, + tr("Key Files") + " (*.txt);;All Files (*)"); + + if (file_name.isEmpty()) return; + + Module::TriggerEvent( + "REQUEST_TRANS_KEY_2_PAPER_KEY", + { + {"secret_key", QString(gf_buffer.ConvertToQByteArray().toBase64())}, + }, + [this, file_name](Module::EventIdentifier i, + Module::Event::ListenerIdentifier ei, + Module::Event::Params p) { + qCDebug(ui) << "REQUEST_TRANS_KEY_2_PAPER_KEY callback: " << i << ei; + + if (p["ret"] != "0" || p["paper_key"].isEmpty()) { + QMessageBox::critical( + this, tr("Error"), + tr("An error occurred trying to generate Paper Key.")); + return; + } + + if (!WriteFile(file_name, p["paper_key"].toLatin1())) { + QMessageBox::critical( + this, tr("Export Error"), + tr("Couldn't open %1 for writing").arg(file_name)); + return; + } + }); + } +} + +void KeyPairOperaTab::slot_import_paper_key() { + if (!Module::IsModuleActivate(kPaperKeyModuleID)) return; + + auto [err, gf_buffer] = + GpgKeyImportExporter::GetInstance().ExportKey(m_key_, false, false, true); + if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { + CommonUtils::RaiseMessageBox(this, err); + return; + } + + // generate a file name +#ifndef WINDOWS + auto file_string = m_key_.GetName() + "<" + m_key_.GetEmail() + ">(" + + m_key_.GetId() + ")_paper_key.txt"; #else - if (!rev_file.open(QIODeviceBase::ReadOnly)) { + auto file_string = m_key_.GetName() + "[" + m_key_.GetEmail() + "](" + + m_key_.GetId() + ")_paper_key.txt"; #endif + std::replace(file_string.begin(), file_string.end(), ' ', '_'); + + auto file_name = QFileDialog::getOpenFileName( + this, tr("Import A Paper Key"), file_string, + tr("Paper Key File") + " (*.txt);;All Files (*)"); + + if (file_name.isEmpty()) return; + + QFileInfo file_info(file_name); + + if (!file_info.isFile() || !file_info.isReadable()) { QMessageBox::critical( this, tr("Error"), tr("Cannot open this file. Please make sure that this " @@ -445,7 +570,43 @@ void KeyPairOperaTab::slot_import_revoke_cert() { return; } - emit UISignalStation::GetInstance()->SignalKeyRevoked(m_key_.GetId()); - CommonUtils::GetInstance()->SlotImportKeys(nullptr, rev_file.readAll()); + if (file_info.size() > static_cast<qint64>(1024 * 1024)) { + QMessageBox::critical( + this, tr("Error"), + tr("The target file is too large for a paper key keyring.")); + return; + } + + auto [succ, gf_in_buff] = ReadFileGFBuffer(file_name); + if (!succ) { + QMessageBox::critical( + this, tr("Error"), + tr("Cannot open this file. Please make sure that this " + "is a regular file and it's readable.")); + return; + } + + Module::TriggerEvent( + "REQUEST_TRANS_PAPER_KEY_2_KEY", + { + {"public_key", QString(gf_buffer.ConvertToQByteArray().toBase64())}, + {"paper_key_secrets", + QString(gf_in_buff.ConvertToQByteArray().toBase64())}, + }, + [this](Module::EventIdentifier i, Module::Event::ListenerIdentifier ei, + Module::Event::Params p) { + qCDebug(ui) << "REQUEST_TRANS_PAPER_KEY_2_KEY callback: " << i << ei; + + if (p["ret"] != "0" || p["secret_key"].isEmpty()) { + QMessageBox::critical(this, tr("Error"), + tr("An error occurred trying to recover the " + "Paper Key back to the private key.")); + return; + } + + CommonUtils::GetInstance()->SlotImportKeys( + this, QByteArray::fromBase64(p["secret_key"].toLatin1())); + }); } + } // namespace GpgFrontend::UI diff --git a/src/ui/dialog/keypair_details/KeyPairOperaTab.h b/src/ui/dialog/keypair_details/KeyPairOperaTab.h index 22c94957..27bc7400 100644 --- a/src/ui/dialog/keypair_details/KeyPairOperaTab.h +++ b/src/ui/dialog/keypair_details/KeyPairOperaTab.h @@ -126,6 +126,18 @@ class KeyPairOperaTab : public QWidget { */ void slot_import_revoke_cert(); + /** + * @brief + * + */ + void slot_export_paper_key(); + + /** + * @brief + * + */ + void slot_import_paper_key(); + private: GpgKey m_key_; ///< QMenu* key_server_opera_menu_{}; ///< diff --git a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp index 2a9a4c96..1d463aad 100644 --- a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp +++ b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp @@ -175,9 +175,6 @@ void KeyPairSubkeyTab::slot_refresh_subkey_list() { this->buffered_subkeys_.push_back(std::move(sub_key)); } - GF_UI_LOG_DEBUG("buffered_subkeys_ refreshed size", - this->buffered_subkeys_.size()); - subkey_list_->setRowCount(buffered_subkeys_.size()); for (const auto& subkeys : buffered_subkeys_) { @@ -211,12 +208,10 @@ void KeyPairSubkeyTab::slot_refresh_subkey_list() { } } - GF_UI_LOG_DEBUG("subkey_list_ item {} refreshed", row); - row++; } - GF_UI_LOG_DEBUG("subkey_list_ refreshed"); + qCDebug(ui, "subkey_list_ refreshed"); if (subkey_list_->rowCount() > 0) { subkey_list_->selectRow(0); @@ -309,8 +304,6 @@ void KeyPairSubkeyTab::create_subkey_opera_menu() { } void KeyPairSubkeyTab::slot_edit_subkey() { - GF_UI_LOG_DEBUG("fpr {}", get_selected_subkey().GetFingerprint()); - auto* dialog = new KeySetExpireDateDialog( key_.GetId(), get_selected_subkey().GetFingerprint(), this); dialog->show(); diff --git a/src/ui/dialog/keypair_details/KeyPairUIDTab.cpp b/src/ui/dialog/keypair_details/KeyPairUIDTab.cpp index 47cae8c1..5b0a8271 100644 --- a/src/ui/dialog/keypair_details/KeyPairUIDTab.cpp +++ b/src/ui/dialog/keypair_details/KeyPairUIDTab.cpp @@ -228,7 +228,6 @@ void KeyPairUIDTab::slot_refresh_tofu_info() { continue; } auto tofu_infos = uid.GetTofuInfos(); - GF_UI_LOG_DEBUG("tofu info size: {}", tofu_infos->size()); if (tofu_infos->empty()) { tofu_tabs_->hide(); } else { @@ -383,7 +382,6 @@ void KeyPairUIDTab::slot_del_uid() { if (ret == QMessageBox::Yes) { for (const auto& uid : *selected_uids) { - GF_UI_LOG_DEBUG("uid: {}", uid); if (!GpgUIDOperator::GetInstance().RevUID(m_key_, uid)) { QMessageBox::critical( nullptr, tr("Operation Failed"), diff --git a/src/ui/dialog/keypair_details/KeySetExpireDateDialog.cpp b/src/ui/dialog/keypair_details/KeySetExpireDateDialog.cpp index 43fb6f3b..9ab1350c 100644 --- a/src/ui/dialog/keypair_details/KeySetExpireDateDialog.cpp +++ b/src/ui/dialog/keypair_details/KeySetExpireDateDialog.cpp @@ -58,18 +58,10 @@ KeySetExpireDateDialog::KeySetExpireDateDialog(const KeyId& key_id, } void KeySetExpireDateDialog::slot_confirm() { - GF_UI_LOG_DEBUG("confirm called, date: {}, time: {}", - ui_->dateEdit->date().toString(), - ui_->timeEdit->time().toString()); auto datetime = QDateTime(ui_->dateEdit->date(), ui_->timeEdit->time()); std::unique_ptr<QDateTime> expires = nullptr; if (ui_->noExpirationCheckBox->checkState() == Qt::Unchecked) { expires = std::make_unique<QDateTime>(datetime.toLocalTime()); - - GF_UI_LOG_DEBUG("keyid: {}", m_key_.GetId(), m_subkey_, - expires->toSecsSinceEpoch()); - } else { - GF_UI_LOG_DEBUG("keyid: {}", m_key_.GetId(), m_subkey_, "Non Expired"); } auto err = GpgKeyOpera::GetInstance().SetExpire(m_key_, m_subkey_, expires); diff --git a/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp b/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp index a56a7fc7..07c7b688 100644 --- a/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp +++ b/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp @@ -41,11 +41,14 @@ KeyUIDSignDialog::KeyUIDSignDialog(const GpgKey& key, UIDArgsListPtr uid, m_uids_(std::move(uid)), m_key_(key) { const auto key_id = m_key_.GetId(); - m_key_list_ = new KeyList(KeyMenuAbility::NONE, this); + m_key_list_ = + new KeyList(KeyMenuAbility::kCOLUMN_FILTER | KeyMenuAbility::kSEARCH_BAR, + GpgKeyTableColumn::kNAME | GpgKeyTableColumn::kEMAIL_ADDRESS | + GpgKeyTableColumn::kKEY_ID, + this); m_key_list_->AddListGroupTab( - tr("Signers"), "signers", KeyListRow::ONLY_SECRET_KEY, - KeyListColumn::NAME | KeyListColumn::EmailAddress, - [key_id](const GpgKey& key, const KeyTable&) -> bool { + tr("Signers"), "signers", GpgKeyTableDisplayMode::kPRIVATE_KEY, + [key_id](const GpgKey& key) -> bool { return !(key.IsDisabled() || !key.IsHasCertificationCapability() || !key.IsHasMasterKey() || key.IsExpired() || key.IsRevoked() || key_id == key.GetId()); @@ -101,13 +104,9 @@ void KeyUIDSignDialog::slot_sign_key(bool clicked) { // Set Signers auto key_ids = m_key_list_->GetChecked(); auto keys = GpgKeyGetter::GetInstance().GetKeys(key_ids); - - GF_UI_LOG_DEBUG("key info got"); auto expires = std::make_unique<QDateTime>(expires_edit_->dateTime()); - GF_UI_LOG_DEBUG("sign start"); for (const auto& uid : *m_uids_) { - GF_UI_LOG_DEBUG("sign uid: {}", uid); // Sign For mKey if (!GpgKeyManager::GetInstance().SignKey(m_key_, *keys, uid, expires)) { QMessageBox::critical( diff --git a/src/ui/dialog/settings/SettingsAppearance.cpp b/src/ui/dialog/settings/SettingsAppearance.cpp index f09f9823..6f9961c0 100644 --- a/src/ui/dialog/settings/SettingsAppearance.cpp +++ b/src/ui/dialog/settings/SettingsAppearance.cpp @@ -141,16 +141,9 @@ void AppearanceTab::SetSettings() { auto target_theme_index = ui_->themeComboBox->findText(theme); if (theme.isEmpty() || target_theme_index == -1) { #ifdef QT5_BUILD - GF_UI_LOG_DEBUG( - "There is not valid theme found from settings, " - "using current theme (qt5): {}", - QApplication::style()->metaObject()->className()); ui_->themeComboBox->setCurrentIndex(ui_->themeComboBox->findText( QApplication::style()->metaObject()->className())); #else - GF_UI_LOG_DEBUG( - "There is not valid theme found from settings, using current theme: {}", - QApplication::style()->name()); ui_->themeComboBox->setCurrentIndex( ui_->themeComboBox->findText(QApplication::style()->name())); #endif diff --git a/src/ui/dialog/settings/SettingsDialog.cpp b/src/ui/dialog/settings/SettingsDialog.cpp index 70b8c7b0..4d80ced2 100644 --- a/src/ui/dialog/settings/SettingsDialog.cpp +++ b/src/ui/dialog/settings/SettingsDialog.cpp @@ -89,7 +89,7 @@ SettingsDialog::SettingsDialog(QWidget* parent) connect(this, &SettingsDialog::SignalRestartNeeded, qobject_cast<MainWindow*>(parent), &MainWindow::SlotSetRestartNeeded); - this->setMinimumSize(480, 680); + this->setMinimumWidth(500); this->adjustSize(); this->show(); } @@ -112,7 +112,6 @@ void SettingsDialog::SlotAccept() { key_server_tab_->ApplySettings(); network_tab_->ApplySettings(); - GF_UI_LOG_DEBUG("ui restart status: {}", restart_mode_); if (restart_mode_ != kNonRestartCode) { emit SignalRestartNeeded(restart_mode_); } @@ -125,8 +124,6 @@ auto SettingsDialog::ListLanguages() -> QHash<QString, QString> { auto filenames = QDir(QLatin1String(":/i18n")).entryList(); for (const auto& file : filenames) { - GF_UI_LOG_DEBUG("get locale from locale directory: {}", file); - auto start = file.indexOf('.') + 1; auto end = file.lastIndexOf('.'); if (start < 0 || end < 0 || start >= end) continue; diff --git a/src/ui/dialog/settings/SettingsGeneral.cpp b/src/ui/dialog/settings/SettingsGeneral.cpp index 9764b747..6167ea01 100644 --- a/src/ui/dialog/settings/SettingsGeneral.cpp +++ b/src/ui/dialog/settings/SettingsGeneral.cpp @@ -52,6 +52,8 @@ GeneralTab::GeneralTab(QWidget* parent) tr("Enable to use longer key expiration date.")); ui_->importConfirmationCheckBox->setText( tr("Import files dropped on the Key List without confirmation.")); + ui_->disableLoadingModulesCheckBox->setText( + tr("Disable loading of all modules (including integrated modules)")); ui_->langBox->setTitle(tr("Language")); ui_->langNoteLabel->setText( @@ -129,9 +131,13 @@ void GeneralTab::SetSettings() { ui_->importConfirmationCheckBox->setCheckState( confirm_import_keys ? Qt::Checked : Qt::Unchecked); + auto disable_loading_all_modules = + settings.value("basic/disable_loading_all_modules", false).toBool(); + ui_->disableLoadingModulesCheckBox->setCheckState( + disable_loading_all_modules ? Qt::Checked : Qt::Unchecked); + auto lang_key = settings.value("basic/lang").toString(); auto lang_value = lang_.value(lang_key); - GF_UI_LOG_DEBUG("lang settings current: {}", lang_value); if (!lang_.empty()) { ui_->langSelectBox->setCurrentIndex( ui_->langSelectBox->findText(lang_value)); @@ -152,6 +158,8 @@ void GeneralTab::ApplySettings() { ui_->restoreTextEditorPageCheckBox->isChecked()); settings.setValue("basic/confirm_import_keys", ui_->importConfirmationCheckBox->isChecked()); + settings.setValue("basic/disable_loading_all_modules", + ui_->disableLoadingModulesCheckBox->isChecked()); settings.setValue("basic/lang", lang_.key(ui_->langSelectBox->currentText())); } diff --git a/src/ui/dialog/settings/SettingsKeyServer.cpp b/src/ui/dialog/settings/SettingsKeyServer.cpp index fb6e624c..d3e4578c 100644 --- a/src/ui/dialog/settings/SettingsKeyServer.cpp +++ b/src/ui/dialog/settings/SettingsKeyServer.cpp @@ -78,7 +78,6 @@ KeyserverTab::KeyserverTab(QWidget* parent) connect(ui_->keyServerListTable, &QTableWidget::itemChanged, [=](QTableWidgetItem* item) { - GF_UI_LOG_DEBUG("item edited: {}", item->column()); if (item->column() != 1) return; const auto row_size = ui_->keyServerListTable->rowCount(); // Update Actions @@ -180,8 +179,6 @@ void KeyserverTab::ApplySettings() { } void KeyserverTab::slot_refresh_table() { - GF_UI_LOG_INFO("start refreshing key server table"); - ui_->keyServerListTable->blockSignals(true); ui_->keyServerListTable->setRowCount(key_server_str_list_.size()); diff --git a/src/ui/function/GenerateRevokeCertification.cpp b/src/ui/function/GenerateRevokeCertification.cpp index 9f8afcff..f9b655a3 100644 --- a/src/ui/function/GenerateRevokeCertification.cpp +++ b/src/ui/function/GenerateRevokeCertification.cpp @@ -48,14 +48,12 @@ auto GenerateRevokeCertification::Exec(const GpgKey& key, output_path, "--gen-revoke", key.GetFingerprint()}, [=](int exit_code, const QString& p_out, const QString& p_err) { if (exit_code != 0) { - GF_UI_LOG_ERROR( - "gnupg gen revoke execute error, process stderr: {}, process " - "stdout: {}", - p_err, p_out); + qCWarning(ui) << "gnupg gen revoke execute error, process stderr: " + << p_err << ", process stdout: " << p_out; } else { - GF_UI_LOG_DEBUG( - "gnupg gen revoke exit_code: {}, process stdout size: {}", - exit_code, p_out.size()); + qCDebug(ui, + "gnupg gen revoke exit_code: %d, process stdout size: %lld", + exit_code, p_out.size()); } }, nullptr, @@ -63,7 +61,6 @@ auto GenerateRevokeCertification::Exec(const GpgKey& key, // Code From Gpg4Win while (proc->canReadLine()) { const QString line = QString::fromUtf8(proc->readLine()).trimmed(); - GF_UI_LOG_DEBUG("line: {}", line); if (line == QLatin1String("[GNUPG:] GET_BOOL gen_revoke.okay")) { proc->write("y\n"); } else if (line == QLatin1String("[GNUPG:] GET_LINE " diff --git a/src/ui/function/RaisePinentry.cpp b/src/ui/function/RaisePinentry.cpp deleted file mode 100644 index 7c68d67c..00000000 --- a/src/ui/function/RaisePinentry.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "RaisePinentry.h" - -#include "core/function/CoreSignalStation.h" -#include "core/model/GpgPassphraseContext.h" -#include "core/utils/CacheUtils.h" -#include "pinentry/pinentrydialog.h" - -namespace GpgFrontend::UI { - -auto FindTopMostWindow(QWidget* fallback) -> QWidget* { - QList<QWidget*> top_widgets = QApplication::topLevelWidgets(); - foreach (QWidget* widget, top_widgets) { - if (widget->isActiveWindow()) { - GF_UI_LOG_TRACE("find a topmost widget, address: {}", - static_cast<void*>(widget)); - return widget; - } - } - return fallback; -} - -RaisePinentry::RaisePinentry(QWidget* parent, - QSharedPointer<GpgPassphraseContext> context) - : QWidget(parent), context_(std::move(context)) {} - -auto RaisePinentry::Exec() -> int { - GF_UI_LOG_DEBUG( - "setting pinetry's arguments, context uids: {}, passphrase info: {}, " - "prev_was_bad: {}", - context_->GetUidsInfo(), context_->GetPassphraseInfo(), - context_->IsPreWasBad()); - - bool ask_for_new = context_->IsAskForNew() && - context_->GetPassphraseInfo().isEmpty() && - context_->GetUidsInfo().isEmpty(); - - auto* pinentry = - new PinEntryDialog(FindTopMostWindow(this), 0, 15, true, ask_for_new, - ask_for_new ? tr("Repeat Passphrase:") : QString(), - tr("Show passphrase"), tr("Hide passphrase")); - - if (context_->IsPreWasBad()) { - pinentry->setError(tr("Given Passphrase was wrong. Please retry.")); - } - - pinentry->setPrompt(tr("Passphrase:")); - - if (!context_->GetUidsInfo().isEmpty()) { - pinentry->setDescription(QString("Please provide Passphrase of Key:\n%1\n") - .arg(context_->GetUidsInfo())); - } - - struct pinentry pinentry_info; - pinentry->setPinentryInfo(pinentry_info); - - pinentry->setRepeatErrorText(tr("Passphrases do not match")); - pinentry->setGenpinLabel(QString("")); - pinentry->setGenpinTT(QString("")); - pinentry->setCapsLockHint(tr("Caps Lock is on")); - pinentry->setFormattedPassphrase({false, QString()}); - pinentry->setConstraintsOptions({false, QString(), QString(), QString()}); - - pinentry->setWindowTitle(tr("Bundled Pinentry")); - - /* If we reuse the same dialog window. */ - pinentry->setPin(QString()); - pinentry->setOkText(tr("Confirm")); - pinentry->setCancelText(tr("Cancel")); - - GF_UI_LOG_DEBUG("buddled pinentry is ready to start..."); - connect(pinentry, &PinEntryDialog::finished, this, - [pinentry, this](int result) { - bool ret = result != 0; - GF_UI_LOG_DEBUG("buddled pinentry finished, ret: {}", ret); - - if (!ret) { - emit CoreSignalStation::GetInstance() - ->SignalUserInputPassphraseCallback({}); - return -1; - } - - auto pin = pinentry->pin().toUtf8(); - - context_->SetPassphrase(pin); - emit CoreSignalStation::GetInstance() - ->SignalUserInputPassphraseCallback(context_); - return 0; - }); - connect(pinentry, &PinEntryDialog::finished, this, &QWidget::deleteLater); - - pinentry->open(); - return 0; -} -} // namespace GpgFrontend::UI diff --git a/src/ui/function/RaisePinentry.h b/src/ui/function/RaisePinentry.h deleted file mode 100644 index 40175dfd..00000000 --- a/src/ui/function/RaisePinentry.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (C) 2021 Saturneric <[email protected]> - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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. - * - * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric <[email protected]> starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include "ui/GpgFrontendUI.h" - -namespace GpgFrontend { -class GpgPassphraseContext; -} - -namespace GpgFrontend::UI { - -class RaisePinentry : public QWidget { - Q_OBJECT - public: - /** - * @brief Construct a new Raise Pinentry object - * - * @param parent - */ - explicit RaisePinentry(QWidget *parent, QSharedPointer<GpgPassphraseContext>); - - /** - * @brief - * - * @return int - */ - auto Exec() -> int; - - private: - QSharedPointer<GpgPassphraseContext> context_; -}; - -} // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/function/SetOwnerTrustLevel.cpp b/src/ui/function/SetOwnerTrustLevel.cpp index 87f4cb61..29697eaa 100644 --- a/src/ui/function/SetOwnerTrustLevel.cpp +++ b/src/ui/function/SetOwnerTrustLevel.cpp @@ -54,7 +54,6 @@ auto SetOwnerTrustLevel::Exec(const QString& key_id) -> bool { key.GetOwnerTrustLevel(), false, &ok); if (ok && !item.isEmpty()) { - GF_UI_LOG_DEBUG("selected owner trust policy: {}", item); int trust_level = 0; // Unknown Level if (item == tr("Ultimate")) { trust_level = 5; @@ -86,7 +85,7 @@ auto SetOwnerTrustLevel::Exec(const QString& key_id) -> bool { } // update key database and refresh ui - emit UISignalStation::GetInstance()->SignalKeyDatabaseRefresh(); + emit UISignalStation::GetInstance() -> SignalKeyDatabaseRefresh(); return true; } diff --git a/src/ui/main_window/GeneralMainWindow.cpp b/src/ui/main_window/GeneralMainWindow.cpp index 3d662332..9ea13836 100644 --- a/src/ui/main_window/GeneralMainWindow.cpp +++ b/src/ui/main_window/GeneralMainWindow.cpp @@ -45,10 +45,7 @@ GpgFrontend::UI::GeneralMainWindow::GeneralMainWindow(QString name, GpgFrontend::UI::GeneralMainWindow::~GeneralMainWindow() = default; void GpgFrontend::UI::GeneralMainWindow::closeEvent(QCloseEvent *event) { - GF_UI_LOG_DEBUG("main window close event caught, event type: {}", - event->type()); slot_save_settings(); - QMainWindow::closeEvent(event); } @@ -56,16 +53,13 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept { try { WindowStateSO window_state(SettingsObject(name_ + "_state")); - GF_UI_LOG_DEBUG("restore main window state: {}", - window_state.window_state_data); - if (!window_state.window_state_data.isEmpty()) { // state sets pos & size of dock-widgets this->restoreState( QByteArray::fromBase64(window_state.window_state_data.toUtf8())); } - this->setMinimumSize(640, 480); + this->setMinimumSize(800, 600); // restore window size & location if (window_state.window_save) { @@ -73,9 +67,6 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept { size_ = {window_state.width, window_state.height}; if (this->parent() != nullptr) { - GF_UI_LOG_DEBUG("parent address: {}", - static_cast<void *>(this->parent())); - QPoint parent_pos = {0, 0}; QSize parent_size = {0, 0}; @@ -91,12 +82,6 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept { parent_size = parent_window->size(); } - GF_UI_LOG_DEBUG("parent pos x: {} y: {}", parent_pos.x(), - parent_pos.y()); - - GF_UI_LOG_DEBUG("parent size width: {} height: {}", parent_size.width(), - parent_size.height()); - if (parent_pos != QPoint{0, 0}) { QPoint const parent_center{parent_pos.x() + parent_size.width() / 2, parent_pos.y() + parent_size.height() / 2}; @@ -106,8 +91,8 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept { } } - if (size_.width() < 640) size_.setWidth(640); - if (size_.height() < 480) size_.setHeight(480); + if (size_.width() < 800) size_.setWidth(800); + if (size_.height() < 600) size_.setHeight(600); this->move(pos_); this->resize(size_); @@ -127,13 +112,12 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept { icon_style_ = toolButtonStyle(); } catch (...) { - GF_UI_LOG_ERROR("general main window: {}, caught exception", name_); + qCWarning(ui) << "general main window: " << name_ << ", caught exception"; } } void GpgFrontend::UI::GeneralMainWindow::slot_save_settings() noexcept { try { - GF_UI_LOG_DEBUG("save main window state, name: {}", name_); SettingsObject general_windows_state(name_ + "_state"); // update geo of current dialog @@ -150,7 +134,7 @@ void GpgFrontend::UI::GeneralMainWindow::slot_save_settings() noexcept { general_windows_state.Store(window_state.Json()); } catch (...) { - GF_UI_LOG_ERROR("general main window: {}, caught exception", name_); + qCWarning(ui) << "general main window: " << name_ << ", caught exception"; } } @@ -158,11 +142,6 @@ void GeneralMainWindow::setPosCenterOfScreen() { // update cache update_rect_cache(); - int screen_width = screen_rect_.width(); - int screen_height = screen_rect_.height(); - GF_UI_LOG_DEBUG("dialog current screen available geometry", screen_width, - screen_height); - // update rect of current dialog rect_ = this->geometry(); this->move(screen_rect_.center() - @@ -173,16 +152,6 @@ void GeneralMainWindow::movePosition2CenterOfParent() { // update cache update_rect_cache(); - // log for debug - GF_UI_LOG_DEBUG("parent pos x: {} y: {}", parent_rect_.x(), parent_rect_.y()); - GF_UI_LOG_DEBUG("parent size width: {}, height: {}", parent_rect_.width(), - parent_rect_.height()); - GF_UI_LOG_DEBUG("parent center pos x: {}, y: {}", parent_rect_.center().x(), - parent_rect_.center().y()); - GF_UI_LOG_DEBUG("dialog pos x: {} y: {}", rect_.x(), rect_.y()); - GF_UI_LOG_DEBUG("dialog size width: {} height: {}", rect_.width(), - rect_.height()); - if (parent_rect_.topLeft() != QPoint{0, 0} && parent_rect_.size() != QSize{0, 0}) { if (rect_.width() <= 0) rect_.setWidth(100); @@ -191,10 +160,6 @@ void GeneralMainWindow::movePosition2CenterOfParent() { QPoint target_position = parent_rect_.center() - QPoint(rect_.width() / 2, rect_.height() / 2); - GF_UI_LOG_DEBUG( - "update position to parent's center, target pos, x:{}, y: {}", - target_position.x(), target_position.y()); - this->move(target_position); } else { setPosCenterOfScreen(); diff --git a/src/ui/main_window/KeyMgmt.cpp b/src/ui/main_window/KeyMgmt.cpp index afc6129c..09746140 100644 --- a/src/ui/main_window/KeyMgmt.cpp +++ b/src/ui/main_window/KeyMgmt.cpp @@ -52,55 +52,48 @@ namespace GpgFrontend::UI { KeyMgmt::KeyMgmt(QWidget* parent) : GeneralMainWindow("key_management", parent) { /* the list of Keys available*/ - key_list_ = new KeyList(KeyMenuAbility::ALL, this); + key_list_ = new KeyList(KeyMenuAbility::kALL, GpgKeyTableColumn::kALL, this); key_list_->AddListGroupTab(tr("All"), "all", - KeyListRow::SECRET_OR_PUBLIC_KEY); + GpgKeyTableDisplayMode::kPUBLIC_KEY | + GpgKeyTableDisplayMode::kPRIVATE_KEY); key_list_->AddListGroupTab( tr("Only Public Key"), "only_public_key", - KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + GpgKeyTableDisplayMode::kPUBLIC_KEY, [](const GpgKey& key) -> bool { return !key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); key_list_->AddListGroupTab( tr("Has Private Key"), "has_private_key", - KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + GpgKeyTableDisplayMode::kPRIVATE_KEY, [](const GpgKey& key) -> bool { return key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); key_list_->AddListGroupTab( - tr("No Primary Key"), "no_primary_key", KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + tr("No Primary Key"), "no_primary_key", + GpgKeyTableDisplayMode::kPUBLIC_KEY | + GpgKeyTableDisplayMode::kPRIVATE_KEY, + [](const GpgKey& key) -> bool { return !key.IsHasMasterKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); key_list_->AddListGroupTab( - tr("Revoked"), "revoked", KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { - return key.IsRevoked(); - }); + tr("Revoked"), "revoked", + GpgKeyTableDisplayMode::kPUBLIC_KEY | + GpgKeyTableDisplayMode::kPRIVATE_KEY, + + [](const GpgKey& key) -> bool { return key.IsRevoked(); }); key_list_->AddListGroupTab( - tr("Expired"), "expired", KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { - return key.IsExpired(); - }); + tr("Expired"), "expired", + GpgKeyTableDisplayMode::kPUBLIC_KEY | + GpgKeyTableDisplayMode::kPRIVATE_KEY, + + [](const GpgKey& key) -> bool { return key.IsExpired(); }); setCentralWidget(key_list_); key_list_->SetDoubleClickedAction( @@ -420,7 +413,7 @@ void KeyMgmt::SlotExportKeyToClipboard() { } if (data_obj == nullptr || !data_obj->Check<GFBuffer>()) { - GF_CORE_LOG_ERROR("data object checking failed"); + qCWarning(ui, "data object checking failed"); QMessageBox::critical(this, tr("Error"), tr("Unknown error occurred")); return; @@ -579,7 +572,6 @@ void KeyMgmt::SlotImportKeyPackage() { return; } - GF_UI_LOG_INFO("importing key package: {}", key_package_file_name); CommonUtils::WaitForOpera( this, tr("Importing"), [=](const OperaWaitingHd& op_hd) { KeyPackageOperator::ImportKeyPackage( diff --git a/src/ui/main_window/MainWindow.cpp b/src/ui/main_window/MainWindow.cpp index c50cfc5e..3106f226 100644 --- a/src/ui/main_window/MainWindow.cpp +++ b/src/ui/main_window/MainWindow.cpp @@ -43,12 +43,8 @@ namespace GpgFrontend::UI { MainWindow::MainWindow() : GeneralMainWindow("main_window") { - this->setMinimumSize(1200, 700); + this->setMinimumSize(1200, 870); this->setWindowTitle(qApp->applicationName()); - - connect(CoreSignalStation::GetInstance(), - &CoreSignalStation::SignalNeedUserInputPassphrase, this, - &MainWindow::SlotRaisePinentry); } void MainWindow::Init() noexcept { @@ -61,10 +57,14 @@ void MainWindow::Init() noexcept { setCentralWidget(edit_); /* the list of Keys available*/ - m_key_list_ = - new KeyList(KeyMenuAbility::REFRESH | KeyMenuAbility::UNCHECK_ALL | - KeyMenuAbility::SEARCH_BAR, - this); + m_key_list_ = new KeyList( + KeyMenuAbility::kREFRESH | KeyMenuAbility::kCHECK_ALL | + KeyMenuAbility::kUNCHECK_ALL | KeyMenuAbility::kCOLUMN_FILTER | + KeyMenuAbility::kSEARCH_BAR, + GpgKeyTableColumn::kTYPE | GpgKeyTableColumn::kNAME | + GpgKeyTableColumn::kKEY_ID | GpgKeyTableColumn::kEMAIL_ADDRESS | + GpgKeyTableColumn::kUSAGE | GpgKeyTableColumn::kOWNER_TRUST, + this); info_board_ = new InfoBoardWidget(this); @@ -132,9 +132,9 @@ void MainWindow::Init() noexcept { Module::ListenRTPublishEvent( this, kVersionCheckingModuleID, "version.loading_done", [=](Module::Namespace, Module::Key, int, std::any) { - GF_UI_LOG_DEBUG( - "version-checking version.loading_done changed, calling slot " - "version upgrade"); + qCDebug(ui, + "version-checking version.loading_done changed, calling slot " + "version upgrade"); this->slot_version_upgrade_notify(); }); @@ -151,7 +151,7 @@ void MainWindow::Init() noexcept { if (show_wizard) slot_start_wizard(); } catch (...) { - GF_UI_LOG_ERROR(tr("Critical error occur while loading GpgFrontend.")); + qCWarning(ui) << tr("Critical error occur while loading GpgFrontend."); QMessageBox::critical( nullptr, tr("Loading Failed"), tr("Critical error occur while loading GpgFrontend.")); @@ -161,8 +161,6 @@ void MainWindow::Init() noexcept { } void MainWindow::restore_settings() { - GF_UI_LOG_DEBUG("restore settings for main windows"); - KeyServerSO key_server(SettingsObject("key_server")); if (key_server.server_list.empty()) key_server.ResetDefaultServerList(); if (key_server.default_server < 0) key_server.default_server = 0; @@ -177,8 +175,6 @@ void MainWindow::restore_settings() { prohibit_update_checking_ = settings.value("network/prohibit_update_check").toBool(); - - GF_UI_LOG_DEBUG("settings restored"); } void MainWindow::recover_editor_unsaved_pages_from_cache() { @@ -189,9 +185,6 @@ void MainWindow::recover_editor_unsaved_pages_from_cache() { return; } - GF_UI_LOG_DEBUG("plan ot recover unsaved page from cache, page array: {}", - json_data.toJson()); - bool first = true; auto unsaved_page_array = json_data.array(); @@ -207,10 +200,6 @@ void MainWindow::recover_editor_unsaved_pages_from_cache() { auto title = unsaved_page_json["title"].toString(); auto content = unsaved_page_json["content"].toString(); - GF_UI_LOG_DEBUG( - "recovering unsaved page from cache, page title: {}, content size", - title, content.size()); - if (first) { edit_->SlotCloseTab(); first = false; diff --git a/src/ui/main_window/MainWindow.h b/src/ui/main_window/MainWindow.h index f53a4a03..b253a667 100644 --- a/src/ui/main_window/MainWindow.h +++ b/src/ui/main_window/MainWindow.h @@ -233,11 +233,6 @@ class MainWindow : public GeneralMainWindow { */ void SlotSetRestartNeeded(int); - /** - * @details Open a new tab for path - */ - void SlotRaisePinentry(QSharedPointer<GpgPassphraseContext>); - private slots: /** diff --git a/src/ui/main_window/MainWindowFileSlotFunction.cpp b/src/ui/main_window/MainWindowFileSlotFunction.cpp index bc3accfa..3d151ce6 100644 --- a/src/ui/main_window/MainWindowFileSlotFunction.cpp +++ b/src/ui/main_window/MainWindowFileSlotFunction.cpp @@ -282,7 +282,6 @@ void MainWindow::SlotFileDecrypt(const QString& path) { } auto out_path = SetExtensionOfOutputFile(path, kDECRYPT, true); - GF_UI_LOG_DEBUG("file decrypt target output path: {}", out_path); if (QFileInfo(out_path).exists()) { auto ret = QMessageBox::warning( this, tr("Warning"), @@ -332,7 +331,6 @@ void MainWindow::SlotArchiveDecrypt(const QString& path) { } auto out_path = SetExtensionOfOutputFileForArchive(path, kDECRYPT, true); - GF_UI_LOG_DEBUG("archive decrypt target output path: {}", out_path); if (QFileInfo(out_path).exists()) { auto ret = QMessageBox::warning( this, tr("Warning"), @@ -493,9 +491,6 @@ void MainWindow::SlotFileVerify(const QString& path) { return; } - GF_UI_LOG_DEBUG("verification data file path: {}", data_file_path); - GF_UI_LOG_DEBUG("verification signature file path: {}", sign_file_path); - CommonUtils::WaitForOpera( this, tr("Verifying"), [=](const OperaWaitingHd& op_hd) { GpgFileOpera::GetInstance().VerifyFile( @@ -817,7 +812,6 @@ void MainWindow::SlotArchiveDecryptVerify(const QString& path) { auto out_path = SetExtensionOfOutputFileForArchive(path, kDECRYPT_VERIFY, true); - GF_UI_LOG_INFO("out_path: {}", out_path); check_result = TargetFilePreCheck(out_path, false); if (!std::get<0>(check_result)) { QMessageBox::critical(this, tr("Error"), diff --git a/src/ui/main_window/MainWindowGpgOperaFunction.cpp b/src/ui/main_window/MainWindowGpgOperaFunction.cpp index 3cef497d..d197e336 100644 --- a/src/ui/main_window/MainWindowGpgOperaFunction.cpp +++ b/src/ui/main_window/MainWindowGpgOperaFunction.cpp @@ -295,14 +295,6 @@ void MainWindow::SlotEncryptSign() { auto signer_key_ids = signers_picker->GetCheckedSigners(); auto signer_keys = GpgKeyGetter::GetInstance().GetKeys(signer_key_ids); - for (const auto& key : *keys) { - GF_UI_LOG_DEBUG("keys {}", key.GetEmail()); - } - - for (const auto& signer : *signer_keys) { - GF_UI_LOG_DEBUG("signers {}", signer.GetEmail()); - } - // data to transfer into task auto buffer = GFBuffer(edit_->CurTextPage()->GetTextPage()->toPlainText()); diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp index 7d50b85a..f1754be7 100644 --- a/src/ui/main_window/MainWindowSlotFunction.cpp +++ b/src/ui/main_window/MainWindowSlotFunction.cpp @@ -63,14 +63,14 @@ void MainWindow::slot_append_selected_keys() { auto key_ids = m_key_list_->GetSelected(); if (key_ids->empty()) { - GF_UI_LOG_ERROR("no key is selected to export"); + qCWarning(ui, "no key is selected to export"); return; } auto key = GpgKeyGetter::GetInstance().GetKey(key_ids->front()); if (!key.IsGood()) { - GF_UI_LOG_ERROR("selected key for exporting is invalid, key id: {}", - key_ids->front()); + qCWarning(ui) << "selected key for exporting is invalid, key id: " + << key_ids->front(); return; } @@ -88,7 +88,7 @@ void MainWindow::slot_append_keys_create_datetime() { auto key_ids = m_key_list_->GetSelected(); if (key_ids->empty()) { - GF_UI_LOG_ERROR("no key is selected"); + qCWarning(ui, "no key is selected"); return; } @@ -112,7 +112,7 @@ void MainWindow::slot_append_keys_expire_datetime() { auto key_ids = m_key_list_->GetSelected(); if (key_ids->empty()) { - GF_UI_LOG_ERROR("no key is selected"); + qCWarning(ui, "no key is selected"); return; } @@ -204,8 +204,9 @@ void MainWindow::slot_add_key_2_favourite() { if (key_ids->empty()) return; auto key = GpgKeyGetter::GetInstance().GetKey(key_ids->front()); - CommonUtils::GetInstance()->AddKey2Favourtie(key); + if (!key.IsGood()) return; + CommonUtils::GetInstance()->AddKey2Favourtie(key); emit SignalUIRefresh(); } @@ -263,15 +264,14 @@ void MainWindow::SlotOpenFile(const QString& path) { } void MainWindow::slot_version_upgrade_notify() { - GF_UI_LOG_DEBUG( + qCDebug( + ui, "slot version upgrade notify called, checking version info from rt..."); + auto is_loading_done = Module::RetrieveRTValueTypedOrDefault<>( kVersionCheckingModuleID, "version.loading_done", false); - - GF_UI_LOG_DEBUG("checking version info from rt, is loading done state: {}", - is_loading_done); if (!is_loading_done) { - GF_UI_LOG_ERROR("invalid version info from rt, loading hasn't done yet"); + qCWarning(ui, "invalid version info from rt, loading hasn't done yet"); return; } @@ -287,12 +287,6 @@ void MainWindow::slot_version_upgrade_notify() { auto latest_version = Module::RetrieveRTValueTypedOrDefault<>( kVersionCheckingModuleID, "version.latest_version", QString{}); - GF_UI_LOG_DEBUG( - "got version info from rt, need upgrade: {}, with drawn: {}, " - "current version released: {}", - is_need_upgrade, is_current_a_withdrawn_version, - is_current_version_released); - if (is_need_upgrade) { statusBar()->showMessage( tr("GpgFrontend Upgradeable (New Version: %1).").arg(latest_version), diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp index 39ceedc6..1fc4eb5c 100644 --- a/src/ui/main_window/MainWindowSlotUI.cpp +++ b/src/ui/main_window/MainWindowSlotUI.cpp @@ -33,7 +33,6 @@ #include "core/model/SettingsObject.h" #include "ui/UserInterfaceUtils.h" #include "ui/dialog/Wizard.h" -#include "ui/function/RaisePinentry.h" #include "ui/main_window/KeyMgmt.h" #include "ui/struct/settings_object/AppearanceSO.h" #include "ui/widgets/TextEdit.h" @@ -53,7 +52,7 @@ void MainWindow::slot_start_wizard() { void MainWindow::slot_import_key_from_edit() { if (edit_->TabCount() == 0 || edit_->SlotCurPageTextEdit() == nullptr) return; CommonUtils::GetInstance()->SlotImportKeys( - this, edit_->CurTextPage()->GetTextPage()->toPlainText()); + this, edit_->CurTextPage()->GetTextPage()->toPlainText().toLatin1()); } void MainWindow::slot_open_key_management() { @@ -98,7 +97,6 @@ void MainWindow::slot_disable_tab_actions(int number) { add_pgp_header_act_->setDisabled(disable); if (edit_->CurFilePage() != nullptr) { - GF_UI_LOG_DEBUG("edit current page is file page"); auto* file_page = edit_->CurFilePage(); emit file_page->SignalCurrentTabChanged(); } @@ -109,9 +107,6 @@ void MainWindow::slot_open_settings_dialog() { connect(dialog, &SettingsDialog::finished, this, [&]() -> void { AppearanceSO appearance(SettingsObject("general_settings_state")); - GF_UI_LOG_DEBUG("tool bar icon_size: {}, {}", - appearance.tool_bar_icon_width, - appearance.tool_bar_icon_height); this->setToolButtonStyle(appearance.tool_bar_button_style); import_button_->setToolButtonStyle(appearance.tool_bar_button_style); @@ -182,14 +177,10 @@ void MainWindow::slot_cut_pgp_header() { edit_->SlotFillTextEditWithText(content.trimmed()); } -void MainWindow::SlotSetRestartNeeded(int mode) { - GF_UI_LOG_DEBUG("restart mode: {}", mode); - this->restart_mode_ = mode; -} +void MainWindow::SlotSetRestartNeeded(int mode) { this->restart_mode_ = mode; } void MainWindow::SlotUpdateCryptoMenuStatus(unsigned int type) { MainWindow::CryptoMenu::OperationType opera_type = type; - GF_UI_LOG_DEBUG("update crypto menu status, type: {}", opera_type); // refresh status to disable all verify_act_->setDisabled(true); @@ -220,10 +211,4 @@ void MainWindow::SlotUpdateCryptoMenuStatus(unsigned int type) { } } -void MainWindow::SlotRaisePinentry( - QSharedPointer<GpgPassphraseContext> context) { - auto* function = new RaisePinentry(this, context); - function->Exec(); -} - } // namespace GpgFrontend::UI diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp index 8b611152..c1189fa2 100644 --- a/src/ui/main_window/MainWindowUI.cpp +++ b/src/ui/main_window/MainWindowUI.cpp @@ -707,37 +707,32 @@ void MainWindow::create_dock_windows() { addDockWidget(Qt::RightDockWidgetArea, key_list_dock_); m_key_list_->AddListGroupTab( - tr("Default"), "default", KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + tr("Default"), "default", + GpgKeyTableDisplayMode::kPUBLIC_KEY | + GpgKeyTableDisplayMode::kPRIVATE_KEY, + [](const GpgKey& key) -> bool { return !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); m_key_list_->AddListGroupTab( - tr("Favourite"), "favourite", KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + tr("Favourite"), "favourite", + GpgKeyTableDisplayMode::kPUBLIC_KEY | + GpgKeyTableDisplayMode::kPRIVATE_KEY | + GpgKeyTableDisplayMode::kFAVORITES, + [](const GpgKey& key) -> bool { return CommonUtils::GetInstance()->KeyExistsinFavouriteList(key); }); m_key_list_->AddListGroupTab( tr("Only Public Key"), "only_public_key", - KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + GpgKeyTableDisplayMode::kPUBLIC_KEY, [](const GpgKey& key) -> bool { return !key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); m_key_list_->AddListGroupTab( tr("Has Private Key"), "has_private_key", - KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + GpgKeyTableDisplayMode::kPRIVATE_KEY, [](const GpgKey& key) -> bool { return key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); diff --git a/src/module/mods/ver_check/VersionCheckingModule.h b/src/ui/struct/UIMountPoint.h index 35ee4ac3..61ac83c6 100644 --- a/src/module/mods/ver_check/VersionCheckingModule.h +++ b/src/ui/struct/UIMountPoint.h @@ -28,29 +28,31 @@ #pragma once -#include <GFSDKModule.h> - -#include "GFModuleExport.h" - -extern "C" { - -auto GF_MODULE_EXPORT GFGetModuleGFSDKVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleQtEnvVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleID() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleVersion() -> const char *; - -auto GF_MODULE_EXPORT GFGetModuleMetaData() -> GFModuleMetaData *; - -auto GF_MODULE_EXPORT GFRegisterModule() -> int; - -auto GF_MODULE_EXPORT GFActiveModule() -> int; - -auto GF_MODULE_EXPORT GFExecuteModule(GFModuleEvent *) -> int; - -auto GF_MODULE_EXPORT GFDeactiveModule() -> int; - -auto GF_MODULE_EXPORT GFUnregisterModule() -> int; -}; +struct UIMountPoint { + QString id; + QString entry_type; + QMap<QString, QVariant> meta_data_desc; + + UIMountPoint() = default; + + explicit UIMountPoint(const QJsonObject& j) { + if (const auto v = j["id"]; v.isDouble()) { + id = v.toString(); + } + if (const auto v = j["entry_type"]; v.isDouble()) { + entry_type = v.toString(); + } + if (const auto v = j["meta_data_desc"]; v.isDouble()) { + meta_data_desc = v.toVariant().toMap(); + } + } + + [[nodiscard]] auto ToJson() const -> QJsonObject { + QJsonObject j; + j["id"] = id; + j["entry_type"] = entry_type; + j["meta_data_desc"] = QJsonObject::fromVariantMap(meta_data_desc); + + return j; + } +};
\ No newline at end of file diff --git a/src/ui/thread/KeyServerImportTask.cpp b/src/ui/thread/KeyServerImportTask.cpp index 8bcb2eab..e3662db2 100644 --- a/src/ui/thread/KeyServerImportTask.cpp +++ b/src/ui/thread/KeyServerImportTask.cpp @@ -44,8 +44,6 @@ GpgFrontend::UI::KeyServerImportTask::KeyServerImportTask( if (keyserver_url_.isEmpty()) { KeyServerSO key_server(SettingsObject("general_settings_state")); keyserver_url_ = key_server.GetTargetServer(); - GF_UI_LOG_DEBUG("key server import task sets key server url: {}", - keyserver_url_); } } @@ -71,8 +69,9 @@ void GpgFrontend::UI::KeyServerImportTask::dealing_reply_from_server() { auto buffer = reply_->readAll(); if (network_reply != QNetworkReply::NoError) { - GF_UI_LOG_ERROR("key import error, message from key server reply: ", - buffer); + qCWarning(ui) << "key import error, message from key server reply: " + << buffer; + QString err_msg; switch (network_reply) { case QNetworkReply::ContentNotFoundError: diff --git a/src/ui/thread/ListedKeyServerTestTask.cpp b/src/ui/thread/ListedKeyServerTestTask.cpp index 5f7e2dca..1d492735 100644 --- a/src/ui/thread/ListedKeyServerTestTask.cpp +++ b/src/ui/thread/ListedKeyServerTestTask.cpp @@ -48,7 +48,6 @@ auto GpgFrontend::UI::ListedKeyServerTestTask::Run() -> int { size_t index = 0; for (const auto& url : urls_) { auto key_url = QUrl{url}; - GF_UI_LOG_DEBUG("key server request: {}", key_url.host()); auto request = QNetworkRequest(key_url); request.setHeader(QNetworkRequest::UserAgentHeader, @@ -59,12 +58,10 @@ auto GpgFrontend::UI::ListedKeyServerTestTask::Run() -> int { connect(network_reply, &QNetworkReply::finished, this, [this, index, network_reply]() { - GF_UI_LOG_DEBUG("key server domain reply: {}", urls_[index]); this->slot_process_network_reply(index, network_reply); }); connect(timer, &QTimer::timeout, this, [this, index, network_reply]() { - GF_UI_LOG_DEBUG("timeout for key server: {}", urls_[index]); if (network_reply->isRunning()) { network_reply->abort(); this->slot_process_network_reply(index, network_reply); diff --git a/src/ui/thread/ProxyConnectionTestTask.cpp b/src/ui/thread/ProxyConnectionTestTask.cpp index c1d2f3e6..7d2c496f 100644 --- a/src/ui/thread/ProxyConnectionTestTask.cpp +++ b/src/ui/thread/ProxyConnectionTestTask.cpp @@ -51,12 +51,10 @@ auto GpgFrontend::UI::ProxyConnectionTestTask::Run() -> int { connect(network_reply, &QNetworkReply::finished, this, [this, network_reply]() { - GF_UI_LOG_DEBUG("key server domain reply: {} received", url_); this->slot_process_network_reply(network_reply); }); connect(timer, &QTimer::timeout, this, [this, network_reply]() { - GF_UI_LOG_DEBUG("timeout for key server: {}", url_); if (network_reply->isRunning()) { network_reply->abort(); this->slot_process_network_reply(network_reply); @@ -70,8 +68,6 @@ auto GpgFrontend::UI::ProxyConnectionTestTask::Run() -> int { void GpgFrontend::UI::ProxyConnectionTestTask::slot_process_network_reply( QNetworkReply* reply) { auto buffer = reply->readAll(); - GF_UI_LOG_DEBUG("key server domain reply: {}, buffer size: {}", url_, - buffer.size()); if (reply->error() == QNetworkReply::NoError && !buffer.isEmpty()) { result_ = "Reachable"; diff --git a/src/ui/widgets/FilePage.cpp b/src/ui/widgets/FilePage.cpp index d99bfc53..f44aa12b 100644 --- a/src/ui/widgets/FilePage.cpp +++ b/src/ui/widgets/FilePage.cpp @@ -117,7 +117,6 @@ void FilePage::SlotGoPath() { } void FilePage::keyPressEvent(QKeyEvent* event) { - GF_UI_LOG_DEBUG("file page notices key press by user: {}", event->key()); if (ui_->pathEdit->hasFocus() && (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)) { SlotGoPath(); diff --git a/src/ui/widgets/FileTreeView.cpp b/src/ui/widgets/FileTreeView.cpp index de22ec83..b9ffbd27 100644 --- a/src/ui/widgets/FileTreeView.cpp +++ b/src/ui/widgets/FileTreeView.cpp @@ -63,12 +63,9 @@ FileTreeView::FileTreeView(QWidget* parent, const QString& target_path) void FileTreeView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { QTreeView::selectionChanged(selected, deselected); - GF_UI_LOG_DEBUG( - "file tree view selected changed, selected: {}, deselected: {}", - selected.size(), deselected.size()); + if (!selected.indexes().empty()) { selected_path_ = dir_model_->filePath(selected.indexes().first()); - GF_UI_LOG_DEBUG("file tree view selected target path: {}", selected_path_); emit SignalSelectedChanged(selected_path_); } else { selected_path_ = QString(); @@ -83,7 +80,6 @@ void FileTreeView::SlotGoPath(const QString& target_path) { auto file_info = QFileInfo(target_path); if (file_info.isDir() && file_info.isReadable() && file_info.isExecutable()) { current_path_ = file_info.absoluteFilePath(); - GF_UI_LOG_DEBUG("file tree view set target path: {}", current_path_); this->setRootIndex(dir_model_->index(file_info.filePath())); dir_model_->setRootPath(file_info.filePath()); slot_adjust_column_widths(); @@ -116,7 +112,6 @@ void FileTreeView::SlotUpLevel() { auto target_path = dir_model_->fileInfo(current_root).absoluteFilePath(); if (auto parent_path = QDir(target_path); parent_path.cdUp()) { target_path = parent_path.absolutePath(); - GF_UI_LOG_DEBUG("file tree view go parent path: {}", target_path); this->SlotGoPath(target_path); } current_path_ = target_path; @@ -145,9 +140,7 @@ auto FileTreeView::GetPathByClickPoint(const QPoint& point) -> QString { return {}; } - auto index_path = dir_model_->fileInfo(index).absoluteFilePath(); - GF_UI_LOG_DEBUG("file tree view right click on: {}", index_path); - return index_path; + return dir_model_->fileInfo(index).absoluteFilePath(); } auto FileTreeView::GetSelectedPath() -> QString { return selected_path_; } @@ -162,8 +155,6 @@ auto FileTreeView::SlotDeleteSelectedItem() -> void { if (ret == QMessageBox::Cancel) return; - GF_UI_LOG_DEBUG("delete item: {}", data.toString()); - if (!dir_model_->remove(index)) { QMessageBox::critical(this, tr("Error"), tr("Unable to delete the file or folder.")); @@ -207,7 +198,6 @@ void FileTreeView::SlotTouch() { QLineEdit::Normal, new_file_name, &ok); if (ok && !new_file_name.isEmpty()) { auto file_path = root_path + "/" + new_file_name; - GF_UI_LOG_DEBUG("new file path: {}", file_path); QFile new_file(file_path); if (!new_file.open(QIODevice::WriteOnly | QIODevice::NewOnly)) { @@ -229,7 +219,6 @@ void FileTreeView::SlotTouchBelowAtSelectedItem() { QLineEdit::Normal, new_file_name, &ok); if (ok && !new_file_name.isEmpty()) { auto file_path = root_path + "/" + new_file_name; - GF_UI_LOG_DEBUG("new file path: {}", file_path); QFile new_file(file_path); if (!new_file.open(QIODevice::WriteOnly | QIODevice::NewOnly)) { @@ -272,7 +261,7 @@ void FileTreeView::SlotRenameSelectedItem() { if (ok && !text.isEmpty()) { auto file_info = QFileInfo(selected_path_); auto new_name_path = file_info.absolutePath() + "/" + text; - GF_UI_LOG_DEBUG("new filename path: {}", new_name_path); + if (!QDir().rename(file_info.absoluteFilePath(), new_name_path)) { QMessageBox::critical(this, tr("Error"), tr("Unable to rename the file or folder.")); @@ -355,8 +344,6 @@ void FileTreeView::slot_show_custom_context_menu(const QPoint& point) { auto target_path = this->GetPathByClickPoint(point); auto select_path = GetSelectedPath(); - GF_UI_LOG_DEBUG("file tree view, target path: {}, select path: {}", - target_path, select_path); if (target_path.isEmpty() && !select_path.isEmpty()) { target_path = select_path; } @@ -404,8 +391,9 @@ void FileTreeView::slot_calculate_hash() { return; } auto result = ExtractParams<QString>(data_object, 0); - emit UISignalStation::GetInstance()->SignalRefreshInfoBoard( - result, InfoBoardStatus::INFO_ERROR_OK); + emit UISignalStation::GetInstance() + -> SignalRefreshInfoBoard(result, + InfoBoardStatus::INFO_ERROR_OK); }, "calculate_file_hash"); }); diff --git a/src/ui/widgets/GRTTreeView.cpp b/src/ui/widgets/GRTTreeView.cpp index 09d7dcf0..b52f6881 100644 --- a/src/ui/widgets/GRTTreeView.cpp +++ b/src/ui/widgets/GRTTreeView.cpp @@ -35,7 +35,7 @@ namespace GpgFrontend::UI { GRTTreeView::GRTTreeView(QWidget* parent) : QTreeView(parent) { setModel(new Module::GlobalRegisterTableTreeModel( - Module::ModuleManager::GetInstance().GRT())); + Module::ModuleManager::GetInstance().GRT(), this)); connect(model(), &QFileSystemModel::layoutChanged, this, &GRTTreeView::slot_adjust_column_widths); diff --git a/src/ui/widgets/HelpPage.cpp b/src/ui/widgets/HelpPage.cpp index 78169944..cf56564c 100644 --- a/src/ui/widgets/HelpPage.cpp +++ b/src/ui/widgets/HelpPage.cpp @@ -28,6 +28,8 @@ #include "ui/widgets/HelpPage.h" +#include "core/function/GlobalSettingStation.h" + namespace GpgFrontend::UI { HelpPage::HelpPage(const QString& path, QWidget* parent) : QWidget(parent) { @@ -64,7 +66,10 @@ auto HelpPage::localized_help(const QUrl& url) -> QUrl { QStringList fileparts = filename.split("."); // QSettings settings; - QString lang = QSettings().value("int/lang", QLocale().name()).toString(); + QString lang = GlobalSettingStation::GetInstance() + .GetSettings() + .value("int/lang", QLocale().name()) + .toString(); if (lang.isEmpty()) { lang = QLocale().name(); } diff --git a/src/ui/widgets/InfoBoardWidget.cpp b/src/ui/widgets/InfoBoardWidget.cpp index 425e6ccd..10b8ad83 100644 --- a/src/ui/widgets/InfoBoardWidget.cpp +++ b/src/ui/widgets/InfoBoardWidget.cpp @@ -115,7 +115,6 @@ void InfoBoardWidget::AssociateTabWidget(QTabWidget* tab) { void InfoBoardWidget::AddOptionalAction(const QString& name, const std::function<void()>& action) { - GF_UI_LOG_DEBUG("add option action: {}", name); auto* action_button = new QPushButton(name); auto* layout = new QHBoxLayout(); layout->setContentsMargins(5, 0, 5, 0); @@ -165,7 +164,6 @@ void InfoBoardWidget::slot_copy() { void InfoBoardWidget::slot_save() { auto file_path = QFileDialog::getSaveFileName( this, tr("Save Information Board's Content"), {}, tr("Text (*.txt)")); - GF_UI_LOG_DEBUG("file path: {}", file_path); if (file_path.isEmpty()) return; QFile file(file_path); diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp index be79a6fd..6ddf62a3 100644 --- a/src/ui/widgets/KeyList.cpp +++ b/src/ui/widgets/KeyList.cpp @@ -29,7 +29,7 @@ #include "ui/widgets/KeyList.h" #include <cstddef> -#include <mutex> +#include <utility> #include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgKeyGetter.h" @@ -40,27 +40,143 @@ namespace GpgFrontend::UI { -KeyList::KeyList(KeyMenuAbility::AbilityType menu_ability, QWidget* parent) +KeyList::KeyList(KeyMenuAbility menu_ability, + GpgKeyTableColumn fixed_columns_filter, QWidget* parent) : QWidget(parent), ui_(GpgFrontend::SecureCreateSharedObject<Ui_KeyList>()), - menu_ability_(menu_ability) { + menu_ability_(menu_ability), + model_(GpgKeyGetter::GetInstance().GetGpgKeyTableModel()), + fixed_columns_filter_(fixed_columns_filter), + global_column_filter_(static_cast<GpgKeyTableColumn>( + GlobalSettingStation::GetInstance() + .GetSettings() + .value("keys/global_columns_filter", + static_cast<unsigned int>(GpgKeyTableColumn::kALL)) + .toUInt())) { init(); } void KeyList::init() { ui_->setupUi(this); - ui_->menuWidget->setHidden(menu_ability_ == 0U); + ui_->menuWidget->setHidden(menu_ability_ == KeyMenuAbility::kNONE); ui_->refreshKeyListButton->setHidden(~menu_ability_ & - KeyMenuAbility::REFRESH); - ui_->syncButton->setHidden(~menu_ability_ & KeyMenuAbility::SYNC_PUBLIC_KEY); - ui_->uncheckButton->setHidden(~menu_ability_ & KeyMenuAbility::UNCHECK_ALL); - ui_->searchBarEdit->setHidden(~menu_ability_ & KeyMenuAbility::SEARCH_BAR); + KeyMenuAbility::kREFRESH); + ui_->syncButton->setHidden(~menu_ability_ & KeyMenuAbility::kSYNC_PUBLIC_KEY); + ui_->checkALLButton->setHidden(~menu_ability_ & KeyMenuAbility::kCHECK_ALL); + ui_->uncheckButton->setHidden(~menu_ability_ & KeyMenuAbility::kUNCHECK_ALL); + ui_->columnTypeButton->setHidden(~menu_ability_ & + KeyMenuAbility::kCOLUMN_FILTER); + ui_->searchBarEdit->setHidden(~menu_ability_ & KeyMenuAbility::kSEARCH_BAR); + + auto* column_type_menu = new QMenu(this); + + key_id_column_action_ = new QAction(tr("Key ID"), this); + key_id_column_action_->setCheckable(true); + key_id_column_action_->setChecked( + (global_column_filter_ & GpgKeyTableColumn::kKEY_ID) != + GpgKeyTableColumn::kNONE); + connect(key_id_column_action_, &QAction::toggled, this, [=](bool checked) { + UpdateKeyTableColumnType( + checked ? global_column_filter_ | GpgKeyTableColumn::kKEY_ID + : global_column_filter_ & ~GpgKeyTableColumn::kKEY_ID); + }); + + algo_column_action_ = new QAction(tr("Algorithm"), this); + algo_column_action_->setCheckable(true); + algo_column_action_->setChecked( + (global_column_filter_ & GpgKeyTableColumn::kALGO) != + GpgKeyTableColumn::kNONE); + connect(algo_column_action_, &QAction::toggled, this, [=](bool checked) { + UpdateKeyTableColumnType( + checked ? global_column_filter_ | GpgKeyTableColumn::kALGO + : global_column_filter_ & ~GpgKeyTableColumn::kALGO); + }); + + owner_trust_column_action_ = new QAction(tr("Owner Trust"), this); + owner_trust_column_action_->setCheckable(true); + owner_trust_column_action_->setChecked( + (global_column_filter_ & GpgKeyTableColumn::kOWNER_TRUST) != + GpgKeyTableColumn::kNONE); + connect( + owner_trust_column_action_, &QAction::toggled, this, [=](bool checked) { + UpdateKeyTableColumnType( + checked ? global_column_filter_ | GpgKeyTableColumn::kOWNER_TRUST + : global_column_filter_ & ~GpgKeyTableColumn::kOWNER_TRUST); + }); + + create_date_column_action_ = new QAction(tr("Create Date"), this); + create_date_column_action_->setCheckable(true); + create_date_column_action_->setChecked( + (global_column_filter_ & GpgKeyTableColumn::kCREATE_DATE) != + GpgKeyTableColumn::kNONE); + connect( + create_date_column_action_, &QAction::toggled, this, [=](bool checked) { + UpdateKeyTableColumnType( + checked ? global_column_filter_ | GpgKeyTableColumn::kCREATE_DATE + : global_column_filter_ & ~GpgKeyTableColumn::kCREATE_DATE); + }); + + subkeys_number_column_action_ = new QAction("Subkey(s)", this); + subkeys_number_column_action_->setCheckable(true); + subkeys_number_column_action_->setChecked( + (global_column_filter_ & GpgKeyTableColumn::kSUBKEYS_NUMBER) != + GpgKeyTableColumn::kNONE); + connect( + subkeys_number_column_action_, &QAction::toggled, this, + [=](bool checked) { + UpdateKeyTableColumnType( + checked + ? global_column_filter_ | GpgKeyTableColumn::kSUBKEYS_NUMBER + : global_column_filter_ & ~GpgKeyTableColumn::kSUBKEYS_NUMBER); + }); + + comment_column_action_ = new QAction("Comment", this); + comment_column_action_->setCheckable(true); + comment_column_action_->setChecked( + (global_column_filter_ & GpgKeyTableColumn::kCOMMENT) != + GpgKeyTableColumn::kNONE); + connect(comment_column_action_, &QAction::toggled, this, [=](bool checked) { + UpdateKeyTableColumnType( + checked ? global_column_filter_ | GpgKeyTableColumn::kCOMMENT + : global_column_filter_ & ~GpgKeyTableColumn::kCOMMENT); + }); + + if ((fixed_columns_filter_ & GpgKeyTableColumn::kKEY_ID) != + GpgKeyTableColumn::kNONE) { + column_type_menu->addAction(key_id_column_action_); + } + + if ((fixed_columns_filter_ & GpgKeyTableColumn::kALGO) != + GpgKeyTableColumn::kNONE) { + column_type_menu->addAction(algo_column_action_); + } + if ((fixed_columns_filter_ & GpgKeyTableColumn::kCREATE_DATE) != + GpgKeyTableColumn::kNONE) { + column_type_menu->addAction(create_date_column_action_); + } + + if ((fixed_columns_filter_ & GpgKeyTableColumn::kOWNER_TRUST) != + GpgKeyTableColumn::kNONE) { + column_type_menu->addAction(owner_trust_column_action_); + } + + if ((fixed_columns_filter_ & GpgKeyTableColumn::kSUBKEYS_NUMBER) != + GpgKeyTableColumn::kNONE) { + column_type_menu->addAction(subkeys_number_column_action_); + } + + if ((fixed_columns_filter_ & GpgKeyTableColumn::kCOMMENT) != + GpgKeyTableColumn::kNONE) { + column_type_menu->addAction(comment_column_action_); + } + + ui_->columnTypeButton->setMenu(column_type_menu); ui_->keyGroupTab->clear(); popup_menu_ = new QMenu(this); - bool forbid_all_gnupg_connection = + auto forbid_all_gnupg_connection = GlobalSettingStation::GetInstance() .GetSettings() .value("network/forbid_all_gnupg_connection", false) @@ -93,6 +209,11 @@ void KeyList::init() { connect(this, &KeyList::SignalRefreshStatusBar, UISignalStation::GetInstance(), &UISignalStation::SignalRefreshStatusBar); + connect(this, &KeyList::SignalColumnTypeChange, this, [=]() { + GlobalSettingStation::GetInstance().GetSettings().setValue( + "keys/global_columns_filter", + static_cast<unsigned int>(global_column_filter_)); + }); setAcceptDrops(true); @@ -112,120 +233,72 @@ void KeyList::init() { } void KeyList::AddListGroupTab(const QString& name, const QString& id, - KeyListRow::KeyType selectType, - KeyListColumn::InfoType infoType, - const KeyTable::KeyTableFilter filter) { - GF_UI_LOG_DEBUG("add list group tab: {}", name); - - auto* key_list = new QTableWidget(this); - if (m_key_list_ == nullptr) { - m_key_list_ = key_list; - } - key_list->setObjectName(id); - ui_->keyGroupTab->addTab(key_list, name); - m_key_tables_.emplace_back(key_list, selectType, infoType, filter); - m_key_tables_.back().SetMenuAbility(menu_ability_); - - key_list->setColumnCount(8); - key_list->horizontalHeader()->setSectionResizeMode( - QHeaderView::ResizeToContents); - key_list->verticalHeader()->hide(); - key_list->setShowGrid(false); - key_list->sortByColumn(2, Qt::AscendingOrder); - key_list->setSelectionBehavior(QAbstractItemView::SelectRows); - key_list->setSelectionMode(QAbstractItemView::SingleSelection); - - // table items not editable - key_list->setEditTriggers(QAbstractItemView::NoEditTriggers); - // no focus (rectangle around table items) - // maybe it should focus on whole row - key_list->setFocusPolicy(Qt::NoFocus); - - key_list->setAlternatingRowColors(true); - - // Hidden Column For Purpose - if ((infoType & KeyListColumn::TYPE) == 0U) { - key_list->setColumnHidden(1, true); - } - if ((infoType & KeyListColumn::NAME) == 0U) { - key_list->setColumnHidden(2, true); - } - if ((infoType & KeyListColumn::EmailAddress) == 0U) { - key_list->setColumnHidden(3, true); - } - if ((infoType & KeyListColumn::Usage) == 0U) { - key_list->setColumnHidden(4, true); - } - if ((infoType & KeyListColumn::Validity) == 0U) { - key_list->setColumnHidden(5, true); - } - if ((infoType & KeyListColumn::KeyID) == 0U) { - key_list->setColumnHidden(6, true); - } - if ((infoType & KeyListColumn::FingerPrint) == 0U) { - key_list->setColumnHidden(7, true); - } + GpgKeyTableDisplayMode display_mode, + GpgKeyTableProxyModel::KeyFilter search_filter, + GpgKeyTableColumn custom_columns_filter) { + auto* key_table = + new KeyTable(this, model_, display_mode, custom_columns_filter, + std::move(search_filter)); - QStringList labels; - labels << tr("Select") << tr("Type") << tr("Name") << tr("Email Address") - << tr("Usage") << tr("Trust") << tr("Key ID") << tr("Finger Print"); + key_table->setObjectName(id); + ui_->keyGroupTab->addTab(key_table, name); - key_list->setHorizontalHeaderLabels(labels); - key_list->horizontalHeader()->setStretchLastSection(false); + connect(this, &KeyList::SignalColumnTypeChange, key_table, + &KeyTable::SignalColumnTypeChange); - connect(key_list, &QTableWidget::doubleClicked, this, - &KeyList::slot_double_clicked); + UpdateKeyTableColumnType(global_column_filter_); } void KeyList::SlotRefresh() { - GF_UI_LOG_DEBUG("refresh, address: {}", static_cast<void*>(this)); - ui_->refreshKeyListButton->setDisabled(true); ui_->syncButton->setDisabled(true); + model_ = GpgKeyGetter::GetInstance().GetGpgKeyTableModel(); + + for (int i = 0; i < ui_->keyGroupTab->count(); i++) { + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->widget(i)); + key_table->RefreshModel(model_); + } + emit SignalRefreshStatusBar(tr("Refreshing Key List..."), 3000); - this->buffered_keys_list_ = GpgKeyGetter::GetInstance().FetchKey(); - this->slot_refresh_ui(); + this->model_ = GpgKeyGetter::GetInstance().GetGpgKeyTableModel(); + + this->SlotRefreshUI(); } void KeyList::SlotRefreshUI() { - GF_UI_LOG_DEBUG("refresh, address: {}", static_cast<void*>(this)); - this->slot_refresh_ui(); + emit SignalRefreshStatusBar(tr("Key List Refreshed."), 1000); + ui_->refreshKeyListButton->setDisabled(false); + ui_->syncButton->setDisabled(false); } auto KeyList::GetChecked(const KeyTable& key_table) -> KeyIdArgsListPtr { auto ret = std::make_unique<KeyIdArgsList>(); - for (int i = 0; i < key_table.key_list_->rowCount(); i++) { - if (key_table.key_list_->item(i, 0)->checkState() == Qt::Checked) { - ret->push_back(key_table.buffered_keys_[i].GetId()); + for (int i = 0; i < key_table.GetRowCount(); i++) { + if (key_table.IsRowChecked(i)) { + ret->push_back(key_table.GetKeyIdByRow(i)); } } return ret; } auto KeyList::GetChecked() -> KeyIdArgsListPtr { - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); auto ret = std::make_unique<KeyIdArgsList>(); - for (int i = 0; i < key_list->rowCount(); i++) { - if (key_list->item(i, 0)->checkState() == Qt::Checked) { - ret->push_back(buffered_keys[i].GetId()); + for (int i = 0; i < key_table->GetRowCount(); i++) { + if (key_table->IsRowChecked(i)) { + ret->push_back(key_table->GetKeyIdByRow(i)); } } return ret; } auto KeyList::GetAllPrivateKeys() -> KeyIdArgsListPtr { - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); auto ret = std::make_unique<KeyIdArgsList>(); - for (int i = 0; i < key_list->rowCount(); i++) { - if ((key_list->item(i, 1) != nullptr) && buffered_keys[i].IsPrivateKey()) { - ret->push_back(buffered_keys[i].GetId()); + for (int i = 0; i < key_table->GetRowCount(); i++) { + if (key_table->IsPrivateKeyByRow(i)) { + ret->push_back(key_table->GetKeyIdByRow(i)); } } return ret; @@ -235,16 +308,11 @@ auto KeyList::GetCheckedPrivateKey() -> KeyIdArgsListPtr { auto ret = std::make_unique<KeyIdArgsList>(); if (ui_->keyGroupTab->size().isEmpty()) return ret; - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; - - for (int i = 0; i < key_list->rowCount(); i++) { - if ((key_list->item(i, 0)->checkState() == Qt::Checked) && - ((key_list->item(i, 1)) != nullptr) && - buffered_keys[i].IsPrivateKey()) { - ret->push_back(buffered_keys[i].GetId()); + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + + for (int i = 0; i < key_table->GetRowCount(); i++) { + if (key_table->IsRowChecked(i) && key_table->IsPrivateKeyByRow(i)) { + ret->push_back(key_table->GetKeyIdByRow(i)); } } return ret; @@ -254,16 +322,11 @@ auto KeyList::GetCheckedPublicKey() -> KeyIdArgsListPtr { auto ret = std::make_unique<KeyIdArgsList>(); if (ui_->keyGroupTab->size().isEmpty()) return ret; - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; - - for (int i = 0; i < key_list->rowCount(); i++) { - if ((key_list->item(i, 0)->checkState() == Qt::Checked) && - ((key_list->item(i, 1)) != nullptr) && - !buffered_keys[i].IsPrivateKey()) { - ret->push_back(buffered_keys[i].GetId()); + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + + for (int i = 0; i < key_table->GetRowCount(); i++) { + if (key_table->IsRowChecked(i) && key_table->IsPublicKeyByRow(i)) { + ret->push_back(key_table->GetKeyIdByRow(i)); } } return ret; @@ -272,52 +335,43 @@ auto KeyList::GetCheckedPublicKey() -> KeyIdArgsListPtr { void KeyList::SetChecked(const KeyIdArgsListPtr& keyIds, const KeyTable& key_table) { if (!keyIds->empty()) { - for (int i = 0; i < key_table.key_list_->rowCount(); i++) { + for (int i = 0; i < key_table.GetRowCount(); i++) { if (std::find(keyIds->begin(), keyIds->end(), - key_table.buffered_keys_[i].GetId()) != keyIds->end()) { - key_table.key_list_->item(i, 0)->setCheckState(Qt::Checked); - } - } - } -} - -void KeyList::SetChecked(KeyIdArgsListPtr key_ids) { - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - if (key_list == nullptr) return; - if (!m_key_tables_.empty()) { - for (auto& key_table : m_key_tables_) { - if (key_table.key_list_ == key_list) { - key_table.SetChecked(std::move(key_ids)); - break; + key_table.GetKeyIdByRow(i)) != keyIds->end()) { + key_table.SetRowChecked(i); } } } } -KeyIdArgsListPtr KeyList::GetSelected() { +auto KeyList::GetSelected() -> KeyIdArgsListPtr { auto ret = std::make_unique<KeyIdArgsList>(); if (ui_->keyGroupTab->size().isEmpty()) return ret; - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + if (key_table == nullptr) { + qCWarning(ui, "fail to get current key table, nullptr"); + return ret; + } - for (int i = 0; i < key_list->rowCount(); i++) { - if (key_list->item(i, 0)->isSelected()) { - ret->push_back(buffered_keys[i].GetId()); - } + QItemSelectionModel* select = key_table->selectionModel(); + for (auto index : select->selectedRows()) { + ret->push_back(key_table->GetKeyIdByRow(index.row())); + } + + if (ret->empty()) { + qCWarning(ui, "nothing is selected at key list"); } return ret; } [[maybe_unused]] auto KeyList::ContainsPrivateKeys() -> bool { if (ui_->keyGroupTab->size().isEmpty()) return false; - m_key_list_ = qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); + auto* key_table = + qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - for (int i = 0; i < m_key_list_->rowCount(); i++) { - if (m_key_list_->item(i, 1) != nullptr) { + for (int i = 0; i < key_table->rowCount(); i++) { + if (key_table->item(i, 1) != nullptr) { return true; } } @@ -326,21 +380,24 @@ KeyIdArgsListPtr KeyList::GetSelected() { void KeyList::SetColumnWidth(int row, int size) { if (ui_->keyGroupTab->size().isEmpty()) return; - m_key_list_ = qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - - m_key_list_->setColumnWidth(row, size); + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + key_table->setColumnWidth(row, size); } void KeyList::contextMenuEvent(QContextMenuEvent* event) { - if (ui_->keyGroupTab->size().isEmpty()) return; - m_key_list_ = qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); + if (ui_->keyGroupTab->count() == 0) return; + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + + if (key_table == nullptr) { + qCDebug(ui, "m_key_list_ is nullptr, key group tab number: %d", + ui_->keyGroupTab->count()); + return; + } QString current_tab_widget_obj_name = ui_->keyGroupTab->widget(ui_->keyGroupTab->currentIndex())->objectName(); - GF_UI_LOG_DEBUG("current tab widget object name: {}", - current_tab_widget_obj_name); if (current_tab_widget_obj_name == "favourite") { - QList<QAction*> actions = popup_menu_->actions(); + auto actions = popup_menu_->actions(); for (QAction* action : actions) { if (action->data().toString() == "remove_key_from_favourtie_action") { action->setVisible(true); @@ -349,7 +406,7 @@ void KeyList::contextMenuEvent(QContextMenuEvent* event) { } } } else { - QList<QAction*> actions = popup_menu_->actions(); + auto actions = popup_menu_->actions(); for (QAction* action : actions) { if (action->data().toString() == "remove_key_from_favourtie_action") { action->setVisible(false); @@ -359,7 +416,7 @@ void KeyList::contextMenuEvent(QContextMenuEvent* event) { } } - if (m_key_list_->selectedItems().length() > 0) { + if (key_table->GetRowSelected() >= 0) { popup_menu_->exec(event->globalPos()); } } @@ -379,7 +436,7 @@ void KeyList::dropEvent(QDropEvent* event) { // "always import keys"-CheckBox auto* check_box = new QCheckBox(tr("Always import without bothering.")); - bool confirm_import_keys = GlobalSettingStation::GetInstance() + auto confirm_import_keys = GlobalSettingStation::GetInstance() .GetSettings() .value("basic/confirm_import_keys", true) .toBool(); @@ -411,14 +468,14 @@ void KeyList::dropEvent(QDropEvent* event) { QFile file; file.setFileName(tmp.toLocalFile()); if (!file.open(QIODevice::ReadOnly)) { - GF_UI_LOG_ERROR("couldn't open file: {}", tmp.toString()); + qCWarning(ui) << "couldn't open file: " << tmp.toString(); } - QByteArray in_buffer = file.readAll(); + auto in_buffer = file.readAll(); this->import_keys(in_buffer); file.close(); } } else { - QByteArray in_buffer(event->mimeData()->text().toUtf8()); + auto in_buffer(event->mimeData()->text().toUtf8()); this->import_keys(in_buffer); } } @@ -435,11 +492,11 @@ void KeyList::import_keys(const QByteArray& in_buffer) { void KeyList::slot_double_clicked(const QModelIndex& index) { if (ui_->keyGroupTab->size().isEmpty()) return; - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; + + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); if (m_action_ != nullptr) { - const auto key = - GpgKeyGetter::GetInstance().GetKey(buffered_keys[index.row()].GetId()); + const auto key = GpgKeyGetter::GetInstance().GetKey( + key_table->GetKeyIdByRow(index.row())); m_action_(key, this); } } @@ -451,30 +508,15 @@ void KeyList::SetDoubleClickedAction( auto KeyList::GetSelectedKey() -> QString { if (ui_->keyGroupTab->size().isEmpty()) return {}; - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; - for (int i = 0; i < m_key_list_->rowCount(); i++) { - if (m_key_list_->item(i, 0)->isSelected()) { - return buffered_keys[i].GetId(); - } - } - return {}; -} + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); -void KeyList::slot_refresh_ui() { - GF_UI_LOG_DEBUG("refresh: {}", static_cast<void*>(buffered_keys_list_.get())); - if (buffered_keys_list_ != nullptr) { - std::lock_guard<std::mutex> guard(buffered_key_list_mutex_); + QItemSelectionModel* select = key_table->selectionModel(); - for (auto& key_table : m_key_tables_) { - key_table.Refresh( - GpgKeyGetter::GetInstance().GetKeysCopy(buffered_keys_list_)); - } - } - emit SignalRefreshStatusBar(tr("Key List Refreshed."), 1000); - ui_->refreshKeyListButton->setDisabled(false); - ui_->syncButton->setDisabled(false); + auto selected_rows = select->selectedRows(); + if (selected_rows.empty()) return {}; + + return key_table->GetKeyIdByRow(selected_rows.first().row()); } void KeyList::slot_sync_with_key_server() { @@ -490,14 +532,12 @@ void KeyList::slot_sync_with_key_server() { QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::No) return; - { - std::lock_guard<std::mutex> guard(buffered_key_list_mutex_); - for (const auto& key : *buffered_keys_list_) { - if (!(key.IsPrivateKey() && key.IsHasMasterKey())) { - key_ids.push_back(key.GetId()); - } - } + + auto all_key_ids = model_->GetAllKeyIds(); + for (auto& key_id : all_key_ids) { + key_ids.push_back(key_id); } + } else { key_ids = *checked_public_keys; } @@ -511,8 +551,6 @@ void KeyList::slot_sync_with_key_server() { CommonUtils::SlotImportKeyFromKeyServer( key_ids, [=](const QString& key_id, const QString& status, size_t current_index, size_t all_index) { - GF_UI_LOG_DEBUG("import key: {} {} {} {}", key_id, status, - current_index, all_index); auto key = GpgKeyGetter::GetInstance().GetKey(key_id); auto status_str = tr("Sync [%1/%2] %3 %4") @@ -535,226 +573,31 @@ void KeyList::filter_by_keyword() { auto keyword = ui_->searchBarEdit->text(); keyword = keyword.trimmed(); - GF_UI_LOG_DEBUG("get new keyword of search bar: {}", keyword); - for (auto& table : m_key_tables_) { + for (int i = 0; i < ui_->keyGroupTab->count(); i++) { + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->widget(i)); // refresh arguments - table.SetFilterKeyword(keyword.toLower()); - table.SetMenuAbility(menu_ability_); + key_table->SetFilterKeyword(keyword.toLower()); } + // refresh ui SlotRefreshUI(); } void KeyList::uncheck_all() { - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - if (key_list == nullptr) return; - if (!m_key_tables_.empty()) { - for (auto& key_table : m_key_tables_) { - if (key_table.key_list_ == key_list) { - key_table.UncheckALL(); - break; - } - } - } + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + if (key_table == nullptr) return; + key_table->UncheckAll(); } void KeyList::check_all() { - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - if (key_list == nullptr) return; - if (!m_key_tables_.empty()) { - for (auto& key_table : m_key_tables_) { - if (key_table.key_list_ == key_list) { - key_table.CheckALL(); - break; - } - } - } -} - -KeyIdArgsListPtr& KeyTable::GetChecked() { - if (checked_key_ids_ == nullptr) { - checked_key_ids_ = std::make_unique<KeyIdArgsList>(); - } - auto& ret = checked_key_ids_; - for (size_t i = 0; i < buffered_keys_.size(); i++) { - auto key_id = buffered_keys_[i].GetId(); - if (key_list_->item(i, 0)->checkState() == Qt::Checked && - std::find(ret->begin(), ret->end(), key_id) == ret->end()) { - ret->push_back(key_id); - } - } - return ret; -} - -void KeyTable::SetChecked(KeyIdArgsListPtr key_ids) { - checked_key_ids_ = std::move(key_ids); -} - -void KeyTable::Refresh(KeyLinkListPtr m_keys) { - auto& checked_key_list = GetChecked(); - // while filling the table, sort enabled causes errors - - key_list_->setSortingEnabled(false); - key_list_->clearContents(); - - // Optimization for copy - KeyLinkListPtr keys = nullptr; - if (m_keys == nullptr) { - keys = GpgKeyGetter::GetInstance().FetchKey(); - } else { - keys = std::move(m_keys); - } - - auto it = keys->begin(); - int row_count = 0; - - while (it != keys->end()) { - // filter by search bar's keyword - if (ability_ & KeyMenuAbility::SEARCH_BAR && !keyword_.isEmpty()) { - QStringList infos; - infos << it->GetName().toLower() << it->GetEmail().toLower() - << it->GetComment().toLower() << it->GetFingerprint().toLower(); - - auto subkeys = it->GetSubKeys(); - for (const auto& subkey : *subkeys) { - infos << subkey.GetFingerprint().toLower() << subkey.GetID().toLower(); - } - - if (infos.filter(keyword_.toLower()).isEmpty()) { - it = keys->erase(it); - continue; - } - } - - if (filter_ != nullptr) { - if (!filter_(*it, *this)) { - it = keys->erase(it); - continue; - } - } - - if (select_type_ == KeyListRow::ONLY_SECRET_KEY && !it->IsPrivateKey()) { - it = keys->erase(it); - continue; - } - row_count++; - it++; - } - - key_list_->setRowCount(row_count); - - int row_index = 0; - it = keys->begin(); - - buffered_keys_.clear(); - - while (it != keys->end()) { - auto* tmp0 = new QTableWidgetItem(QString::number(row_index)); - tmp0->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | - Qt::ItemIsSelectable); - tmp0->setTextAlignment(Qt::AlignCenter); - tmp0->setCheckState(Qt::Unchecked); - key_list_->setItem(row_index, 0, tmp0); - - QString type_str; - QTextStream type_steam(&type_str); - if (it->IsPrivateKey()) { - type_steam << "pub/sec"; - } else { - type_steam << "pub"; - } - - if (it->IsPrivateKey() && !it->IsHasMasterKey()) { - type_steam << "#"; - } - - if (it->IsHasCardKey()) { - type_steam << "^"; - } - - auto* tmp1 = new QTableWidgetItem(type_str); - key_list_->setItem(row_index, 1, tmp1); - - auto* tmp2 = new QTableWidgetItem(it->GetName()); - key_list_->setItem(row_index, 2, tmp2); - auto* tmp3 = new QTableWidgetItem(it->GetEmail()); - key_list_->setItem(row_index, 3, tmp3); - - QString usage; - QTextStream usage_steam(&usage); - - if (it->IsHasActualCertificationCapability()) usage_steam << "C"; - if (it->IsHasActualEncryptionCapability()) usage_steam << "E"; - if (it->IsHasActualSigningCapability()) usage_steam << "S"; - if (it->IsHasActualAuthenticationCapability()) usage_steam << "A"; - - auto* temp_usage = new QTableWidgetItem(usage); - temp_usage->setTextAlignment(Qt::AlignCenter); - key_list_->setItem(row_index, 4, temp_usage); - - auto* temp_validity = new QTableWidgetItem(it->GetOwnerTrust()); - temp_validity->setTextAlignment(Qt::AlignCenter); - key_list_->setItem(row_index, 5, temp_validity); - - auto* temp_id = new QTableWidgetItem(it->GetId()); - temp_id->setTextAlignment(Qt::AlignCenter); - key_list_->setItem(row_index, 6, temp_id); - - auto* temp_fpr = new QTableWidgetItem(it->GetFingerprint()); - temp_fpr->setTextAlignment(Qt::AlignCenter); - key_list_->setItem(row_index, 7, temp_fpr); - - QFont font = tmp2->font(); - - // strike out expired keys - if (it->IsExpired() || it->IsRevoked()) font.setStrikeOut(true); - if (it->IsPrivateKey()) font.setBold(true); - - tmp0->setFont(font); - temp_usage->setFont(font); - temp_fpr->setFont(font); - temp_validity->setFont(font); - tmp1->setFont(font); - tmp2->setFont(font); - tmp3->setFont(font); - temp_id->setFont(font); - - // move to buffered keys - buffered_keys_.emplace_back(std::move(*it)); - - it++; - ++row_index; - } - - if (!checked_key_list->empty()) { - for (int i = 0; i < key_list_->rowCount(); i++) { - if (std::find(checked_key_list->begin(), checked_key_list->end(), - buffered_keys_[i].GetId()) != checked_key_list->end()) { - key_list_->item(i, 0)->setCheckState(Qt::Checked); - } - } - } -} - -void KeyTable::UncheckALL() const { - for (int i = 0; i < key_list_->rowCount(); i++) { - key_list_->item(i, 0)->setCheckState(Qt::Unchecked); - } + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + if (key_table == nullptr) return; + key_table->CheckAll(); } -void KeyTable::CheckALL() const { - for (int i = 0; i < key_list_->rowCount(); i++) { - key_list_->item(i, 0)->setCheckState(Qt::Checked); - } -} - -void KeyTable::SetMenuAbility(KeyMenuAbility::AbilityType ability) { - this->ability_ = ability; +void KeyList::UpdateKeyTableColumnType(GpgKeyTableColumn column_type) { + global_column_filter_ = column_type; + emit SignalColumnTypeChange(fixed_columns_filter_ & global_column_filter_); } -void KeyTable::SetFilterKeyword(QString keyword) { - this->keyword_ = std::move(keyword); -} } // namespace GpgFrontend::UI diff --git a/src/ui/widgets/KeyList.h b/src/ui/widgets/KeyList.h index 1761fb23..cbad6812 100644 --- a/src/ui/widgets/KeyList.h +++ b/src/ui/widgets/KeyList.h @@ -28,7 +28,7 @@ #pragma once -#include "core/model/GpgKey.h" +#include "ui/widgets/KeyTable.h" class Ui_KeyList; @@ -38,126 +38,39 @@ namespace GpgFrontend::UI { * @brief * */ -struct KeyListRow { - using KeyType = unsigned int; - - static const KeyType SECRET_OR_PUBLIC_KEY = 0; ///< - static const KeyType ONLY_SECRET_KEY = 1; ///< +enum class KeyMenuAbility : unsigned int { + kNONE = 0, + kREFRESH = 1 << 0, + kSYNC_PUBLIC_KEY = 1 << 1, + kUNCHECK_ALL = 1 << 2, + kCHECK_ALL = 1 << 3, + kCOLUMN_FILTER = 1 << 4, + kSEARCH_BAR = 1 << 5, + + kALL = ~0U }; -/** - * @brief - * - */ -struct KeyListColumn { - using InfoType = unsigned int; - - static constexpr InfoType ALL = ~0; ///< - static constexpr InfoType TYPE = 1 << 0; ///< - static constexpr InfoType NAME = 1 << 1; ///< - static constexpr InfoType EmailAddress = 1 << 2; ///< - static constexpr InfoType Usage = 1 << 3; ///< - static constexpr InfoType Validity = 1 << 4; ///< - static constexpr InfoType FingerPrint = 1 << 5; ///< - static constexpr InfoType KeyID = 1 << 6; ///< -}; +inline auto operator|(KeyMenuAbility lhs, KeyMenuAbility rhs) + -> KeyMenuAbility { + using T = std::underlying_type_t<KeyMenuAbility>; + return static_cast<KeyMenuAbility>(static_cast<T>(lhs) | static_cast<T>(rhs)); +} -/** - * @brief - * - */ -struct KeyMenuAbility { - using AbilityType = unsigned int; - - static constexpr AbilityType ALL = ~0; ///< - static constexpr AbilityType NONE = 0; ///< - static constexpr AbilityType REFRESH = 1 << 0; ///< - static constexpr AbilityType SYNC_PUBLIC_KEY = 1 << 1; ///< - static constexpr AbilityType UNCHECK_ALL = 1 << 3; ///< - static constexpr AbilityType CHECK_ALL = 1 << 5; ///< - static constexpr AbilityType SEARCH_BAR = 1 << 6; ///< -}; +inline auto operator|=(KeyMenuAbility& lhs, KeyMenuAbility rhs) + -> KeyMenuAbility& { + lhs = lhs | rhs; + return lhs; +} -/** - * @brief - * - */ -struct KeyTable { - using KeyTableFilter = std::function<bool(const GpgKey&, const KeyTable&)>; - - QTableWidget* key_list_; ///< - KeyListRow::KeyType select_type_; ///< - KeyListColumn::InfoType info_type_; ///< - std::vector<GpgKey> buffered_keys_; ///< - KeyTableFilter filter_; ///< - KeyIdArgsListPtr checked_key_ids_; ///< - KeyMenuAbility::AbilityType ability_; ///< - QString keyword_; ///< +inline auto operator&(KeyMenuAbility lhs, KeyMenuAbility rhs) -> bool { + using T = std::underlying_type_t<KeyMenuAbility>; + return (static_cast<T>(lhs) & static_cast<T>(rhs)) != 0; +} - /** - * @brief Construct a new Key Table object - * - * @param _key_list - * @param _select_type - * @param _info_type - * @param _filter - */ - KeyTable( - QTableWidget* _key_list, KeyListRow::KeyType _select_type, - KeyListColumn::InfoType _info_type, - KeyTableFilter _filter = [](const GpgKey&, const KeyTable&) -> bool { - return true; - }) - : key_list_(_key_list), - select_type_(_select_type), - info_type_(_info_type), - filter_(std::move(_filter)) {} - - /** - * @brief - * - * @param m_keys - */ - void Refresh(KeyLinkListPtr m_keys = nullptr); - - /** - * @brief Get the Checked object - * - * @return KeyIdArgsListPtr& - */ - KeyIdArgsListPtr& GetChecked(); - - /** - * @brief - * - */ - void UncheckALL() const; - - /** - * @brief - * - */ - void CheckALL() const; - - /** - * @brief Set the Checked object - * - * @param key_ids - */ - void SetChecked(KeyIdArgsListPtr key_ids); - - /** - * @brief - * - */ - void SetMenuAbility(KeyMenuAbility::AbilityType ability); - - /** - * @brief - * - */ - void SetFilterKeyword(QString keyword); -}; +inline auto operator~(KeyMenuAbility hs) -> KeyMenuAbility { + using T = std::underlying_type_t<GpgKeyTableColumn>; + return static_cast<KeyMenuAbility>(~static_cast<T>(hs)); +} /** * @brief @@ -173,8 +86,10 @@ class KeyList : public QWidget { * @param menu_ability * @param parent */ - explicit KeyList(KeyMenuAbility::AbilityType menu_ability, - QWidget* parent = nullptr); + explicit KeyList( + KeyMenuAbility menu_ability, + GpgKeyTableColumn fixed_column_filter = GpgKeyTableColumn::kALL, + QWidget* parent = nullptr); /** * @brief @@ -186,10 +101,11 @@ class KeyList : public QWidget { */ void AddListGroupTab( const QString& name, const QString& id, - KeyListRow::KeyType selectType = KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::InfoType infoType = KeyListColumn::ALL, - KeyTable::KeyTableFilter filter = - [](const GpgKey&, const KeyTable&) -> bool { return true; }); + GpgKeyTableDisplayMode display_mode = + GpgKeyTableDisplayMode::kPRIVATE_KEY, + GpgKeyTableProxyModel::KeyFilter search_filter = + [](const GpgKey&) -> bool { return true; }, + GpgKeyTableColumn custom_columns_filter = GpgKeyTableColumn::kALL); /** * @brief Set the Double Clicked Action object @@ -259,17 +175,10 @@ class KeyList : public QWidget { /** * @brief Set the Checked object * - * @param key_ids - */ - void SetChecked(KeyIdArgsListPtr key_ids); - - /** - * @brief Set the Checked object - * * @param keyIds * @param key_table */ - static void SetChecked(const KeyIdArgsListPtr& keyIds, + static void SetChecked(const KeyIdArgsListPtr& key_ids, const KeyTable& key_table); /** @@ -294,6 +203,12 @@ class KeyList : public QWidget { */ [[maybe_unused]] auto ContainsPrivateKeys() -> bool; + /** + * @brief + * + */ + void UpdateKeyTableColumnType(GpgKeyTableColumn); + signals: /** * @brief @@ -309,6 +224,14 @@ class KeyList : public QWidget { */ void SignalRefreshDatabase(); + signals: + + /** + * @brief + * + */ + void SignalColumnTypeChange(GpgKeyTableColumn); + public slots: /** @@ -335,7 +258,7 @@ class KeyList : public QWidget { * * @param inBuffer */ - void import_keys(const QByteArray& inBuffer); + void import_keys(const QByteArray& in_buffer); /** * @brief @@ -355,15 +278,20 @@ class KeyList : public QWidget { */ void filter_by_keyword(); - std::mutex buffered_key_list_mutex_; ///< - std::shared_ptr<Ui_KeyList> ui_; ///< - QTableWidget* m_key_list_{}; ///< - std::vector<KeyTable> m_key_tables_; ///< QMenu* popup_menu_{}; ///< - GpgFrontend::KeyLinkListPtr buffered_keys_list_; ///< std::function<void(const GpgKey&, QWidget*)> m_action_ = nullptr; ///< - KeyMenuAbility::AbilityType menu_ability_ = KeyMenuAbility::ALL; ///< + KeyMenuAbility menu_ability_ = KeyMenuAbility::kALL; ///< + QSharedPointer<GpgKeyTableModel> model_; + GpgKeyTableColumn fixed_columns_filter_; + GpgKeyTableColumn global_column_filter_; + + QAction* key_id_column_action_; + QAction* algo_column_action_; + QAction* create_date_column_action_; + QAction* owner_trust_column_action_; + QAction* subkeys_number_column_action_; + QAction* comment_column_action_; private slots: @@ -378,12 +306,6 @@ class KeyList : public QWidget { * @brief * */ - void slot_refresh_ui(); - - /** - * @brief - * - */ void slot_sync_with_key_server(); protected: diff --git a/src/ui/widgets/KeyTable.cpp b/src/ui/widgets/KeyTable.cpp new file mode 100644 index 00000000..1ba44232 --- /dev/null +++ b/src/ui/widgets/KeyTable.cpp @@ -0,0 +1,149 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "ui/widgets/KeyTable.h" + +#include "core/function/gpg/GpgKeyGetter.h" +#include "ui/UserInterfaceUtils.h" +#include "ui/dialog/keypair_details/KeyDetailsDialog.h" + +namespace GpgFrontend::UI { + +auto KeyTable::GetChecked() const -> KeyIdArgsListPtr { + auto ret = std::make_unique<KeyIdArgsList>(); + for (decltype(GetRowCount()) i = 0; i < GetRowCount(); i++) { + if (IsRowChecked(i)) ret->push_back(GetKeyIdByRow(i)); + } + return ret; +} + +KeyTable::KeyTable(QWidget* parent, QSharedPointer<GpgKeyTableModel> model, + GpgKeyTableDisplayMode select_type, + GpgKeyTableColumn column_filter, + GpgKeyTableProxyModel::KeyFilter filter) + : QTableView(parent), + model_(std::move(model)), + proxy_model_(model_, select_type, column_filter, std::move(filter), this), + column_filter_(column_filter) { + setModel(&proxy_model_); + + verticalHeader()->hide(); + horizontalHeader()->setStretchLastSection(false); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + setShowGrid(false); + sortByColumn(2, Qt::AscendingOrder); + setSelectionBehavior(QAbstractItemView::SelectRows); + setSelectionMode(QAbstractItemView::SingleSelection); + + // table items not editable + setEditTriggers(QAbstractItemView::NoEditTriggers); + + setFocusPolicy(Qt::NoFocus); + setAlternatingRowColors(true); + setSortingEnabled(true); + + connect(CommonUtils::GetInstance(), &CommonUtils::SignalFavoritesChanged, + &proxy_model_, &GpgKeyTableProxyModel::SignalFavoritesChanged); + connect(this, &KeyTable::SignalColumnTypeChange, this, + [=](GpgKeyTableColumn global_column_filter) { + emit(&proxy_model_) + ->SignalColumnTypeChange(column_filter_ & global_column_filter); + }); + connect(this, &QTableView::doubleClicked, this, + [this](const QModelIndex& index) { + auto key = + GpgKeyGetter::GetInstance().GetKey(GetKeyIdByRow(index.row())); + if (!key.IsGood()) { + QMessageBox::critical(this, tr("Error"), tr("Key Not Found.")); + return; + } + new KeyDetailsDialog(key, this); + }); +} + +void KeyTable::SetFilterKeyword(const QString& keyword) { + proxy_model_.SetSearchKeywords(keyword); +} + +void KeyTable::RefreshModel(QSharedPointer<GpgKeyTableModel> model) { + model_ = std::move(model); + proxy_model_.setSourceModel(model_.get()); +} + +auto KeyTable::IsRowChecked(int row) const -> bool { + auto index = model()->index(row, 0); + return index.data(Qt::CheckStateRole).toInt() == Qt::Checked; +} + +auto KeyTable::GetRowCount() const -> int { return model()->rowCount(); } + +auto KeyTable::GetKeyIdByRow(int row) const -> QString { + if (row < 0 || row >= model()->rowCount()) return {}; + auto origin_row = model()->index(row, 0).data().toInt(); + return model_->GetKeyIDByRow(origin_row); +} + +auto KeyTable::IsPrivateKeyByRow(int row) const -> bool { + if (row < 0 || row >= model()->rowCount()) return false; + auto origin_row = model()->index(row, 0).data().toInt(); + return model_->IsPrivateKeyByRow(origin_row); +} + +auto KeyTable::IsPublicKeyByRow(int row) const -> bool { + if (row < 0 || row >= model()->rowCount()) return false; + auto origin_row = model()->index(row, 0).data().toInt(); + return !model_->IsPrivateKeyByRow(origin_row); +} + +void KeyTable::SetRowChecked(int row) const { + if (row < 0 || row >= model()->rowCount()) return; + model()->setData(model()->index(row, 0), Qt::Checked, Qt::CheckStateRole); +} + +void KeyTable::CheckAll() { + for (int row = 0; row < model()->rowCount(); ++row) { + auto index = model()->index(row, 0); + model()->setData(index, Qt::Checked, Qt::CheckStateRole); + } +} + +void KeyTable::UncheckAll() { + for (int row = 0; row < model()->rowCount(); ++row) { + auto index = model()->index(row, 0); + model()->setData(index, Qt::Unchecked, Qt::CheckStateRole); + } +} + +[[nodiscard]] auto KeyTable::GetRowSelected() const -> int { + auto selected_indexes = selectedIndexes(); + if (selected_indexes.empty()) return -1; + + return selected_indexes.first().row(); +} +} // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/widgets/KeyTable.h b/src/ui/widgets/KeyTable.h new file mode 100644 index 00000000..4ec8f687 --- /dev/null +++ b/src/ui/widgets/KeyTable.h @@ -0,0 +1,176 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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. + * + * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "core/model/GpgKey.h" +#include "core/model/GpgKeyTableModel.h" +#include "core/model/GpgKeyTableProxyModel.h" + +namespace GpgFrontend::UI { + +/** + * @brief + * + */ +struct KeyTable : public QTableView { + Q_OBJECT + public: + using KeyTableFilter = std::function<bool(const GpgKey&, const KeyTable&)>; + + /** + * @brief Construct a new Key Table object + * + * @param _key_list + * @param _select_type + * @param _info_type + * @param _filter + */ + KeyTable( + QWidget* parent, QSharedPointer<GpgKeyTableModel> model, + GpgKeyTableDisplayMode _select_type, GpgKeyTableColumn _info_type, + GpgKeyTableProxyModel::KeyFilter _filter = [](const GpgKey&) -> bool { + return true; + }); + + /** + * @brief + * + * @param model + */ + void RefreshModel(QSharedPointer<GpgKeyTableModel> model); + + /** + * @brief Get the Checked object + * + * @return KeyIdArgsListPtr& + */ + [[nodiscard]] auto GetChecked() const -> KeyIdArgsListPtr; + + /** + * @brief + * + */ + void UncheckALL() const; + + /** + * @brief + * + */ + void CheckALL() const; + + /** + * @brief + * + */ + void SetFilterKeyword(const QString& keyword); + + /** + * @brief + * + * @param row + * @return true + * @return false + */ + [[nodiscard]] auto IsRowChecked(int row) const -> bool; + + /** + * @brief Set the Row Checked object + * + * @param row + */ + void SetRowChecked(int row) const; + + /** + * @brief Set the Row Checked object + * + * @param row + */ + [[nodiscard]] auto GetRowSelected() const -> int; + + /** + * @brief Get the Row Count object + * + * @return auto + */ + [[nodiscard]] auto GetRowCount() const -> int; + + /** + * @brief Get the Key Id By Row object + * + * @param row + * @return QString + */ + [[nodiscard]] auto GetKeyIdByRow(int row) const -> QString; + + /** + * @brief + * + * @param row + * @return true + * @return false + */ + [[nodiscard]] auto IsPublicKeyByRow(int row) const -> bool; + + /** + * @brief + * + * @param row + * @return true + * @return false + */ + [[nodiscard]] auto IsPrivateKeyByRow(int row) const -> bool; + + /** + * @brief + * + */ + void CheckAll(); + + /** + * @brief + * + */ + void UncheckAll(); + + signals: + + /** + * @brief + * + */ + void SignalColumnTypeChange(GpgKeyTableColumn); + + private: + QSharedPointer<GpgKeyTableModel> model_; + GpgKeyTableProxyModel proxy_model_; + + GpgKeyTableColumn column_filter_; +}; + +} // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/widgets/PlainTextEditorPage.cpp b/src/ui/widgets/PlainTextEditorPage.cpp index 874bbf3b..57910f9d 100644 --- a/src/ui/widgets/PlainTextEditorPage.cpp +++ b/src/ui/widgets/PlainTextEditorPage.cpp @@ -164,7 +164,7 @@ void PlainTextEditorPage::ReadFile() { [=]() { emit read_task->SignalTaskShouldEnd(0); }); connect(read_task, &FileReadTask::SignalFileBytesReadEnd, this, [=]() { // set the UI - GF_UI_LOG_DEBUG("signal file bytes read end rised"); + qCDebug(ui, "signal file bytes read end rised"); this->read_done_ = true; text_page->setEnabled(true); text_page->document()->setModified(false); @@ -186,8 +186,6 @@ auto BinaryToString(const QByteArray &source) -> QString { } void PlainTextEditorPage::slot_insert_text(QByteArray bytes_data) { - GF_UI_LOG_TRACE("inserting data read to editor, data size: {}", - bytes_data.size()); read_bytes_ += bytes_data.size(); // insert the text to the text page diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp index a0dba5f5..9cecfb38 100644 --- a/src/ui/widgets/TextEdit.cpp +++ b/src/ui/widgets/TextEdit.cpp @@ -120,7 +120,6 @@ void TextEdit::SlotNewFileTab() { void TextEdit::SlotOpenFile(const QString& path) { QFile file(path); - GF_UI_LOG_DEBUG("main window editor is opening file at path: {}", path); auto result = file.open(QIODevice::ReadOnly | QIODevice::Text); if (result) { auto* page = new PlainTextEditorPage(path); @@ -510,7 +509,6 @@ QHash<int, QString> TextEdit::UnsavedDocuments() const { if (ep != nullptr && ep->ReadDone() && ep->GetTextPage()->document()->isModified()) { QString doc_name = tab_widget_->tabText(i); - GF_UI_LOG_DEBUG("unsaved: {}", doc_name); // remove * before name of modified doc doc_name.remove(0, 2); @@ -601,8 +599,8 @@ void TextEdit::slot_file_page_path_changed(const QString& path) const { } tab_widget_->setTabText(index, m_path); - emit UISignalStation::GetInstance()->SignalMainWindowlUpdateBasicalOperaMenu( - 0); + emit UISignalStation::GetInstance() + -> SignalMainWindowlUpdateBasicalOperaMenu(0); } void TextEdit::slot_save_status_to_cache_for_revovery() { @@ -614,17 +612,11 @@ void TextEdit::slot_save_status_to_cache_for_revovery() { bool restore_text_editor_page = settings.value("basic/restore_text_editor_page", false).toBool(); if (!restore_text_editor_page) { - GF_UI_LOG_DEBUG("restore_text_editor_page is false, ignoring..."); + qCDebug(ui, "restore_text_editor_page is false, ignoring..."); return; } int tab_count = tab_widget_->count(); - GF_UI_LOG_DEBUG( - "restore_text_editor_page is true, pan to save pages, current tabs " - "count: " - "{}", - tab_count); - std::vector<std::tuple<int, QString, QString>> unsaved_pages; for (int i = 0; i < tab_count; i++) { @@ -643,9 +635,7 @@ void TextEdit::slot_save_status_to_cache_for_revovery() { continue; } - auto raw_text = document->toRawText(); - GF_UI_LOG_DEBUG("unsaved page index: {}, tab title: {}", i, tab_title); - unsaved_pages.emplace_back(i, tab_title, raw_text); + unsaved_pages.emplace_back(i, tab_title, document->toRawText()); } CacheObject cache("editor_unsaved_pages"); |