From 2634b30bfa5bcfd87a8d1f6ceef9e5c41fbaa823 Mon Sep 17 00:00:00 2001 From: "mo.qingliang" Date: Tue, 28 Mar 2023 14:10:27 +0800 Subject: [PATCH] nde-screensaver-0.1.0 --- nde-screensaver-0.1.0/CMakeLists.txt | 224 ++++++++++++ nde-screensaver-0.1.0/cmake/FindPAM.cmake | 74 ++++ nde-screensaver-0.1.0/cmake/FindXAU.cmake | 54 +++ .../cmake/FindXAU.cmake.libxau | 0 nde-screensaver-0.1.0/cmake/FindXCB.cmake | 54 +++ nde-screensaver-0.1.0/cmake/FindXKB.cmake | 58 +++ .../cmake/cmake_uninstall.cmake.in | 22 ++ nde-screensaver-0.1.0/data/CMakeLists.txt | 13 + .../data/autostart/nde-screensaver.desktop | 9 + .../data/faces/default.face.icon.png | Bin 0 -> 3450 bytes .../data/pam/nde-screensaver.pam | 15 + nde-screensaver-0.1.0/src/CMakeLists.txt | 10 + nde-screensaver-0.1.0/src/auth/Auth.cpp | 303 +++++++++++++++ nde-screensaver-0.1.0/src/auth/Auth.h | 140 +++++++ nde-screensaver-0.1.0/src/auth/AuthMessages.h | 213 +++++++++++ nde-screensaver-0.1.0/src/auth/AuthPrompt.cpp | 72 ++++ nde-screensaver-0.1.0/src/auth/AuthPrompt.h | 102 ++++++ .../src/auth/AuthRequest.cpp | 111 ++++++ nde-screensaver-0.1.0/src/auth/AuthRequest.h | 94 +++++ .../src/common/Constants.h.in | 39 ++ .../src/common/MessageHandler.h | 117 ++++++ nde-screensaver-0.1.0/src/common/Messages.h | 57 +++ .../src/common/SafeDataStream.cpp | 82 +++++ .../src/common/SafeDataStream.h | 40 ++ .../src/common/SocketWriter.cpp | 47 +++ .../src/common/SocketWriter.h | 23 ++ nde-screensaver-0.1.0/src/common/Utils.h | 50 +++ .../src/common/com.vm.daemon.xml | 28 ++ .../src/greeter/CMakeLists.txt | 38 ++ .../src/greeter/GreeterApp.cpp | 207 +++++++++++ .../src/greeter/GreeterApp.h | 86 +++++ .../src/greeter/GreeterProxy.cpp | 238 ++++++++++++ .../src/greeter/GreeterProxy.h | 91 +++++ .../src/greeter/KeyboardBackend.h | 45 +++ .../src/greeter/KeyboardLayout.cpp | 38 ++ .../src/greeter/KeyboardLayout.h | 43 +++ .../src/greeter/KeyboardModel.cpp | 116 ++++++ .../src/greeter/KeyboardModel.h | 78 ++++ .../src/greeter/KeyboardModel_p.h | 45 +++ .../src/greeter/ScreenModel.cpp | 77 ++++ .../src/greeter/ScreenModel.h | 64 ++++ .../src/greeter/SessionModel.cpp | 159 ++++++++ .../src/greeter/SessionModel.h | 64 ++++ .../src/greeter/UserModel.cpp | 176 +++++++++ nde-screensaver-0.1.0/src/greeter/UserModel.h | 57 +++ .../src/greeter/XcbKeyboardBackend.cpp | 333 +++++++++++++++++ .../src/greeter/XcbKeyboardBackend.h | 69 ++++ nde-screensaver-0.1.0/src/greeter/theme.qrc | 10 + .../src/greeter/theme/Main.qml | 345 ++++++++++++++++++ .../src/greeter/theme/VirtualKeyboard.qml | 8 + .../src/greeter/theme/keyboard.png | Bin 0 -> 1391 bytes .../src/greeter/theme/poweroff.png | Bin 0 -> 1329 bytes .../src/greeter/theme/reboot.png | Bin 0 -> 1338 bytes .../src/greeter/theme/sleep.png | Bin 0 -> 1432 bytes .../src/greeter/translations/CMakeLists.txt | 46 +++ .../src/greeter/translations/ar.ts | 50 +++ .../src/greeter/translations/bn.ts | 50 +++ .../src/greeter/translations/ca.ts | 50 +++ .../src/greeter/translations/cs.ts | 50 +++ .../src/greeter/translations/da.ts | 50 +++ .../src/greeter/translations/de.ts | 50 +++ .../src/greeter/translations/es.ts | 50 +++ .../src/greeter/translations/et.ts | 50 +++ .../src/greeter/translations/fi.ts | 50 +++ .../src/greeter/translations/fr.ts | 50 +++ .../src/greeter/translations/hi_IN.ts | 50 +++ .../src/greeter/translations/hu.ts | 50 +++ .../src/greeter/translations/is.ts | 50 +++ .../src/greeter/translations/it.ts | 50 +++ .../src/greeter/translations/ja.ts | 50 +++ .../src/greeter/translations/kk.ts | 50 +++ .../src/greeter/translations/ko.ts | 50 +++ .../src/greeter/translations/lt.ts | 50 +++ .../src/greeter/translations/lv.ts | 50 +++ .../src/greeter/translations/nb.ts | 50 +++ .../src/greeter/translations/nl.ts | 50 +++ .../src/greeter/translations/nn.ts | 50 +++ .../src/greeter/translations/pl.ts | 50 +++ .../src/greeter/translations/pt_BR.ts | 50 +++ .../src/greeter/translations/pt_PT.ts | 50 +++ .../src/greeter/translations/ro.ts | 50 +++ .../src/greeter/translations/ru.ts | 50 +++ .../src/greeter/translations/sk.ts | 50 +++ .../src/greeter/translations/sr.ts | 50 +++ .../src/greeter/translations/sr@ijekavian.ts | 50 +++ .../greeter/translations/sr@ijekavianlatin.ts | 50 +++ .../src/greeter/translations/sr@latin.ts | 50 +++ .../src/greeter/translations/sv.ts | 50 +++ .../src/greeter/translations/tr.ts | 50 +++ .../src/greeter/translations/uk.ts | 50 +++ .../src/greeter/translations/zh_CN.ts | 50 +++ .../src/greeter/translations/zh_TW.ts | 50 +++ .../src/greeter/xservergrabber.cpp | 73 ++++ .../src/greeter/xservergrabber.h | 8 + nde-screensaver-0.1.0/src/helper/Backend.cpp | 47 +++ nde-screensaver-0.1.0/src/helper/Backend.h | 51 +++ .../src/helper/CMakeLists.txt | 42 +++ .../src/helper/HelperApp.cpp | 176 +++++++++ nde-screensaver-0.1.0/src/helper/HelperApp.h | 67 ++++ .../src/helper/backend/PamBackend.cpp | 305 ++++++++++++++++ .../src/helper/backend/PamBackend.h | 76 ++++ .../src/helper/backend/PamHandle.cpp | 189 ++++++++++ .../src/helper/backend/PamHandle.h | 200 ++++++++++ .../src/helper/backend/PasswdBackend.cpp | 109 ++++++ .../src/helper/backend/PasswdBackend.h | 43 +++ .../src/nde-screensaver/CMakeLists.txt | 36 ++ .../src/nde-screensaver/PowerManager.cpp | 266 ++++++++++++++ .../src/nde-screensaver/PowerManager.h | 52 +++ .../src/nde-screensaver/ScreenSaverApp.cpp | 171 +++++++++ .../src/nde-screensaver/ScreenSaverApp.h | 58 +++ .../src/nde-screensaver/SocketServer.cpp | 181 +++++++++ .../src/nde-screensaver/SocketServer.h | 60 +++ .../src/nde-screensaver/idlewatcher.cpp | 53 +++ .../src/nde-screensaver/idlewatcher.h | 28 ++ .../src/nde-screensaver/lockscreenmanager.cpp | 245 +++++++++++++ .../src/nde-screensaver/lockscreenmanager.h | 83 +++++ .../nde-screensaver/lockscreenshortcut.cpp | 34 ++ .../src/nde-screensaver/lockscreenshortcut.h | 26 ++ .../nde-screensaver/org.nde.screensaver.xml | 13 + .../src/nde-screensaver/screensaver.cpp | 32 ++ .../src/nde-screensaver/screensaver.h | 17 + nde-screensaver.spec | 76 ++++ 122 files changed, 9151 insertions(+) create mode 100644 nde-screensaver-0.1.0/CMakeLists.txt create mode 100644 nde-screensaver-0.1.0/cmake/FindPAM.cmake create mode 100644 nde-screensaver-0.1.0/cmake/FindXAU.cmake create mode 100644 nde-screensaver-0.1.0/cmake/FindXAU.cmake.libxau create mode 100644 nde-screensaver-0.1.0/cmake/FindXCB.cmake create mode 100644 nde-screensaver-0.1.0/cmake/FindXKB.cmake create mode 100644 nde-screensaver-0.1.0/cmake/cmake_uninstall.cmake.in create mode 100644 nde-screensaver-0.1.0/data/CMakeLists.txt create mode 100644 nde-screensaver-0.1.0/data/autostart/nde-screensaver.desktop create mode 100644 nde-screensaver-0.1.0/data/faces/default.face.icon.png create mode 100644 nde-screensaver-0.1.0/data/pam/nde-screensaver.pam create mode 100644 nde-screensaver-0.1.0/src/CMakeLists.txt create mode 100644 nde-screensaver-0.1.0/src/auth/Auth.cpp create mode 100644 nde-screensaver-0.1.0/src/auth/Auth.h create mode 100644 nde-screensaver-0.1.0/src/auth/AuthMessages.h create mode 100644 nde-screensaver-0.1.0/src/auth/AuthPrompt.cpp create mode 100644 nde-screensaver-0.1.0/src/auth/AuthPrompt.h create mode 100644 nde-screensaver-0.1.0/src/auth/AuthRequest.cpp create mode 100644 nde-screensaver-0.1.0/src/auth/AuthRequest.h create mode 100644 nde-screensaver-0.1.0/src/common/Constants.h.in create mode 100644 nde-screensaver-0.1.0/src/common/MessageHandler.h create mode 100644 nde-screensaver-0.1.0/src/common/Messages.h create mode 100644 nde-screensaver-0.1.0/src/common/SafeDataStream.cpp create mode 100644 nde-screensaver-0.1.0/src/common/SafeDataStream.h create mode 100644 nde-screensaver-0.1.0/src/common/SocketWriter.cpp create mode 100644 nde-screensaver-0.1.0/src/common/SocketWriter.h create mode 100644 nde-screensaver-0.1.0/src/common/Utils.h create mode 100644 nde-screensaver-0.1.0/src/common/com.vm.daemon.xml create mode 100644 nde-screensaver-0.1.0/src/greeter/CMakeLists.txt create mode 100644 nde-screensaver-0.1.0/src/greeter/GreeterApp.cpp create mode 100644 nde-screensaver-0.1.0/src/greeter/GreeterApp.h create mode 100644 nde-screensaver-0.1.0/src/greeter/GreeterProxy.cpp create mode 100644 nde-screensaver-0.1.0/src/greeter/GreeterProxy.h create mode 100644 nde-screensaver-0.1.0/src/greeter/KeyboardBackend.h create mode 100644 nde-screensaver-0.1.0/src/greeter/KeyboardLayout.cpp create mode 100644 nde-screensaver-0.1.0/src/greeter/KeyboardLayout.h create mode 100644 nde-screensaver-0.1.0/src/greeter/KeyboardModel.cpp create mode 100644 nde-screensaver-0.1.0/src/greeter/KeyboardModel.h create mode 100644 nde-screensaver-0.1.0/src/greeter/KeyboardModel_p.h create mode 100644 nde-screensaver-0.1.0/src/greeter/ScreenModel.cpp create mode 100644 nde-screensaver-0.1.0/src/greeter/ScreenModel.h create mode 100644 nde-screensaver-0.1.0/src/greeter/SessionModel.cpp create mode 100644 nde-screensaver-0.1.0/src/greeter/SessionModel.h create mode 100644 nde-screensaver-0.1.0/src/greeter/UserModel.cpp create mode 100644 nde-screensaver-0.1.0/src/greeter/UserModel.h create mode 100644 nde-screensaver-0.1.0/src/greeter/XcbKeyboardBackend.cpp create mode 100644 nde-screensaver-0.1.0/src/greeter/XcbKeyboardBackend.h create mode 100644 nde-screensaver-0.1.0/src/greeter/theme.qrc create mode 100644 nde-screensaver-0.1.0/src/greeter/theme/Main.qml create mode 100644 nde-screensaver-0.1.0/src/greeter/theme/VirtualKeyboard.qml create mode 100644 nde-screensaver-0.1.0/src/greeter/theme/keyboard.png create mode 100644 nde-screensaver-0.1.0/src/greeter/theme/poweroff.png create mode 100644 nde-screensaver-0.1.0/src/greeter/theme/reboot.png create mode 100644 nde-screensaver-0.1.0/src/greeter/theme/sleep.png create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/CMakeLists.txt create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/ar.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/bn.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/ca.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/cs.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/da.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/de.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/es.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/et.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/fi.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/fr.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/hi_IN.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/hu.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/is.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/it.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/ja.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/kk.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/ko.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/lt.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/lv.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/nb.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/nl.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/nn.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/pl.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/pt_BR.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/pt_PT.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/ro.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/ru.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/sk.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/sr.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/sr@ijekavian.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/sr@ijekavianlatin.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/sr@latin.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/sv.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/tr.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/uk.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/zh_CN.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/translations/zh_TW.ts create mode 100644 nde-screensaver-0.1.0/src/greeter/xservergrabber.cpp create mode 100644 nde-screensaver-0.1.0/src/greeter/xservergrabber.h create mode 100644 nde-screensaver-0.1.0/src/helper/Backend.cpp create mode 100644 nde-screensaver-0.1.0/src/helper/Backend.h create mode 100644 nde-screensaver-0.1.0/src/helper/CMakeLists.txt create mode 100644 nde-screensaver-0.1.0/src/helper/HelperApp.cpp create mode 100644 nde-screensaver-0.1.0/src/helper/HelperApp.h create mode 100644 nde-screensaver-0.1.0/src/helper/backend/PamBackend.cpp create mode 100644 nde-screensaver-0.1.0/src/helper/backend/PamBackend.h create mode 100644 nde-screensaver-0.1.0/src/helper/backend/PamHandle.cpp create mode 100644 nde-screensaver-0.1.0/src/helper/backend/PamHandle.h create mode 100644 nde-screensaver-0.1.0/src/helper/backend/PasswdBackend.cpp create mode 100644 nde-screensaver-0.1.0/src/helper/backend/PasswdBackend.h create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/CMakeLists.txt create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/PowerManager.cpp create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/PowerManager.h create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/ScreenSaverApp.cpp create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/ScreenSaverApp.h create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/SocketServer.cpp create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/SocketServer.h create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/idlewatcher.cpp create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/idlewatcher.h create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/lockscreenmanager.cpp create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/lockscreenmanager.h create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/lockscreenshortcut.cpp create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/lockscreenshortcut.h create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/org.nde.screensaver.xml create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/screensaver.cpp create mode 100644 nde-screensaver-0.1.0/src/nde-screensaver/screensaver.h create mode 100644 nde-screensaver.spec diff --git a/nde-screensaver-0.1.0/CMakeLists.txt b/nde-screensaver-0.1.0/CMakeLists.txt new file mode 100644 index 0000000..3af2aec --- /dev/null +++ b/nde-screensaver-0.1.0/CMakeLists.txt @@ -0,0 +1,224 @@ +cmake_minimum_required(VERSION 2.8.8) + +project(nde-screensaver) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_AUTOMOC ON) +SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +# Silence CMake 3.0 warnings +if(POLICY CMP0043) + cmake_policy(SET CMP0043 OLD) +endif() + +# Set version +set(NSS_VERSION_MAJOR 0) +set(NSS_VERSION_MINOR 1) +set(NSS_VERSION_PATCH 0) +set(NSS_VERSION_STRING "${NSS_VERSION_MAJOR}.${NSS_VERSION_MINOR}.${NSS_VERSION_PATCH}") + +# Set up packaging +set(CPACK_PACKAGE_NAME "nss") +set(CPACK_PACKAGE_VERSION "${NSS_VERSION_STRING}") +set(CPACK_GENERATOR "TGZ") +set(CPACK_SET_DESTDIR FALSE) +set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") +set(CPACK_SOURCE_IGNORE_FILES "/build/;/.git;/*.user;/.tx/;~$;${CPACK_SOURCE_IGNORE_FILES}") +include(CPack) +add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source) + +# Options +option(BUILD_MAN_PAGES "Build man pages" OFF) +option(ENABLE_JOURNALD "Enable logging to journald" ON) +option(ENABLE_PAM "Enable PAM support" ON) +option(NO_SYSTEMD "Disable systemd support" OFF) +option(USE_ELOGIND "Use elogind instead of logind" OFF) + +# ECM +find_package(ECM 1.4.0 REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH};${ECM_MODULE_PATH}") +find_package(KF5IdleTime) + +# Definitions +add_definitions(-Wall -std=c++11 -DQT_NO_CAST_FROM_BYTEARRAY) + +# Default build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +# Handle build type +if(CMAKE_BUILD_TYPE MATCHES [Dd]ebug) + message(STATUS "Debug build") + add_definitions(-DDEBUG) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0") +else() + message(STATUS "Release build") + add_definitions(-DNDEBUG) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") +endif() + +# Default absolute paths +if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR) + set(CMAKE_INSTALL_SYSCONFDIR "/etc") +endif() +if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR) + set(CMAKE_INSTALL_LOCALSTATEDIR "/var") +endif() + +# Standard installation paths +include(GNUInstallDirs) + +# Macros +include(FeatureSummary) + +# PKG-CONFIG +find_package(PkgConfig) +# libstatgrab +find_library(STATGRAB_LIB statgrab) + +# PAM +if(ENABLE_PAM) + find_package(PAM REQUIRED) + + if(PAM_FOUND) + add_definitions(-DUSE_PAM) + endif() +endif() +add_feature_info("PAM" PAM_FOUND "PAM support") + +# getspnam and shadow(5) support +include(CheckFunctionExists) +check_function_exists(getspnam HAVE_GETSPNAM) + +# XCB +find_package(XCB REQUIRED) +find_package(nde REQUIRED) +# XKB +find_package(XKB REQUIRED) +find_package(nde-globalkeys REQUIRED) +# XAU +find_package(XAU REQUIRED) +find_package(X11 REQUIRED) + +# Qt 5 +find_package(Qt5 5.8.0 CONFIG REQUIRED Core DBus Gui Qml Quick LinguistTools Test Network X11Extras) + +# find qt5 imports dir +get_target_property(QMAKE_EXECUTABLE Qt5::qmake LOCATION) +if(NOT QT_IMPORTS_DIR) + exec_program(${QMAKE_EXECUTABLE} ARGS "-query QT_INSTALL_QML" RETURN_VALUE return_code OUTPUT_VARIABLE QT_IMPORTS_DIR) +endif() + +# Uninstall target +if ("${ECM_VERSION}" VERSION_LESS "1.7.0") + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") +endif() + +# systemd +if(NOT NO_SYSTEMD AND NOT USE_ELOGIND) + pkg_check_modules(SYSTEMD "systemd") +endif() + +if(SYSTEMD_FOUND) + add_definitions(-DHAVE_SYSTEMD) + set(CMAKE_AUTOMOC_MOC_OPTIONS -DHAVE_SYSTEMD) + + # libsystemd-journal was merged into libsystemd in 209 + if(${SYSTEMD_VERSION} VERSION_LESS 209) + pkg_check_modules(JOURNALD "libsystemd-journal") + else() + pkg_check_modules(JOURNALD "libsystemd") + endif() + + if(ENABLE_JOURNALD) + if(JOURNALD_FOUND) + add_definitions(-DHAVE_JOURNALD) + set(CMAKE_AUTOMOC_MOC_OPTIONS -DHAVE_JOURNALD) + else() + message(WARNING "Disable journald support for lack of libsystemd-journal") + endif() + endif() + + if (NOT DEFINED SYSTEMD_SYSTEM_UNIT_DIR) + execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=systemdsystemunitdir systemd OUTPUT_VARIABLE SYSTEMD_SYSTEM_UNIT_DIR) + string(REGEX REPLACE "[ \t\n]+" "" SYSTEMD_SYSTEM_UNIT_DIR ${SYSTEMD_SYSTEM_UNIT_DIR}) + endif() + + set(MINIMUM_VT 1) + set(HALT_COMMAND "/usr/bin/systemctl poweroff") + set(REBOOT_COMMAND "/usr/bin/systemctl reboot") +else() + set(SYSTEMD_FOUND 0) +endif() +add_feature_info("systemd" SYSTEMD_FOUND "systemd support") +add_feature_info("journald" JOURNALD_FOUND "journald support") + +# elogind +if(NO_SYSTEMD AND USE_ELOGIND) + pkg_check_modules(ELOGIND "libelogind") +endif() + +if(ELOGIND_FOUND) + add_definitions(-DHAVE_ELOGIND) + set(CMAKE_AUTOMOC_MOC_OPTIONS -DHAVE_ELOGIND) + + set(MINIMUM_VT 7) + set(HALT_COMMAND "/usr/bin/loginctl poweroff") + set(REBOOT_COMMAND "/usr/bin/loginctl reboot") +endif() +add_feature_info("elogind" ELOGIND_FOUND "elogind support") + +# Default behaviour if neither systemd nor elogind is used +if (NOT ELOGIND_FOUND AND NOT SYSTEMD_FOUND) + set(MINIMUM_VT 7) + set(HALT_COMMAND "/sbin/shutdown -h -P now") + set(REBOOT_COMMAND "/sbin/shutdown -r now") +endif() + + +# Set constants +set(DATA_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/nde-screensaver" CACHE PATH "System application data install directory") +set(LOG_FILE "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/log/nss.log" CACHE PATH "Path of the nde-screensaver log file") +set(COMPONENTS_TRANSLATION_DIR "${DATA_INSTALL_DIR}/translations" CACHE PATH "Components translations directory") + + +# Autodetect UID_MIN and UID_MAX from /etc/login.defs +if(NOT DEFINED LOGIN_DEFS_PATH) + set(LOGIN_DEFS_PATH "/etc/login.defs" CACHE PATH "Path to login.defs") +endif() + +if(NOT EXISTS "${LOGIN_DEFS_PATH}" AND NOT DEFINED UID_MIN AND NOT DEFINED UID_MAX) + message(FATAL_ERROR "Could not find login.defs at ${LOGIN_DEFS_PATH}. Try -DLOGIN_DEFS_PATH.") +endif() + +if(NOT DEFINED UID_MIN) + file(STRINGS "${LOGIN_DEFS_PATH}" UID_MIN LIMIT_COUNT 1 REGEX "^UID_MIN") + string(REGEX REPLACE "^UID_MIN[\t ]+([0-9]+)" "\\1" UID_MIN "${UID_MIN}") + if(NOT UID_MIN MATCHES "[0-9]+") + message(WARNING "Could not detect a valid UID_MIN (got '${UID_MIN}'). You should review your login.defs file.") + set(UID_MIN 1000) + else() + message(STATUS "Autodetected UID_MIN=${UID_MIN} from ${LOGIN_DEFS_PATH}") + endif() +endif() + +if(NOT DEFINED UID_MAX) + file(STRINGS "${LOGIN_DEFS_PATH}" UID_MAX LIMIT_COUNT 1 REGEX "^UID_MAX") + string(REGEX REPLACE "^UID_MAX[\t ]+([0-9]+)" "\\1" UID_MAX "${UID_MAX}") + if(NOT UID_MAX MATCHES "[0-9]+") + message(WARNING "Could not detect a valid UID_MAX (got '${UID_MAX}'). You should review your login.defs file.") + set(UID_MAX 65000) + else() + message(STATUS "Autodetected UID_MAX=${UID_MAX} from ${LOGIN_DEFS_PATH}") + endif() +endif() + +add_subdirectory(data) +add_subdirectory(src) + +# Display feature summary +feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/nde-screensaver-0.1.0/cmake/FindPAM.cmake b/nde-screensaver-0.1.0/cmake/FindPAM.cmake new file mode 100644 index 0000000..f209c0b --- /dev/null +++ b/nde-screensaver-0.1.0/cmake/FindPAM.cmake @@ -0,0 +1,74 @@ +# - Try to find the PAM libraries +# Once done this will define +# +# PAM_FOUND - system has pam +# PAM_INCLUDE_DIR - the pam include directory +# PAM_LIBRARIES - libpam library + +if (PAM_INCLUDE_DIR AND PAM_LIBRARY) + # Already in cache, be silent + set(PAM_FIND_QUIETLY TRUE) +endif (PAM_INCLUDE_DIR AND PAM_LIBRARY) + +find_path(PAM_INCLUDE_DIR NAMES security/pam_appl.h pam/pam_appl.h) +find_library(PAM_LIBRARY pam) +find_library(DL_LIBRARY dl) + +if (PAM_INCLUDE_DIR AND PAM_LIBRARY) + set(PAM_FOUND TRUE) + if (DL_LIBRARY) + set(PAM_LIBRARIES ${PAM_LIBRARY} ${DL_LIBRARY}) + else (DL_LIBRARY) + set(PAM_LIBRARIES ${PAM_LIBRARY}) + endif (DL_LIBRARY) + + if (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) + # darwin claims to be something special + set(HAVE_PAM_PAM_APPL_H 1) + endif (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) + + if (NOT DEFINED PAM_MESSAGE_CONST) + include(CheckCXXSourceCompiles) + # XXX does this work with plain c? + check_cxx_source_compiles(" +#if ${HAVE_PAM_PAM_APPL_H}+0 +# include +#else +# include +#endif + +static int PAM_conv( + int num_msg, + const struct pam_message **msg, /* this is the culprit */ + struct pam_response **resp, + void *ctx) +{ + return 0; +} + +int main(void) +{ + struct pam_conv PAM_conversation = { + &PAM_conv, /* this bombs out if the above does not match */ + 0 + }; + + return 0; +} +" PAM_MESSAGE_CONST) + endif (NOT DEFINED PAM_MESSAGE_CONST) + set(PAM_MESSAGE_CONST ${PAM_MESSAGE_CONST} CACHE BOOL "PAM expects a conversation function with const pam_message") + +endif (PAM_INCLUDE_DIR AND PAM_LIBRARY) + +if (PAM_FOUND) + if (NOT PAM_FIND_QUIETLY) + message(STATUS "Found PAM: ${PAM_LIBRARIES}") + endif (NOT PAM_FIND_QUIETLY) +else (PAM_FOUND) + if (PAM_FIND_REQUIRED) + message(FATAL_ERROR "PAM was not found") + endif(PAM_FIND_REQUIRED) +endif (PAM_FOUND) + +mark_as_advanced(PAM_INCLUDE_DIR PAM_LIBRARY DL_LIBRARY PAM_MESSAGE_CONST) \ No newline at end of file diff --git a/nde-screensaver-0.1.0/cmake/FindXAU.cmake b/nde-screensaver-0.1.0/cmake/FindXAU.cmake new file mode 100644 index 0000000..03cafb7 --- /dev/null +++ b/nde-screensaver-0.1.0/cmake/FindXAU.cmake @@ -0,0 +1,54 @@ +# - Try to find libXau +# Once done this will define +# +# LIBXAU_FOUND - system has libXau +# LIBXAU_LIBRARIES - Link these to use libXau +# LIBXAU_INCLUDE_DIR - the libXau include dir +# LIBXAU_DEFINITIONS - compiler switches required for using libXau + +# Copyright (c) 2008 Helio Chissini de Castro, +# Copyright (c) 2007, Matthias Kretz, +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +IF (NOT WIN32) + IF (LIBXAU_INCLUDE_DIR AND LIBXAU_LIBRARIES) + # in cache already + SET(XAU_FIND_QUIETLY TRUE) + ENDIF (LIBXAU_INCLUDE_DIR AND LIBXAU_LIBRARIES) + + FIND_PACKAGE(PkgConfig) + PKG_CHECK_MODULES(PKG_XAU xau) + + SET(LIBXAU_DEFINITIONS ${PKG_XAU_CFLAGS}) + + FIND_PATH(LIBXAU_INCLUDE_DIR XAuth.h ${PKG_XAU_INCLUDE_DIR}) + FIND_LIBRARY(LIBXAU_LIBRARIES NAMES Xau libXau PATHS ${PKG_XAU_LIBRARY_DIRS}) + + include(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(XAU DEFAULT_MSG LIBXAU_LIBRARIES) + + MARK_AS_ADVANCED(LIBXAU_INCLUDE_DIR LIBXAU_LIBRARIES) +ENDIF (NOT WIN32) diff --git a/nde-screensaver-0.1.0/cmake/FindXAU.cmake.libxau b/nde-screensaver-0.1.0/cmake/FindXAU.cmake.libxau new file mode 100644 index 0000000..e69de29 diff --git a/nde-screensaver-0.1.0/cmake/FindXCB.cmake b/nde-screensaver-0.1.0/cmake/FindXCB.cmake new file mode 100644 index 0000000..95703ef --- /dev/null +++ b/nde-screensaver-0.1.0/cmake/FindXCB.cmake @@ -0,0 +1,54 @@ +# - Try to find libxcb +# Once done this will define +# +# LIBXCB_FOUND - system has libxcb +# LIBXCB_LIBRARIES - Link these to use libxcb +# LIBXCB_INCLUDE_DIR - the libxcb include dir +# LIBXCB_DEFINITIONS - compiler switches required for using libxcb + +# Copyright (c) 2008 Helio Chissini de Castro, +# Copyright (c) 2007, Matthias Kretz, +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +IF (NOT WIN32) + IF (LIBXCB_INCLUDE_DIR AND LIBXCB_LIBRARIES) + # in cache already + SET(XCB_FIND_QUIETLY TRUE) + ENDIF (LIBXCB_INCLUDE_DIR AND LIBXCB_LIBRARIES) + + FIND_PACKAGE(PkgConfig) + PKG_CHECK_MODULES(PKG_XCB xcb) + + SET(LIBXCB_DEFINITIONS ${PKG_XCB_CFLAGS}) + + FIND_PATH(LIBXCB_INCLUDE_DIR xcb/xcb.h ${PKG_XCB_INCLUDE_DIRS}) + FIND_LIBRARY(LIBXCB_LIBRARIES NAMES xcb libxcb PATHS ${PKG_XCB_LIBRARY_DIRS}) + + include(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(XCB DEFAULT_MSG LIBXCB_LIBRARIES LIBXCB_INCLUDE_DIR) + + MARK_AS_ADVANCED(LIBXCB_INCLUDE_DIR LIBXCB_LIBRARIES XCBPROC_EXECUTABLE) +ENDIF (NOT WIN32) diff --git a/nde-screensaver-0.1.0/cmake/FindXKB.cmake b/nde-screensaver-0.1.0/cmake/FindXKB.cmake new file mode 100644 index 0000000..dc4dcd7 --- /dev/null +++ b/nde-screensaver-0.1.0/cmake/FindXKB.cmake @@ -0,0 +1,58 @@ +# - Try to find libxcb +# Once done this will define +# +# LIBXKB_FOUND - system has libxcb +# LIBXKB_LIBRARIES - Link these to use libxcb-xkb +# LIBXKB_INCLUDE_DIR - the libxcb-xkb include dir +# LIBXKB_DEFINITIONS - compiler switches required for using libxcb + +# Copyright (c) 2013, Abdurrahman AVCI, +# Copyright (c) 2008, Helio Chissini de Castro, +# Copyright (c) 2007, Matthias Kretz, +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +IF (NOT WIN32) + IF (LIBXKB_INCLUDE_DIR AND LIBXKB_LIBRARIES) + # in cache already + SET(XKB_FIND_QUIETLY TRUE) + ENDIF (LIBXKB_INCLUDE_DIR AND LIBXKB_LIBRARIES) + + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + FIND_PACKAGE(PkgConfig) + PKG_CHECK_MODULES(PKG_XKB xcb-xkb) + + SET(LIBXKB_DEFINITIONS ${PKG_XKB_CFLAGS}) + + FIND_PATH(LIBXKB_INCLUDE_DIR xcb/xkb.h ${PKG_XKB_INCLUDE_DIRS}) + + FIND_LIBRARY(LIBXKB_LIBRARIES NAMES xcb-xkb libxcb-xkb PATHS ${PKG_XKB_LIBRARY_DIRS}) + + include(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(XKB DEFAULT_MSG LIBXKB_LIBRARIES LIBXKB_INCLUDE_DIR) + + MARK_AS_ADVANCED(LIBXKB_INCLUDE_DIR LIBXKB_LIBRARIES) +ENDIF (NOT WIN32) diff --git a/nde-screensaver-0.1.0/cmake/cmake_uninstall.cmake.in b/nde-screensaver-0.1.0/cmake/cmake_uninstall.cmake.in new file mode 100644 index 0000000..c6d8094 --- /dev/null +++ b/nde-screensaver-0.1.0/cmake/cmake_uninstall.cmake.in @@ -0,0 +1,22 @@ +if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") +endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +list(REVERSE files) +foreach (file ${files}) + message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") + if (EXISTS "$ENV{DESTDIR}${file}") + execute_process( + COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}" + OUTPUT_VARIABLE rm_out + RESULT_VARIABLE rm_retval + ) + if(NOT ${rm_retval} EQUAL 0) + message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") + endif (NOT ${rm_retval} EQUAL 0) + else (EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") + endif (EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) diff --git a/nde-screensaver-0.1.0/data/CMakeLists.txt b/nde-screensaver-0.1.0/data/CMakeLists.txt new file mode 100644 index 0000000..f0ede02 --- /dev/null +++ b/nde-screensaver-0.1.0/data/CMakeLists.txt @@ -0,0 +1,13 @@ + +install(FILES + "faces/default.face.icon.png" + DESTINATION "${DATA_INSTALL_DIR}/faces" + RENAME ".face.icon" +) +install(FILES + "autostart/nde-screensaver.desktop" + DESTINATION "${CMAKE_INSTALL_FULL_SYSCONFDIR}/xdg/autostart") + +install(FILES + "pam/nde-screensaver.pam" + DESTINATION "${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d" RENAME nde-screensaver) diff --git a/nde-screensaver-0.1.0/data/autostart/nde-screensaver.desktop b/nde-screensaver-0.1.0/data/autostart/nde-screensaver.desktop new file mode 100644 index 0000000..56d2194 --- /dev/null +++ b/nde-screensaver-0.1.0/data/autostart/nde-screensaver.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=nde-screensaver +TryExec=nde-screensaver +Exec=nde-screensaver +X-Nde-Module=true +OnlyShowIn=Nde; +Name[zh_CN]=屏幕保护程序 diff --git a/nde-screensaver-0.1.0/data/faces/default.face.icon.png b/nde-screensaver-0.1.0/data/faces/default.face.icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0064ffa5501e91044ed8562fa612d45ec482c79d GIT binary patch literal 3450 zcmaJ^c|4SB8=jan*0M*IF^mw#h{4D{c4IH9k!5By6SJ5Z*-~_5E7BOJQaWTm5!oVS z!jO+tO4d4r2$3Z_edCR0RAHDyRnC=-t#lzh3bV?`<%WYhs@@^<9(u#)nXHaOK6iV=qD!LLV3<{ksqpSakN28JUWIDs2jK$ldOdwnaZ6XnegzKTKb@fni3q1=fINaL8$j|_e zGSsuyu{?Uz5MgQa!xu%thLZ4P#t&cIe|&X+>bpA%Bq}#D3Qr@R$Kz~h6cYH)l##@r zYO%8UDc|3|xSwm$`Kd3AD+adP*#Bzu4-wqWpIxPadi63~%aQeKX`Axbd=U`+L-U*LUdQqpXhM zi97Upqse_INF`DTATDZfk$Z((iLjAo@g)^P)Tav6;Ep zbqymF8V!=$^Ua|^<90zF=TRLpXWRw4kF~4{6tS&jIu?gir@*D8q-J!21Pq9nUA|R|LG85SYwq*Qm5vL{h3HFuV&>P`?v#uNL&XfUPI>u` zJ`IIcFI;y}D!1s6+o1FUXRjKw7@JOD%;kZPl-5EFc(F45VS*R1zz&n30$53ZzDE%h zm!s>eJNgi4Wqyl%mB`z!7Yn-d{&_U)**g1Tt-VnEgp*jm<)RJrm?Y5I3gMxgrBt5M z8R*mOLKx%gB;FJR)}%LhHaof<1Si>cR!ep6xlkX$9|3*2eeB_x6QJONPra%b*0od2 zez{dK0k2Wjr%x`kqhr5EBr%gR^@V2U6PbTZU6(PK>;!I9JY|_?Sc0q0->|x<(0yRu zqoOuZQ9|`x7PFUWG(_jPY!!H)ZIa+AlQe*6QoR&hX>9&4;E3k=Q_tpWQU=^nDi03w zOd5_9VVh1XyxuWR{ljEn@!(AI$%$q$L!a5-CR09E$lz;apKhLfq$mD*-%w(mnw2;H}NcW7ItVZcGQophz_c;;dg^v%OM-+_H zCfy^P`o`1VnY{f(`%DuxeDNqX%!@cA7Jnz0=Mbmy&ZC3}RbMa!CEE!8yB|k-7NRn0 zdQq!)qy_ewIc}A&< zQO1OdL4;j~T>5&B8%}+$b^8$HVGd@-pK7H5`#RJ3V$+wCbQ#Gh=Nf9y#P_Q%gRUqQkGtQl6^_ll;a~m|EB)N_OwqUlw9@j) z!Cd>`^S>^Uq4libG^gz#-?Vq~>!(|HtW$OFAmmnNGBBmvjdxULa{?_|QeUqcKM)1| zR-Pd{XpxcyZOL^tQyVB4w@S*^%k%de_T3nHuB^DI1Qo;;A^FZ-i!LRii_^1us$}v# zE)yiq`R0P(JA|x$*7_y2VJ4@_m^G|!wVr0?pnASei$~brt$zNso*e4p{c-xf$v|(l z7a4=FJ!wk|wL(7gmZAB_Rdhr!(Az=pERKt)7&NN${Vpim>W97^!|t?_C?S=j}aR>556e}wdJzMzLpxpQB z+B}TaFwMsJA2K>2)ZdL> z?7h(BuCf1FO2J++A7+2V@Hpga42pg$sij{8*;22O#`cjry|4Y8>^3v^V5Bxrl=7fp z+1QM1F{Y$L_JO@zPw7ibAWxLgW?a#d{+*z;6#-SMal7H^#kYtfEvrN6GiHmTiRQ%} z5Cg&WCntu{ZaURnr7vVF`Q=m(=kNoa0tr5xK4JIu{xtnS@#me^N<5+qrUBU@<7dzJ z=nVSo1%591G1zf3wOmm<-h4b}*6EW0ZI%V;QNM~-M(KoJ(rv%t-z2fH-0cn$x~SBiUWZ5> z%P*nk9{|}_i%pl*##P>Z6Ke<(l5O3t`+%G4w1G`ls9aGyoT0E_gsGo)F;tV;zT3jA z{Mgwj_?jakq=I2pNs=;j=jAeMyJ)PLu=`0I;s+^sTAPgOEqSRTKy2K-Ji@EzsT)#o z#!#P1ETE#4a=_SSc$qUetjR~Yd|TBOS2R0T8&|fpb!=?TO9IFjbwn%*DfWTy(QnRA zLa;Cm9$qKtjov4)l^eCZZu$rGV*$y)F3HD=nqqsYDsdiH?B>_oEk^u|9SR%^SoYD9 z1bGo`NWAR&c$;-Lc_h1HM6b93QhCd6ynIU&-j+0`s>3!sH+DtRQsG}`zDNlc>eYaR zVxmI|+EJHleOm*bB$0T&0oeJ>h^@LAmsjyeVmi&DIA@4blOQ2imp3z?9R9$Vg?1OWwQ07yB>XNHGi+9cZ z7p|}|7xCh&-FyNViDSk@7WcNIPBQy)*y8K!ufur?nH%pVX7Pobroqt}?%sy%t({R1E&VS48!v4A2mk;8 literal 0 HcmV?d00001 diff --git a/nde-screensaver-0.1.0/data/pam/nde-screensaver.pam b/nde-screensaver-0.1.0/data/pam/nde-screensaver.pam new file mode 100644 index 0000000..35c5fab --- /dev/null +++ b/nde-screensaver-0.1.0/data/pam/nde-screensaver.pam @@ -0,0 +1,15 @@ +#%PAM-1.0 +auth required pam_env.so +auth sufficient pam_rootok.so +# Uncomment the following line to implicitly trust users in the "wheel" group. +#auth sufficient pam_wheel.so trust use_uid +# Uncomment the following line to require a user to be in the "wheel" group. +#auth required pam_wheel.so use_uid +auth substack system-auth +auth include postlogin +account sufficient pam_succeed_if.so uid = 0 use_uid quiet +account include system-auth +password include system-auth +session include system-auth +session include postlogin +session optional pam_xauth.so diff --git a/nde-screensaver-0.1.0/src/CMakeLists.txt b/nde-screensaver-0.1.0/src/CMakeLists.txt new file mode 100644 index 0000000..35e0c5c --- /dev/null +++ b/nde-screensaver-0.1.0/src/CMakeLists.txt @@ -0,0 +1,10 @@ +configure_file("common/Constants.h.in" "common/Constants.h" IMMEDIATE @ONLY) + +#add_subdirectory(daemon) +add_subdirectory(greeter) +add_subdirectory(helper) +add_subdirectory(nde-screensaver) +#add_subdirectory(autologin) +#add_subdirectory(udstokenserver) +#add_subdirectory(getToken) +#add_subdirectory(vmdaemon) diff --git a/nde-screensaver-0.1.0/src/auth/Auth.cpp b/nde-screensaver-0.1.0/src/auth/Auth.cpp new file mode 100644 index 0000000..bc69f11 --- /dev/null +++ b/nde-screensaver-0.1.0/src/auth/Auth.cpp @@ -0,0 +1,303 @@ +/* + * Qt Authentication Library + * Copyright (C) 2013 Martin Bříza + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "Auth.h" +#include "Constants.h" +#include "AuthMessages.h" +#include "SafeDataStream.h" + +#include +#include +#include +#include + +#include + +#include + +namespace NSS { + class Auth::SocketServer : public QLocalServer { + Q_OBJECT + public slots: + void handleNewConnection(); + public: + static SocketServer *instance(); + + QMap helpers; + private: + static Auth::SocketServer *self; + SocketServer(); + }; + + Auth::SocketServer *Auth::SocketServer::self = nullptr; + + class Auth::Private : public QObject { + Q_OBJECT + public: + Private(Auth *parent); + ~Private(); + void setSocket(QLocalSocket *socket); + public slots: + void dataPending(); + void childExited(int exitCode, QProcess::ExitStatus exitStatus); + void childError(QProcess::ProcessError error); + void requestFinished(); + public: + AuthRequest *request { nullptr }; + QProcess *child { nullptr }; + QLocalSocket *socket { nullptr }; + QString user { }; + QString cookie { }; + QProcessEnvironment environment { }; + qint64 id { 0 }; + static qint64 lastId; + }; + qint64 Auth::Private::lastId = 1; + Auth::SocketServer::SocketServer() + : QLocalServer() { + connect(this, SIGNAL(newConnection()), this, SLOT(handleNewConnection())); + } + + void Auth::SocketServer::handleNewConnection() { + while (hasPendingConnections()) { + Msg m = Msg::MSG_UNKNOWN; + qint64 id; + QLocalSocket *socket = nextPendingConnection(); + SafeDataStream str(socket); + str.receive(); + str >> m >> id; + if (m == Msg::HELLO && id && SocketServer::instance()->helpers.contains(id)) { + helpers[id]->setSocket(socket); + if (socket->bytesAvailable() > 0) + helpers[id]->dataPending(); + } + } + } + + Auth::SocketServer* Auth::SocketServer::instance() { + if (!self) { + self = new SocketServer(); + self->listen(QStringLiteral("nss-auth%1").arg(QUuid::createUuid().toString().replace(QRegExp(QStringLiteral("[{}]")), QString()))); + } + return self; + } + + + Auth::Private::Private(Auth *parent) + : QObject(parent) + , request(new AuthRequest(parent)) + , child(new QProcess(this)) + , id(lastId++){ + SocketServer::instance()->helpers[id] = this; + QProcessEnvironment env = child->processEnvironment(); + bool langEmpty = true; + QFile localeFile(QStringLiteral("/etc/locale.conf")); + if (localeFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&localeFile); + while (!in.atEnd()) { + QStringList parts = in.readLine().split(QLatin1Char('=')); + if (parts.size() >= 2) { + env.insert(parts[0], parts[1]); + if (parts[0] == QLatin1String("LANG")) + langEmpty = false; + } + } + localeFile.close(); + } + if (langEmpty) + env.insert(QStringLiteral("LANG"), QStringLiteral("C")); + child->setProcessEnvironment(env); + connect(child, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(childExited(int,QProcess::ExitStatus))); + connect(child, SIGNAL(error(QProcess::ProcessError)), this, SLOT(childError(QProcess::ProcessError))); + connect(request, SIGNAL(finished()), this, SLOT(requestFinished())); + connect(request, SIGNAL(promptsChanged()), parent, SIGNAL(requestChanged())); + } + + Auth::Private::~Private() + { + SocketServer::instance()->helpers.remove(id); + } + + + void Auth::Private::setSocket(QLocalSocket *socket) { + this->socket = socket; + connect(socket, SIGNAL(readyRead()), this, SLOT(dataPending())); + } + + void Auth::Private::dataPending() { + Auth *auth = qobject_cast(parent()); + Msg m = MSG_UNKNOWN; + SafeDataStream str(socket); + str.receive(); + str >> m; + switch (m) { + case ERROR: { + QString message; + Error type = ERROR_NONE; + str >> message >> type; + Q_EMIT auth->error(message, type); + break; + } + case INFO: { + QString message; + Info type = INFO_NONE; + str >> message >> type; + Q_EMIT auth->info(message, type); + break; + } + case REQUEST: { + Request r; + str >> r; + request->setRequest(&r); + break; + } + case AUTHENTICATED: { + QString user; + str >> user; + if (!user.isEmpty()) { + auth->setUser(user); + Q_EMIT auth->authentication(user, true); + str.reset(); + str << AUTHENTICATED << environment << cookie; + str.send(); + } + else { + Q_EMIT auth->authentication(user, false); + } + break; + } + default: { + Q_EMIT auth->error(QStringLiteral("Auth: Unexpected value received: %1").arg(m), ERROR_INTERNAL); + } + } + } + + void Auth::Private::childExited(int exitCode, QProcess::ExitStatus exitStatus) { + if (exitStatus != QProcess::NormalExit) { + qWarning("Auth: nde-screensaver-helper crashed (exit code %d)", exitCode); + Q_EMIT qobject_cast(parent())->error(child->errorString(), ERROR_INTERNAL); + } + + if (exitCode == HELPER_SUCCESS) + qDebug() << "Auth: nde-screensaver-helper exited successfully"; + else + { + qWarning("Auth: nde-screensaver-helper exited with %d", exitCode); + Q_EMIT qobject_cast(parent())->error("", ERROR_UNKNOWN); + } + + Q_EMIT qobject_cast(parent())->finished((Auth::HelperExitStatus)exitCode); + } + + void Auth::Private::childError(QProcess::ProcessError error) { + Q_UNUSED(error) + Q_EMIT qobject_cast(parent())->error(child->errorString(), ERROR_INTERNAL); + } + + void Auth::Private::requestFinished() { + SafeDataStream str(socket); + Request r = request->request(); + str << REQUEST << r; + str.send(); + request->setRequest(); + } + + + Auth::Auth(const QString &user, QObject *parent, bool verbose) + : QObject(parent) + , d(new Private(this)) { + setUser(user); + setVerbose(verbose); + } + + Auth::Auth(QObject* parent) + : QObject(parent) + , d(new Private(this)) { + } + + Auth::~Auth() { + delete d; + } + + void Auth::registerTypes() { + qmlRegisterType(); + qmlRegisterType(); + qmlRegisterType("Auth", 1, 0, "Auth"); + } + + const QString& Auth::cookie() const { + return d->cookie; + } + + const QString &Auth::user() const { + return d->user; + } + + bool Auth::verbose() const { + return d->child->processChannelMode() == QProcess::ForwardedChannels; + } + + AuthRequest *Auth::request() { + return d->request; + } + + void Auth::insertEnvironment(const QProcessEnvironment &env) { + d->environment.insert(env); + } + + void Auth::insertEnvironment(const QString &key, const QString &value) { + d->environment.insert(key, value); + } + + void Auth::setCookie(const QString& cookie) { + if (cookie != d->cookie) { + d->cookie = cookie; + Q_EMIT cookieChanged(); + } + } + + void Auth::setUser(const QString &user) { + if (user != d->user) { + d->user = user; + Q_EMIT userChanged(); + } + } + void Auth::setVerbose(bool on) { + if (on != verbose()) { + if (on) + d->child->setProcessChannelMode(QProcess::ForwardedChannels); + else + d->child->setProcessChannelMode(QProcess::SeparateChannels); + Q_EMIT verboseChanged(); + } + } + + void Auth::start() { + QStringList args; + args << QStringLiteral("--socket") << SocketServer::instance()->fullServerName(); + args << QStringLiteral("--id") << QStringLiteral("%1").arg(d->id); + if (!d->user.isEmpty()) + args << QStringLiteral("--user") << d->user; + qWarning() << QStringLiteral("%1/nde-screensaver-helper").arg(QStringLiteral(LIBEXEC_INSTALL_DIR)) << args; + d->child->start(QStringLiteral("%1/nde-screensaver-helper").arg(QStringLiteral(LIBEXEC_INSTALL_DIR)), args); + } +} + +#include "Auth.moc" diff --git a/nde-screensaver-0.1.0/src/auth/Auth.h b/nde-screensaver-0.1.0/src/auth/Auth.h new file mode 100644 index 0000000..33a9503 --- /dev/null +++ b/nde-screensaver-0.1.0/src/auth/Auth.h @@ -0,0 +1,140 @@ +#ifndef NSS_AUTH_H +#define NSS_AUTH_H + +#include "AuthRequest.h" +#include "AuthPrompt.h" + +#include +#include + +namespace NSS { + + class Auth : public QObject { + Q_OBJECT + Q_PROPERTY(bool verbose READ verbose WRITE setVerbose NOTIFY verboseChanged) + Q_PROPERTY(QString cookie READ cookie WRITE setCookie NOTIFY cookieChanged) + Q_PROPERTY(QString user READ user WRITE setUser NOTIFY userChanged) + Q_PROPERTY(AuthRequest* request READ request NOTIFY requestChanged) + public: + explicit Auth(const QString &user = QString(), QObject *parent = 0, bool verbose = false); + explicit Auth(QObject *parent); + ~Auth(); + + enum Info { + INFO_NONE = 0, + INFO_UNKNOWN, + INFO_PASS_CHANGE_REQUIRED, + _INFO_LAST + }; + + enum Error { + ERROR_NONE = 0, + ERROR_UNKNOWN, + ERROR_AUTHENTICATION, + ERROR_INTERNAL, + _ERROR_LAST + }; + + enum HelperExitStatus { + HELPER_SUCCESS = 0, + HELPER_AUTH_ERROR, + HELPER_SESSION_ERROR, + HELPER_OTHER_ERROR + }; + + static void registerTypes(); + + bool verbose() const; + const QString &cookie() const; + const QString &user() const; + AuthRequest *request(); + + /** + * If starting a session, you will probably want to provide some basic env variables for the session. + * This only inserts the variables - if the current key already had a value, it will be overwritten. + * User-specific data such as $HOME is generated automatically. + * @param env the environment + */ + void insertEnvironment(const QProcessEnvironment &env); + + /** + * Works the same as \ref insertEnvironment but only for one key-value pair + * @param key key + * @param value value + */ + void insertEnvironment(const QString &key, const QString &value); + + /** + * Forwards the output of the underlying authenticator to the current process + * @param on true if should forward the output + */ + void setVerbose(bool on = true); + + /** + * Sets the user which will then authenticate + * @param user username + */ + void setUser(const QString &user); + + + /** + * Set the display server cookie, to be inserted into the user's $XAUTHORITY + * @param cookie cookie data + */ + void setCookie(const QString &cookie); + + public Q_SLOTS: + /** + * Sets up the environment and starts the authentication + */ + void start(); + + Q_SIGNALS: + void verboseChanged(); + void cookieChanged(); + void userChanged(); + void requestChanged(); + + /** + * Emitted when authentication phase finishes + * + * @note If you want to set some environment variables for the session right before the + * session is started, connect to this signal using a blocking connection and insert anything + * you need in the slot. + * @param user username + * @param success true if succeeded + */ + void authentication(QString user, bool success); + + /** + * Emitted when the helper quits, either after authentication or when the session ends. + * Or, when something goes wrong. + * + * @param success true if every underlying task went fine + */ + void finished(Auth::HelperExitStatus status); + + /** + * Emitted on error + * + * @param message message to be displayed to the user + */ + void error(QString message, Auth::Error type); + + /** + * Information from the underlying stack is to be presented to the user + * + * @param message message to be displayed to the user + */ + void info(QString message, Auth::Info type); + + private: + class Private; + class SocketServer; + friend Private; + friend SocketServer; + Private *d { nullptr }; + }; +} + +#endif // NSS_AUTH_H diff --git a/nde-screensaver-0.1.0/src/auth/AuthMessages.h b/nde-screensaver-0.1.0/src/auth/AuthMessages.h new file mode 100644 index 0000000..0f86e8b --- /dev/null +++ b/nde-screensaver-0.1.0/src/auth/AuthMessages.h @@ -0,0 +1,213 @@ +/* + * Message IDs to pass between the library and the helper + * Copyright (C) 2013 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef MESSAGES_H +#define MESSAGES_H + +#include +#include + +#include "Auth.h" + +namespace NSS { + class Prompt { + public: + Prompt() { } + Prompt(AuthPrompt::Type type, QString message, bool hidden) + : type(type), message(message), hidden(hidden) { } + Prompt(const Prompt &o) + : type(o.type), response(o.response), message(o.message), hidden(o.hidden) { } + ~Prompt() { + clear(); + } + Prompt& operator=(const Prompt &o) { + type = o.type; + response = o.response; + message = o.message; + hidden = o.hidden; + return *this; + } + bool operator==(const Prompt &o) const { + return type == o.type && response == o.response && message == o.message && hidden == o.hidden; + } + bool valid() const { + return !(type == AuthPrompt::NONE && response.isEmpty() && message.isEmpty()); + } + void clear() { + type = AuthPrompt::NONE; + // overwrite the whole thing with zeroes before clearing + memset(response.data(), 0, response.length()); + response.clear(); + message.clear(); + hidden = false; + } + + AuthPrompt::Type type { AuthPrompt::NONE }; + QByteArray response { }; + QString message { }; + bool hidden { false }; + }; + + class Request { + public: + Request() { } + Request(QList prompts) + : prompts(prompts) { } + Request(const Request &o) + : prompts(o.prompts) { } + Request& operator=(const Request &o) { + prompts = QList(o.prompts); + return *this; + } + bool operator==(const Request &o) const { + return prompts == o.prompts; + } + bool valid() const { + return !(prompts.isEmpty()); + } + void clear() { + prompts.clear(); + } + + QList prompts { }; + }; + + enum Msg { + MSG_UNKNOWN = 0, + HELLO = 1, + ERROR, + INFO, + REQUEST, + AUTHENTICATED, + MSG_LAST, + }; + + inline QDataStream& operator<<(QDataStream &s, const Msg &m) { + s << qint32(m); + return s; + } + + inline QDataStream& operator>>(QDataStream &s, Msg &m) { + // TODO seriously? + qint32 i; + s >> i; + if (i >= MSG_LAST || i <= MSG_UNKNOWN) { + s.setStatus(QDataStream::ReadCorruptData); + return s; + } + m = Msg(i); + return s; + } + + inline QDataStream& operator<<(QDataStream &s, const Auth::Error &m) { + s << qint32(m); + return s; + } + + inline QDataStream& operator>>(QDataStream &s, Auth::Error &m) { + // TODO seriously? + qint32 i; + s >> i; + if (i >= Auth::_ERROR_LAST || i < Auth::ERROR_NONE) { + s.setStatus(QDataStream::ReadCorruptData); + return s; + } + m = Auth::Error(i); + return s; + } + + inline QDataStream& operator<<(QDataStream &s, const Auth::Info &m) { + s << qint32(m); + return s; + } + + inline QDataStream& operator>>(QDataStream &s, Auth::Info &m) { + // TODO seriously? + qint32 i; + s >> i; + if (i >= Auth::_INFO_LAST || i < Auth::INFO_NONE) { + s.setStatus(QDataStream::ReadCorruptData); + return s; + } + m = Auth::Info(i); + return s; + } + + inline QDataStream& operator<<(QDataStream &s, const QProcessEnvironment &m) { + s << m.toStringList(); + return s; + } + + inline QDataStream& operator>>(QDataStream &s, QProcessEnvironment &m) { + QStringList l; + s >> l; + for (QString s : l) { + int pos = s.indexOf(QLatin1Char('=')); + m.insert(s.left(pos), s.mid(pos + 1)); + } + return s; + } + + inline QDataStream& operator<<(QDataStream &s, const Prompt &m) { + s << qint32(m.type) << m.message << m.hidden << m.response; + return s; + } + + inline QDataStream& operator>>(QDataStream &s, Prompt &m) { + qint32 type; + QString message; + bool hidden; + QByteArray response; + s >> type >> message >> hidden >> response; + m.type = AuthPrompt::Type(type); + m.message = message; + m.hidden = hidden; + m.response = response; + return s; + } + + inline QDataStream& operator<<(QDataStream &s, const Request &m) { + qint32 length = m.prompts.length(); + s << length; + Q_FOREACH(Prompt p, m.prompts) { + s << p; + } + return s; + } + + inline QDataStream& operator>>(QDataStream &s, Request &m) { + QList prompts; + qint32 length; + s >> length; + for (int i = 0; i < length; i++) { + Prompt p; + s >> p; + prompts << p; + } + if (prompts.length() != length) { + s.setStatus(QDataStream::ReadCorruptData); + return s; + } + m.prompts = prompts; + return s; + } +} + +#endif // MESSAGES_H diff --git a/nde-screensaver-0.1.0/src/auth/AuthPrompt.cpp b/nde-screensaver-0.1.0/src/auth/AuthPrompt.cpp new file mode 100644 index 0000000..43c3fb5 --- /dev/null +++ b/nde-screensaver-0.1.0/src/auth/AuthPrompt.cpp @@ -0,0 +1,72 @@ +/* + * Qt Authentication Library + * Copyright (C) 2013 Martin Bříza + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "AuthPrompt.h" +#include "Auth.h" +#include "AuthMessages.h" + +namespace NSS { + class AuthPrompt::Private : public Prompt { + public: + Private(const Prompt *p) { + // initializers are too mainstream i guess + type = p->type; + hidden = p->hidden; + message = p->message; + response = p->response; + } + }; + + AuthPrompt::AuthPrompt(const Prompt *prompt, AuthRequest *parent) + : QObject(parent) + , d(new Private(prompt)) { + } + + AuthPrompt::~AuthPrompt() { + delete d; + } + + AuthPrompt::Type AuthPrompt::type() const { + return d->type; + } + + QString AuthPrompt::message() const { + return d->message; + } + + QByteArray AuthPrompt::response() const { + return d->response; + } + + QByteArray AuthPrompt::responseFake() { + return QByteArray(); + } + + void AuthPrompt::setResponse(const QByteArray &r) { + if (r != d->response) { + d->response = r; + Q_EMIT responseChanged(); + } + } + + bool AuthPrompt::hidden() const { + return d->hidden; + } +} diff --git a/nde-screensaver-0.1.0/src/auth/AuthPrompt.h b/nde-screensaver-0.1.0/src/auth/AuthPrompt.h new file mode 100644 index 0000000..e2158bd --- /dev/null +++ b/nde-screensaver-0.1.0/src/auth/AuthPrompt.h @@ -0,0 +1,102 @@ +/* + * + * Copyright (C) 2013 Martin Bříza + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef PROMPT_H +#define PROMPT_H + +#include + +namespace NSS { + class Auth; + class AuthRequest; + class Prompt; + /** + * \brief + * One prompt input for the authentication + * + * \section description + * The main, not completely obvious rationale for this class is: + * + * \warning Don't use the \ref message property if you have your own strings for + * the \ref Type -s. PAM sends horrible horrible stuff and passwd obviously + * doesn't tell us a thing. + */ + class AuthPrompt : public QObject { + Q_OBJECT + Q_ENUMS(Type) + Q_PROPERTY(Type type READ type CONSTANT) + Q_PROPERTY(QString message READ message CONSTANT) + Q_PROPERTY(bool hidden READ hidden CONSTANT) + Q_PROPERTY(QByteArray response READ responseFake WRITE setResponse NOTIFY responseChanged) + public: + virtual ~AuthPrompt(); + /** + * \note In hex not for binary operations but to leave space for adding other codes + */ + enum Type { + NONE = 0x0000, ///< No type + UNKNOWN = 0x0001, ///< Unknown type + CHANGE_CURRENT = 0x0010, ///< On changing the password: Current one + CHANGE_NEW, ///< On changing the password: The new one + CHANGE_REPEAT, ///< On changing the password: The new one, repeated + LOGIN_USER = 0x0080, ///< On logging in: The username + LOGIN_PASSWORD ///< On logging in: The password + }; + /** + * @return the type of the prompt + */ + Type type() const; + /** + * @warning the preferred way is to use \ref type + * @return message from the stack + */ + QString message() const; + /** + * @return true if user's input should not be shown in readable form + */ + bool hidden() const; + /** + * Public getter for the response data. + * The property is write-only though, so it returns garbage. + * Contained only to keep the MOC parser happy. + * @warning do not use, doesn't return valid data + * @return empty byte array + */ + QByteArray responseFake(); + /** + * Setter for the response data + * @param r data entered by the user + */ + void setResponse(const QByteArray &r); + Q_SIGNALS: + /** + * Emitted when the response was entered by the user + */ + void responseChanged(); + private: + AuthPrompt(const Prompt *prompt, AuthRequest *parent = 0); + QByteArray response() const; + friend class AuthRequest; + class Private; + Private *d { nullptr }; + }; +} + +#endif //PROMPT_H \ No newline at end of file diff --git a/nde-screensaver-0.1.0/src/auth/AuthRequest.cpp b/nde-screensaver-0.1.0/src/auth/AuthRequest.cpp new file mode 100644 index 0000000..886171d --- /dev/null +++ b/nde-screensaver-0.1.0/src/auth/AuthRequest.cpp @@ -0,0 +1,111 @@ +/* + * Qt Authentication Library + * Copyright (C) 2013 Martin Bříza + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "AuthRequest.h" +#include "Auth.h" +#include "AuthMessages.h" + +namespace NSS { + class AuthRequest::Private : public QObject { + Q_OBJECT + public slots: + void responseChanged(); + public: + Private(QObject *parent); + QList prompts { }; + bool finishAutomatically { false }; + bool finished { true }; + }; + + AuthRequest::Private::Private(QObject* parent) + : QObject(parent) { } + + void AuthRequest::Private::responseChanged() { + Q_FOREACH(AuthPrompt *qap, prompts) { + if (qap->response().isEmpty()) + return; + } + if (finishAutomatically && prompts.length() > 0) + qobject_cast(parent())->done(); + } + + AuthRequest::AuthRequest(Auth *parent) + : QObject(parent) + , d(new Private(this)) { } + + void AuthRequest::setRequest(const Request *request) { + QList promptsCopy(d->prompts); + d->prompts.clear(); + if (request != nullptr) { + Q_FOREACH (const Prompt& p, request->prompts) { + AuthPrompt *qap = new AuthPrompt(&p, this); + d->prompts << qap; + if (finishAutomatically()) + connect(qap, SIGNAL(responseChanged()), d, SLOT(responseChanged())); + } + d->finished = false; + } + Q_EMIT promptsChanged(); + if (request == nullptr) { + qDeleteAll(promptsCopy); + } + } + + QList AuthRequest::prompts() { + return d->prompts; + } + + QQmlListProperty AuthRequest::promptsDecl() { + return QQmlListProperty(this, d->prompts); + } + + void AuthRequest::done() { + if (!d->finished) { + d->finished = true; + Q_EMIT finished(); + } + } + + bool AuthRequest::finishAutomatically() { + return d->finishAutomatically; + } + + void AuthRequest::setFinishAutomatically(bool value) { + if (value != d->finishAutomatically) { + d->finishAutomatically = value; + Q_EMIT finishAutomaticallyChanged(); + } + } + + Request AuthRequest::request() const { + Request r; + Q_FOREACH (const AuthPrompt* qap, d->prompts) { + Prompt p; + p.hidden = qap->hidden(); + p.message = qap->message(); + p.response = qap->response(); + p.type = qap->type(); + r.prompts << p; + } + return r; + } +} + +#include "AuthRequest.moc" diff --git a/nde-screensaver-0.1.0/src/auth/AuthRequest.h b/nde-screensaver-0.1.0/src/auth/AuthRequest.h new file mode 100644 index 0000000..801c393 --- /dev/null +++ b/nde-screensaver-0.1.0/src/auth/AuthRequest.h @@ -0,0 +1,94 @@ +/* + * Qt Authentication library + * Copyright (C) 2013 Martin Bříza + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef REQUEST_H +#define REQUEST_H + +#include + +#include + +namespace NSS { + class Auth; + class AuthPrompt; + class Request; + /** + * \brief + * AuthRequest is the main class for tracking requests from the underlying auth stack + * + * \section description + * Typically, when logging in, you'll receive a list containing one or two fields: + * + * * First one for the username (if you didn't provide it before); + * hidden = false, type = LOGIN_USER, message = whatever the stack provides + * + * * Second one for the user's password + * hidden = true, type = LOGIN_PASSWORD, message = whatever the stack provides + * + * It's up to you to fill the \ref AuthPrompt::response property. + * When all the fields are filled to your satisfaction, just trigger the \ref done + * slot and the response will go back to the authenticator. + * + * \todo Decide if it's sane to use the info messages from PAM or to somehow parse them + * and make the password changing message into a Request::Type of some kind + */ + class AuthRequest : public QObject { + Q_OBJECT + Q_PROPERTY(QQmlListProperty prompts READ promptsDecl NOTIFY promptsChanged) + Q_PROPERTY(bool finishAutomatically READ finishAutomatically WRITE setFinishAutomatically NOTIFY finishAutomaticallyChanged) + public: + /** + * @return list of the contained prompts + */ + QList prompts(); + /** + * For QML apps + * @return list of the contained prompts + */ + QQmlListProperty promptsDecl(); + + static AuthRequest *empty(); + + bool finishAutomatically(); + void setFinishAutomatically(bool value); + public Q_SLOTS: + /** + * Call this slot when all prompts has been filled to your satisfaction + */ + void done(); + Q_SIGNALS: + /** + * Emitted when \ref done was called + */ + void finished(); + + void finishAutomaticallyChanged(); + void promptsChanged(); + private: + AuthRequest(Auth *parent); + void setRequest(const Request *request = nullptr); + Request request() const; + friend class Auth; + class Private; + Private *d { nullptr }; + }; +} + +#endif //REQUEST_H diff --git a/nde-screensaver-0.1.0/src/common/Constants.h.in b/nde-screensaver-0.1.0/src/common/Constants.h.in new file mode 100644 index 0000000..5ae4b47 --- /dev/null +++ b/nde-screensaver-0.1.0/src/common/Constants.h.in @@ -0,0 +1,39 @@ +/*************************************************************************** +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef NSS_CONSTANTS_H +#define NSS_CONSTANTS_H + +#define BIN_INSTALL_DIR "@CMAKE_INSTALL_FULL_BINDIR@" +#define LIBEXEC_INSTALL_DIR "@CMAKE_INSTALL_FULL_LIBEXECDIR@" +#define DATA_INSTALL_DIR "@DATA_INSTALL_DIR@" +#define SYS_CONFIG_DIR "@CMAKE_INSTALL_FULL_SYSCONFDIR@" +#define IMPORTS_INSTALL_DIR "@QT_IMPORTS_DIR@" +#define COMPONENTS_TRANSLATION_DIR "@COMPONENTS_TRANSLATION_DIR@" + +#define LOG_FILE "@LOG_FILE@" +#define MINIMUM_VT @MINIMUM_VT@ + +#define UID_MIN @UID_MIN@ +#define UID_MAX @UID_MAX@ + +#define HALT_COMMAND "@HALT_COMMAND@" +#define REBOOT_COMMAND "@REBOOT_COMMAND@" + +#endif // NSS_CONSTANTS_H diff --git a/nde-screensaver-0.1.0/src/common/MessageHandler.h b/nde-screensaver-0.1.0/src/common/MessageHandler.h new file mode 100644 index 0000000..ea87b42 --- /dev/null +++ b/nde-screensaver-0.1.0/src/common/MessageHandler.h @@ -0,0 +1,117 @@ +#ifndef NSS_MESSAGEHANDLER_H +#define NSS_MESSAGEHANDLER_H + +#include "Constants.h" + +#include +#include + +#include + +#ifdef HAVE_JOURNALD +#include +#include +#endif + +namespace NSS { +#ifdef HAVE_JOURNALD + static void journaldLogger(QtMsgType type, const QMessageLogContext &context, const QString &msg) { + int priority = LOG_INFO; + switch (type) { + case QtDebugMsg: + priority = LOG_DEBUG; + break; + case QtWarningMsg: + priority = LOG_WARNING; + break; + case QtCriticalMsg: + priority = LOG_CRIT; + break; + case QtFatalMsg: + priority = LOG_ALERT; + break; + default: + break; + } + + char fileBuffer[PATH_MAX + sizeof("CODE_FILE=")]; + snprintf(fileBuffer, sizeof(fileBuffer), "CODE_FILE=%s", context.file ? context.file : "unknown"); + + char lineBuffer[32]; + snprintf(lineBuffer, sizeof(lineBuffer), "CODE_LINE=%d", context.line); + + sd_journal_print_with_location(priority, fileBuffer, lineBuffer, + context.function ? context.function : "unknown", + "%s", qPrintable(msg)); + } +#endif + + static void standardLogger(QtMsgType type, const QString &msg) { + static QFile file(QStringLiteral(LOG_FILE)); + + // try to open file only if it's not already open + if (!file.isOpen()) { + if (!file.open(QFile::Append | QFile::WriteOnly)) + file.open(QFile::Truncate | QFile::WriteOnly); + } + + // create timestamp + QString timestamp = QDateTime::currentDateTime().toString(QStringLiteral("hh:mm:ss.zzz")); + + // set log priority + QString logPriority = QStringLiteral("(II)"); + switch (type) { + case QtDebugMsg: + break; + case QtWarningMsg: + logPriority = QStringLiteral("(WW)"); + break; + case QtCriticalMsg: + case QtFatalMsg: + logPriority = QStringLiteral("(EE)"); + break; + default: + break; + } + + // prepare log message + QString logMessage = QStringLiteral("[%1] %2 %3\n").arg(timestamp).arg(logPriority).arg(msg); + + // log message + if (file.isOpen()) { + file.write(logMessage.toLocal8Bit()); + file.flush(); + } else { + printf("%s", qPrintable(logMessage)); + fflush(stdout); + } + } + + static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &prefix, const QString &msg) { + QString logMessage = msg; + +#ifdef HAVE_JOURNALD + journaldLogger(type, context, logMessage); +#else + // prepend program name + logMessage = prefix + msg; + + // log to file or stdout + standardLogger(type, logMessage); +#endif + } + + void DaemonMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { + messageHandler(type, context, QStringLiteral("DAEMON: "), msg); + } + + void HelperMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { + messageHandler(type, context, QStringLiteral("HELPER: "), msg); + } + + void GreeterMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { + messageHandler(type, context, QStringLiteral("GREETER: "), msg); + } +} + +#endif // NSS_MESSAGEHANDLER_H diff --git a/nde-screensaver-0.1.0/src/common/Messages.h b/nde-screensaver-0.1.0/src/common/Messages.h new file mode 100644 index 0000000..d533639 --- /dev/null +++ b/nde-screensaver-0.1.0/src/common/Messages.h @@ -0,0 +1,57 @@ +/*************************************************************************** +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef NSS_MESSAGES_H +#define NSS_MESSAGES_H + +#include + +namespace NSS { + enum class GreeterMessages { + Connect = 0, + Login, + PowerOff, + Reboot, + Suspend, + Hibernate, + HybridSleep + }; + + enum class DaemonMessages { + HostName, + Capabilities, + LoggingIn, + LoginSucceeded, + LoginFailed + }; + + enum Capability { + None = 0x0000, + PowerOff = 0x0001, + Reboot = 0x0002, + Suspend = 0x0004, + Hibernate = 0x0008, + HybridSleep = 0x0010 + }; + + Q_DECLARE_FLAGS(Capabilities, Capability) + Q_DECLARE_OPERATORS_FOR_FLAGS(Capabilities) +} + +#endif // NSS_MESSAGES_H diff --git a/nde-screensaver-0.1.0/src/common/SafeDataStream.cpp b/nde-screensaver-0.1.0/src/common/SafeDataStream.cpp new file mode 100644 index 0000000..96a6ebe --- /dev/null +++ b/nde-screensaver-0.1.0/src/common/SafeDataStream.cpp @@ -0,0 +1,82 @@ +/* + * QDataStream implementation for safe socket operation + * Copyright (C) 2014 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "SafeDataStream.h" + +#include + +namespace NSS { + SafeDataStream::SafeDataStream(QIODevice* device) + : QDataStream(&m_data, QIODevice::ReadWrite) + , m_device(device) { } + + void SafeDataStream::send() { + qint64 length = m_data.length(); + qint64 writtenTotal = 0; + if (!m_device->isOpen()) { + qCritical() << " Auth: SafeDataStream: Could not write any data"; + return; + } + m_device->write((const char*) &length, sizeof(length)); + while (writtenTotal != length) { + qint64 written = m_device->write(m_data.mid(writtenTotal)); + if (written < 0 || !m_device->isOpen()) { + qCritical() << " Auth: SafeDataStream: Could not write all stored data"; + return; + } + writtenTotal += written; + m_device->waitForBytesWritten(-1); + } + + reset(); + } + + void SafeDataStream::receive() { + qint64 length = -1; + + if (!m_device->isOpen()) { + qCritical() << " Auth: SafeDataStream: Could not read from the device"; + return; + } + if (!m_device->bytesAvailable()) + m_device->waitForReadyRead(-1); + m_device->read((char*) &length, sizeof(length)); + + if (length < 0) + return; + reset(); + + while (m_data.length() < length) { + if (!m_device->isOpen()) { + qCritical() << " Auth: SafeDataStream: Could not read from the device"; + return; + } + if (!m_device->bytesAvailable()) + m_device->waitForReadyRead(-1); + m_data.append(m_device->read(length - m_data.length())); + } + } + + void SafeDataStream::reset() { + m_data.clear(); + device()->reset(); + resetStatus(); + } +} diff --git a/nde-screensaver-0.1.0/src/common/SafeDataStream.h b/nde-screensaver-0.1.0/src/common/SafeDataStream.h new file mode 100644 index 0000000..e664aeb --- /dev/null +++ b/nde-screensaver-0.1.0/src/common/SafeDataStream.h @@ -0,0 +1,40 @@ +/* + * QDataStream implementation for safe socket operation + * Copyright (C) 2014 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef SAFEDATASTREAM_H +#define SAFEDATASTREAM_H + +#include + +namespace NSS { + class SafeDataStream : public QDataStream { + public: + SafeDataStream(QIODevice* device); + void send(); + void receive(); + void reset(); + + private: + QByteArray m_data { }; + QIODevice *m_device { nullptr }; + }; +} + +#endif // SAFEDATASTREAM_H diff --git a/nde-screensaver-0.1.0/src/common/SocketWriter.cpp b/nde-screensaver-0.1.0/src/common/SocketWriter.cpp new file mode 100644 index 0000000..ea6fc21 --- /dev/null +++ b/nde-screensaver-0.1.0/src/common/SocketWriter.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** +* Copyright (c) 2015 Pier Luigi Fiorini +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include "SocketWriter.h" +#include + +namespace NSS { + SocketWriter::SocketWriter(QLocalSocket *socket) : socket(socket) { + output = new QDataStream(&data, QIODevice::WriteOnly); + } + + SocketWriter::~SocketWriter() { + socket->write(data); + socket->flush(); + + delete output; + } + + SocketWriter &SocketWriter::operator << (const quint32 &u) { + *output << u; + + return *this; + } + + SocketWriter &SocketWriter::operator << (const QString &s) { + *output << s; + + return *this; + } +} diff --git a/nde-screensaver-0.1.0/src/common/SocketWriter.h b/nde-screensaver-0.1.0/src/common/SocketWriter.h new file mode 100644 index 0000000..1a722ef --- /dev/null +++ b/nde-screensaver-0.1.0/src/common/SocketWriter.h @@ -0,0 +1,23 @@ +#ifndef NSS_SOCKETWRITER_H +#define NSS_SOCKETWRITER_H + +#include +#include +namespace NSS { + class SocketWriter { + Q_DISABLE_COPY(SocketWriter) + public: + SocketWriter(QLocalSocket *socket); + ~SocketWriter(); + + SocketWriter &operator << (const quint32 &u); + SocketWriter &operator << (const QString &s); + + private: + QByteArray data; + QDataStream *output; + QLocalSocket *socket; + }; +} + +#endif // NSS_SOCKETWRITER_H diff --git a/nde-screensaver-0.1.0/src/common/Utils.h b/nde-screensaver-0.1.0/src/common/Utils.h new file mode 100644 index 0000000..44ae4aa --- /dev/null +++ b/nde-screensaver-0.1.0/src/common/Utils.h @@ -0,0 +1,50 @@ +/*************************************************************************** +* Copyright (c) 2013 Abdurrahman AVCI +* Copyright (c) 2014 David Edmundson +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef NSS_UTILS_H +#define NSS_UTILS_H + +#include +#include + +namespace NSS { +#define TR(x) QT_TRANSLATE_NOOP("Common translate", QStringLiteral(x)) +inline QString generateName(int length) { + QString digits = QStringLiteral("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + + // reserve space for name + QString name; + name.reserve(length); + + // create random device + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, digits.length() - 1); + + // generate name + for (int i = 0; i < length; ++i) + name[i] = digits.at(dis(gen)); + + // return result + return name; +} +} + +#endif diff --git a/nde-screensaver-0.1.0/src/common/com.vm.daemon.xml b/nde-screensaver-0.1.0/src/common/com.vm.daemon.xml new file mode 100644 index 0000000..a49f415 --- /dev/null +++ b/nde-screensaver-0.1.0/src/common/com.vm.daemon.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/CMakeLists.txt b/nde-screensaver-0.1.0/src/greeter/CMakeLists.txt new file mode 100644 index 0000000..02bb2ad --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/CMakeLists.txt @@ -0,0 +1,38 @@ +include_directories( + "${CMAKE_SOURCE_DIR}/src/common" + "${CMAKE_BINARY_DIR}/src/common" + "${LIBXCB_INCLUDE_DIR}" +) + +set(GREETER_SOURCES + ${CMAKE_SOURCE_DIR}/src/common/SocketWriter.cpp + GreeterApp.cpp + GreeterProxy.cpp + KeyboardLayout.cpp + KeyboardModel.cpp + ScreenModel.cpp + UserModel.cpp + XcbKeyboardBackend.cpp + xservergrabber.cpp +) +configure_file("theme.qrc" "theme.qrc") +qt5_add_resources(RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/theme.qrc) + +add_executable(nde-screensaver-greeter ${GREETER_SOURCES} ${RESOURCES}) +target_link_libraries(nde-screensaver-greeter + Qt5::Quick + Qt5::DBus + Qt5::X11Extras + ${X11_LIBRARIES} + ${LIBXCB_LIBRARIES} + ${LIBXKB_LIBRARIES} + ${STATGRAB_LIB}) + +if(JOURNALD_FOUND) + target_link_libraries(nde-screensaver-greeter ${JOURNALD_LIBRARIES}) +endif() + +add_subdirectory(translations) + +add_dependencies(nde-screensaver-greeter components-translation) +install(TARGETS nde-screensaver-greeter RUNTIME DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}") diff --git a/nde-screensaver-0.1.0/src/greeter/GreeterApp.cpp b/nde-screensaver-0.1.0/src/greeter/GreeterApp.cpp new file mode 100644 index 0000000..25ab6d0 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/GreeterApp.cpp @@ -0,0 +1,207 @@ +/*************************************************************************** +* Copyright (c) 2015-2018 Pier Luigi Fiorini +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include "GreeterApp.h" +#include "GreeterProxy.h" +#include "Constants.h" +#include "ScreenModel.h" +#include "UserModel.h" +#include "KeyboardModel.h" +#include "MessageHandler.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "Utils.h" +#include "xservergrabber.h" +static const QEvent::Type StartupEventType = static_cast(QEvent::registerEventType()); + +namespace NSS { + GreeterApp::GreeterApp(QObject *parent) + : QObject(parent) + { + m_components_tranlator = new QTranslator(); + if (m_components_tranlator->load(QLocale::system(), QString(), QString(), QStringLiteral(COMPONENTS_TRANSLATION_DIR))) + QCoreApplication::installTranslator(m_components_tranlator); + + m_userModel = new UserModel(); + m_keyboard = new KeyboardModel(); + } + + + QString GreeterApp::socketName() const + { + return m_socket; + } + + void GreeterApp::setSocketName(const QString &name) + { + m_socket = name; + } + void GreeterApp::customEvent(QEvent *event) + { + if (event->type() == StartupEventType) + startup(); + } + + void GreeterApp::addViewForScreen(QScreen *screen) { + // create view + QQuickView *view = new QQuickView(); + view->setScreen(screen); + view->setFlags(Qt::X11BypassWindowManagerHint | + Qt::WindowStaysOnTopHint | + Qt::FramelessWindowHint); + view->setResizeMode(QQuickView::SizeRootObjectToView); + view->setGeometry(screen->geometry()); + + m_views.append(view); + + connect(qGuiApp, &QGuiApplication::screenRemoved, view, [view, this, screen](QScreen *s) { + if (s == screen) + removeViewForScreen(view); + }); + + // always resize when the screen geometry changes + connect(screen, &QScreen::geometryChanged, this, [view](const QRect &r) { + view->setGeometry(r); + }); + + view->engine()->addImportPath(QStringLiteral(IMPORTS_INSTALL_DIR)); + + // connect proxy signals + connect(m_proxy, SIGNAL(loginSucceeded()), view, SLOT(close())); + ScreenModel *screenModel = new ScreenModel(screen, view); + view->rootContext()->setContextProperty(QStringLiteral("screenModel"), screenModel); + view->rootContext()->setContextProperty(QStringLiteral("userModel"), m_userModel); + view->rootContext()->setContextProperty(QStringLiteral("nss"), m_proxy); + view->rootContext()->setContextProperty(QStringLiteral("keyboard"), m_keyboard); + view->rootContext()->setContextProperty(QStringLiteral("primaryScreen"), QGuiApplication::primaryScreen() == screen); + view->rootContext()->setContextProperty(QStringLiteral("__nss_errors"), QString()); + + // get theme main script + QUrl mainScriptUrl = QUrl::fromLocalFile(":/theme/Main.qml"); + // load theme from resources when an error has occurred + connect(view, &QQuickView::statusChanged, this, [view, mainScriptUrl](QQuickView::Status status) { + if (status != QQuickView::Error) + return; + + QString errors; + Q_FOREACH(const QQmlError &e, view->errors()) { + qWarning() << e; + errors += QLatin1String("\n") + e.toString(); + } + + qWarning() << "Fallback to embedded theme"; + view->rootContext()->setContextProperty(QStringLiteral("__nss_errors"), errors); + view->setSource(mainScriptUrl); + }); + + // set main script as source + qInfo("Loading %s...", qPrintable(mainScriptUrl.toString())); + view->setSource(mainScriptUrl); + + // set default cursor + QCursor cursor(Qt::ArrowCursor); + view->rootObject()->setCursor(cursor); + + // show + qDebug() << "Adding view for" << screen->name() << screen->geometry(); + view->showFullScreen(); + + // activate windows for the primary screen to give focus to text fields + if (QGuiApplication::primaryScreen() == screen) + view->requestActivate(); + + establishGrab(); + } + + void GreeterApp::removeViewForScreen(QQuickView *view) { + // screen is gone, remove the window + m_views.removeOne(view); + view->deleteLater(); + } + + void GreeterApp::startup() + { + // Connect to the daemon + m_proxy = new GreeterProxy(m_userModel->currentUser(), m_socket); + if (!m_testing && !m_proxy->isConnected()) { + qCritical() << "Cannot connect to the daemon - is it running?"; + QCoreApplication::exit(EXIT_FAILURE); + return; + } + m_keyboard->setNumLockState(true); + QList screens = qGuiApp->primaryScreen()->virtualSiblings(); + for (QScreen *screen : screens) + addViewForScreen(screen); + + // Handle screens + connect(qGuiApp, &QGuiApplication::screenAdded, this, &GreeterApp::addViewForScreen); + connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, [this](QScreen *) { + activatePrimary(); + }); + } + + void GreeterApp::activatePrimary() { + // activate and give focus to the window assigned to the primary screen + for (QQuickView *view : m_views) { + if (view->screen() == QGuiApplication::primaryScreen()) { + view->requestActivate(); + break; + } + } + } + + StartupEvent::StartupEvent() + : QEvent(StartupEventType) + { + } +} +int main(int argc, char **argv) +{ + qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); + qInstallMessageHandler(NSS::GreeterMessageHandler); + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + + QGuiApplication app(argc, argv); + QCommandLineParser parser; + parser.setApplicationDescription(TR("nde-screensaver greeter")); + parser.addHelpOption(); + parser.addVersionOption(); + + QCommandLineOption socketOption(QLatin1String("socket"), TR("Socket name"), TR("name")); + parser.addOption(socketOption); + parser.process(app); + + NSS::GreeterApp *greeter = new NSS::GreeterApp(); + greeter->setSocketName(parser.value(socketOption)); + QCoreApplication::postEvent(greeter, new NSS::StartupEvent()); + return app.exec(); +} diff --git a/nde-screensaver-0.1.0/src/greeter/GreeterApp.h b/nde-screensaver-0.1.0/src/greeter/GreeterApp.h new file mode 100644 index 0000000..bbb1256 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/GreeterApp.h @@ -0,0 +1,86 @@ +/*************************************************************************** +* Copyright (c) 2015-2016 Pier Luigi Fiorini +* Copyright (c) 2013 Nikita Mikhaylov +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef GREETERAPP_H +#define GREETERAPP_H + +#include +#include +#include + +class QTranslator; + +namespace NSS { + class Configuration; + class ThemeMetadata; + class ThemeConfig; + class SessionModel; + class ScreenModel; + class UserModel; + class GreeterProxy; + class KeyboardModel; + + + class GreeterApp : public QObject + { + Q_OBJECT + Q_DISABLE_COPY(GreeterApp) + public: + explicit GreeterApp(QObject *parent = nullptr); + + QString socketName() const; + void setSocketName(const QString &name); + + + protected: + void customEvent(QEvent *event) override; + + private slots: + void addViewForScreen(QScreen *screen); + void removeViewForScreen(QQuickView *view); + + private: + bool m_testing = false; + QString m_socket; + QString m_themePath; + + QList m_views; + QTranslator *m_theme_translator { nullptr }, + *m_components_tranlator { nullptr }; + + ThemeMetadata *m_metadata { nullptr }; +// ThemeConfig *m_themeConfig { nullptr }; +// SessionModel *m_sessionModel { nullptr }; + UserModel *m_userModel { nullptr }; + GreeterProxy *m_proxy { nullptr }; + KeyboardModel *m_keyboard { nullptr }; + void startup(); + void activatePrimary(); + }; + + class StartupEvent : public QEvent + { + public: + StartupEvent(); + }; +} + + +#endif // GREETERAPP_H diff --git a/nde-screensaver-0.1.0/src/greeter/GreeterProxy.cpp b/nde-screensaver-0.1.0/src/greeter/GreeterProxy.cpp new file mode 100644 index 0000000..ae17aaa --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/GreeterProxy.cpp @@ -0,0 +1,238 @@ +/*************************************************************************** +* Copyright (c) 2015 Pier Luigi Fiorini +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include "GreeterProxy.h" + +//#include "Configuration.h" +#include "Messages.h" +//#include "SessionModel.h" +#include "SocketWriter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include "Configuration.h" + + +namespace NSS { + class GreeterProxyPrivate { + public: +// SessionModel *sessionModel { nullptr }; + QLocalSocket *socket { nullptr }; + QString hostName; + QString userName; + int loginCount { 0 }; + int tryCount { 0 }; + bool canPowerOff { false }; + bool canReboot { false }; + bool canSuspend { false }; + bool canHibernate { false }; + bool canHybridSleep { false }; + bool isVirtualMachine { false }; + + }; + + GreeterProxy::GreeterProxy(const QString &user, const QString &socket, QObject *parent) : QObject(parent), d(new GreeterProxyPrivate()) { + d->socket = new QLocalSocket(this); + // connect signals + connect(d->socket, SIGNAL(connected()), this, SLOT(connected())); + connect(d->socket, SIGNAL(disconnected()), this, SLOT(disconnected())); + connect(d->socket, SIGNAL(readyRead()), this, SLOT(readyRead())); + connect(d->socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(error())); + + // connect to server + d->userName = user; + qDebug() << "@@@@@@@@@@@@@@@" << socket; + d->socket->connectToServer(socket); + } + + GreeterProxy::~GreeterProxy() { + delete d; + } + const QString &GreeterProxy::hostName() const { + return d->hostName; + } + bool GreeterProxy::canPowerOff() const { + return d->canPowerOff; + } + + bool GreeterProxy::canReboot() const { + return d->canReboot; + } + + bool GreeterProxy::canSuspend() const { + return d->canSuspend; + } + + bool GreeterProxy::canHibernate() const { + return d->canHibernate; + } + + bool GreeterProxy::canHybridSleep() const { + return d->canHybridSleep; + } + + bool GreeterProxy::isVirtualMachine() const { + return d->isVirtualMachine; + } + + bool GreeterProxy::isConnected() const { + return d->socket->state() == QLocalSocket::ConnectedState; + } + + void GreeterProxy::powerOff() { + SocketWriter(d->socket) << quint32(GreeterMessages::PowerOff); + } + + void GreeterProxy::reboot() { + SocketWriter(d->socket) << quint32(GreeterMessages::Reboot); + } + + void GreeterProxy::suspend() { + SocketWriter(d->socket) << quint32(GreeterMessages::Suspend); + } + + void GreeterProxy::hibernate() { + SocketWriter(d->socket) << quint32(GreeterMessages::Hibernate); + } + + void GreeterProxy::hybridSleep() { + SocketWriter(d->socket) << quint32(GreeterMessages::HybridSleep); + } + + void GreeterProxy::login(const QString &user, const QString &password) const { + qDebug() << "----------------" << user << password; + SocketWriter(d->socket) << quint32(GreeterMessages::Login) << user << password; + } + void GreeterProxy::connected() { + // log connection + qDebug() << "Connected to the daemon."; + + // send connected message + SocketWriter(d->socket) << quint32(GreeterMessages::Connect) << d->userName; + } + + void GreeterProxy::disconnected() { + // log disconnection + qDebug() << "Disconnected from the daemon."; + } + + void GreeterProxy::error() { + qCritical() << "Socket error: " << d->socket->errorString(); + } + + bool GreeterProxy::checkVirtualMachine(){ + QProcess p; + QStringList options; + + options << "-c" << "grep -q \"^flags.*\\ hypervisor\\ \" /proc/cpuinfo"; + p.start("/bin/bash", options); + p.waitForFinished(); + p.waitForReadyRead(); + + int exitCode = p.exitCode(); + return exitCode ? false : true; + } + + void GreeterProxy::readyRead() { + // input stream + QDataStream input(d->socket); + + while (input.device()->bytesAvailable()) { + // read message + quint32 message; + input >> message; + + switch (DaemonMessages(message)) { + case DaemonMessages::Capabilities: { + // log message + qDebug() << "Message received from daemon: Capabilities"; + + // read capabilities + quint32 capabilities; + input >> capabilities; + qDebug() << capabilities; + // parse capabilities + d->canPowerOff = capabilities & Capability::PowerOff; + d->canReboot = capabilities & Capability::Reboot; + d->canSuspend = capabilities & Capability::Suspend; + d->canHibernate = capabilities & Capability::Hibernate; + d->canHybridSleep = capabilities & Capability::HybridSleep; + d->isVirtualMachine = checkVirtualMachine(); + + + // emit signals + emit canPowerOffChanged(d->canPowerOff); + emit canRebootChanged(d->canReboot); + emit canSuspendChanged(d->canSuspend); + emit canHibernateChanged(d->canHibernate); + emit canHybridSleepChanged(d->canHybridSleep); + emit isVirtualMachineChanged(d->isVirtualMachine); + } + break; + case DaemonMessages::HostName: { + // log message + qDebug() << "Message received from daemon: HostName"; + + // read host name + input >> d->hostName; + + // emit signal + emit hostNameChanged(d->hostName); + } + break; + case DaemonMessages::LoggingIn: { + qDebug() << "Message received from daemon: LoggingIn"; + + emit loggingIn(); + break; + } + case DaemonMessages::LoginSucceeded: { + // log message + qDebug() << "Message received from daemon: LoginSucceeded"; + // emit signal + emit loginSucceeded(); + } + break; + case DaemonMessages::LoginFailed: { + // log message + qDebug() << "Message received from daemon: LoginFailed"; + + // emit signal + emit loginFailed(); + } + break; + default: { + // log message + qWarning() << "Unknown message received from daemon."; + } + } + } + } +} diff --git a/nde-screensaver-0.1.0/src/greeter/GreeterProxy.h b/nde-screensaver-0.1.0/src/greeter/GreeterProxy.h new file mode 100644 index 0000000..754e34d --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/GreeterProxy.h @@ -0,0 +1,91 @@ +/*************************************************************************** +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef NSS_GREETERPROXY_H +#define NSS_GREETERPROXY_H + +#include +#include + +class QLocalSocket; + +namespace NSS { +// class SessionModel; + + class GreeterProxyPrivate; + class GreeterProxy : public QObject { + Q_OBJECT + Q_DISABLE_COPY(GreeterProxy) + + Q_PROPERTY(QString hostName READ hostName NOTIFY hostNameChanged) + Q_PROPERTY(bool canPowerOff READ canPowerOff NOTIFY canPowerOffChanged) + Q_PROPERTY(bool canReboot READ canReboot NOTIFY canRebootChanged) + Q_PROPERTY(bool canSuspend READ canSuspend NOTIFY canSuspendChanged) + Q_PROPERTY(bool canHibernate READ canHibernate NOTIFY canHibernateChanged) + Q_PROPERTY(bool canHybridSleep READ canHybridSleep NOTIFY canHybridSleepChanged) + Q_PROPERTY(bool isVirtualMachine READ isVirtualMachine NOTIFY isVirtualMachineChanged) + + public: + explicit GreeterProxy(const QString &user, const QString &socket, QObject *parent = 0); + ~GreeterProxy(); + + const QString &hostName() const; + + bool canPowerOff() const; + bool canReboot() const; + bool canSuspend() const; + bool canHibernate() const; + bool canHybridSleep() const; + bool isVirtualMachine() const; + bool checkVirtualMachine(); + + bool isConnected() const; + +// void setSessionModel(SessionModel *model); + public slots: + void powerOff(); + void reboot(); + void suspend(); + void hibernate(); + void hybridSleep(); + + void login(const QString &user, const QString &password/*, const int sessionIndex, bool isAutoLogin = false*/) const; + private slots: + void connected(); + void disconnected(); + void readyRead(); + void error(); + signals: + void hostNameChanged(const QString &hostName); + void canPowerOffChanged(bool canPowerOff); + void canRebootChanged(bool canReboot); + void canSuspendChanged(bool canSuspend); + void canHibernateChanged(bool canHibernate); + void canHybridSleepChanged(bool canHybridSleep); + void isVirtualMachineChanged(bool isVirtualMachine); + + void loggingIn(); + void loginFailed(); + void loginSucceeded(); + private: + GreeterProxyPrivate *d { nullptr }; + }; +} + +#endif // NSS_GREETERPROXY_H diff --git a/nde-screensaver-0.1.0/src/greeter/KeyboardBackend.h b/nde-screensaver-0.1.0/src/greeter/KeyboardBackend.h new file mode 100644 index 0000000..dfa5f48 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/KeyboardBackend.h @@ -0,0 +1,45 @@ +/*************************************************************************** +* Copyright (c) 2013 Nikita Mikhaylov +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef KEYBOARDBACKEND_H +#define KEYBOARDBACKEND_H + +namespace NSS { + class KeyboardModel; + class KeyboardModelPrivate; + + class KeyboardBackend { + public: + KeyboardBackend(KeyboardModelPrivate *kmp) : d(kmp) {} + + virtual ~KeyboardBackend() {} + + virtual void init() = 0; + virtual void disconnect() = 0; + virtual void sendChanges() = 0; + virtual void dispatchEvents() = 0; + + virtual void connectEventsDispatcher(KeyboardModel *model) = 0; + + protected: + KeyboardModelPrivate *d; + }; +} + +#endif // KEYBOARDBACKEND_H diff --git a/nde-screensaver-0.1.0/src/greeter/KeyboardLayout.cpp b/nde-screensaver-0.1.0/src/greeter/KeyboardLayout.cpp new file mode 100644 index 0000000..912af19 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/KeyboardLayout.cpp @@ -0,0 +1,38 @@ +/*************************************************************************** +* Copyright (c) 2013 Nikita Mikhaylov +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include "KeyboardLayout.h" + +namespace NSS { + KeyboardLayout::KeyboardLayout(QString shortName, QString longName) + : m_short(shortName) + , m_long(longName) + { + } + + QString KeyboardLayout::shortName() const + { + return m_short; + } + + QString KeyboardLayout::longName() const + { + return m_long; + } +} diff --git a/nde-screensaver-0.1.0/src/greeter/KeyboardLayout.h b/nde-screensaver-0.1.0/src/greeter/KeyboardLayout.h new file mode 100644 index 0000000..1db986a --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/KeyboardLayout.h @@ -0,0 +1,43 @@ +/*************************************************************************** +* Copyright (c) 2013 Nikita Mikhaylov +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef KEYBOARDLAYOUT_H +#define KEYBOARDLAYOUT_H + +#include + +namespace NSS { + class KeyboardLayout : public QObject { + Q_OBJECT + Q_PROPERTY(QString shortName READ shortName CONSTANT) + Q_PROPERTY(QString longName READ longName CONSTANT) + public: + KeyboardLayout(QString shortName, QString longName); + + virtual ~KeyboardLayout() = default; + + QString shortName() const; + QString longName() const; + + private: + QString m_short, m_long; + }; +} + +#endif // KEYBOARDLAYOUT_H diff --git a/nde-screensaver-0.1.0/src/greeter/KeyboardModel.cpp b/nde-screensaver-0.1.0/src/greeter/KeyboardModel.cpp new file mode 100644 index 0000000..684b714 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/KeyboardModel.cpp @@ -0,0 +1,116 @@ +/*************************************************************************** +* Copyright (c) 2013 Nikita Mikhaylov +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include "KeyboardModel.h" +#include "KeyboardModel_p.h" +#include "XcbKeyboardBackend.h" + +namespace NSS { + /**********************************************/ + /* KeyboardModel */ + /**********************************************/ + + KeyboardModel::KeyboardModel() : d(new KeyboardModelPrivate) { + m_backend = new XcbKeyboardBackend(d); + m_backend->init(); + m_backend->connectEventsDispatcher(this); + } + + KeyboardModel::~KeyboardModel() { + m_backend->disconnect(); + delete m_backend; + + for (QObject *layout: d->layouts) { + delete layout; + } + delete d; + } + + bool KeyboardModel::numLockState() const { + return d->numlock.enabled; + } + + void KeyboardModel::setNumLockState(bool state) { + if (d->numlock.enabled != state) { + d->numlock.enabled = state; + m_backend->sendChanges(); + + emit numLockStateChanged(); + } + } + + bool KeyboardModel::capsLockState() const { + return d->capslock.enabled; + } + + void KeyboardModel::setCapsLockState(bool state) { + if (d->capslock.enabled != state) { + d->capslock.enabled = state; + m_backend->sendChanges(); + + emit capsLockStateChanged(); + } + } + + QList KeyboardModel::layouts() const { + return d->layouts; + } + + int KeyboardModel::currentLayout() const { + return d->layout_id; + } + + void KeyboardModel::setCurrentLayout(int id) { + if (d->layout_id != id) { + d->layout_id = id; + m_backend->sendChanges(); + + emit currentLayoutChanged(); + } + } + + bool KeyboardModel::enabled() const { + return d->enabled; + } + + void KeyboardModel::dispatchEvents() { + // Save old states + bool num_old = d->numlock.enabled, caps_old = d->capslock.enabled; + int layout_old = d->layout_id; + QList layouts_old = d->layouts; + + // Process events + m_backend->dispatchEvents(); + + // Send updates + if (caps_old != d->capslock.enabled) + emit capsLockStateChanged(); + + if (num_old != d->numlock.enabled) + emit numLockStateChanged(); + + if (layout_old != d->layout_id) + emit currentLayoutChanged(); + + if (layouts_old != d->layouts) + emit layoutsChanged(); + } +} + +#include "moc_KeyboardModel.cpp" diff --git a/nde-screensaver-0.1.0/src/greeter/KeyboardModel.h b/nde-screensaver-0.1.0/src/greeter/KeyboardModel.h new file mode 100644 index 0000000..6d58444 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/KeyboardModel.h @@ -0,0 +1,78 @@ +/*************************************************************************** +* Copyright (c) 2013 Nikita Mikhaylov +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef KEYBOARDMODEL_H +#define KEYBOARDMODEL_H + +#include +#include +#include + +namespace NSS { + class KeyboardModelPrivate; + class KeyboardBackend; + + class KeyboardModel : public QObject { + Q_OBJECT + Q_DISABLE_COPY(KeyboardModel) + public: + // LED control + Q_PROPERTY(bool numLock READ numLockState WRITE setNumLockState NOTIFY numLockStateChanged) + Q_PROPERTY(bool capsLock READ capsLockState WRITE setCapsLockState NOTIFY capsLockStateChanged) + + // Layouts control + Q_PROPERTY(int currentLayout READ currentLayout WRITE setCurrentLayout NOTIFY currentLayoutChanged) + Q_PROPERTY(QList layouts READ layouts NOTIFY layoutsChanged) + + Q_PROPERTY(bool enabled READ enabled CONSTANT) + + public: + KeyboardModel(); + virtual ~KeyboardModel(); + + signals: + void numLockStateChanged(); + void capsLockStateChanged(); + + void currentLayoutChanged(); + void layoutsChanged(); + + public slots: + bool numLockState() const; + void setNumLockState(bool state); + + bool capsLockState() const; + void setCapsLockState(bool state); + + QList layouts() const; + int currentLayout() const; + void setCurrentLayout(int id); + + bool enabled() const; + + private slots: + void dispatchEvents(); + + private: + KeyboardModelPrivate * d { nullptr }; + KeyboardBackend * m_backend; + }; +} + +#endif // KEYBOARDMODEL_H diff --git a/nde-screensaver-0.1.0/src/greeter/KeyboardModel_p.h b/nde-screensaver-0.1.0/src/greeter/KeyboardModel_p.h new file mode 100644 index 0000000..ea1de71 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/KeyboardModel_p.h @@ -0,0 +1,45 @@ +/*************************************************************************** +* Copyright (c) 2013 Nikita Mikhaylov +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef KEYBOARDMODEL_P_H +#define KEYBOARDMODEL_P_H + +#include + +namespace NSS { + struct Indicator { + bool enabled { false }; + uint8_t mask { 0 }; + }; + + class KeyboardModelPrivate { + public: + // is extension enabled + bool enabled { true }; + + // indicator state + Indicator numlock, capslock; + + // Layouts + int layout_id { 0 }; + QList layouts; + }; +} + +#endif // KEYBOARDMODEL_P_H diff --git a/nde-screensaver-0.1.0/src/greeter/ScreenModel.cpp b/nde-screensaver-0.1.0/src/greeter/ScreenModel.cpp new file mode 100644 index 0000000..ef669e7 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/ScreenModel.cpp @@ -0,0 +1,77 @@ +/*************************************************************************** +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include "ScreenModel.h" + +#include + +#include +#include + +namespace NSS { + class ScreenModelPrivate { + public: + QScreen *screen { nullptr }; + }; + + ScreenModel::ScreenModel(QScreen *screen, QObject *parent) : QAbstractListModel(parent), d(new ScreenModelPrivate()) { + d->screen = screen; + } + + ScreenModel::~ScreenModel() { + delete d; + } + + QHash ScreenModel::roleNames() const { + // set role names + QHash roleNames; + roleNames[NameRole] = QByteArrayLiteral("name"); + roleNames[GeometryRole] = QByteArrayLiteral("geometry"); + return roleNames; + } + + int ScreenModel::primary() const { + // This used to return the index of the primary screen, since this model + // always have just one screen it should return 0 if it's primary or -1. + return d->screen == QGuiApplication::primaryScreen() ? 0 : -1; + } + + const QRect ScreenModel::geometry(int index) const { + Q_UNUSED(index); + return QRect(QPoint(0, 0), d->screen->geometry().size()); + } + + int ScreenModel::rowCount(const QModelIndex &parent) const { + return 1; + } + + QVariant ScreenModel::data(const QModelIndex &index, int role) const { + if (index.row() < 0 || index.row() >= 1) + return QVariant(); + + // return correct value + if (role == NameRole) + return d->screen->name(); + if (role == GeometryRole) + return QRect(QPoint(0, 0), d->screen->geometry().size()); + + // return empty value + return QVariant(); + } +} diff --git a/nde-screensaver-0.1.0/src/greeter/ScreenModel.h b/nde-screensaver-0.1.0/src/greeter/ScreenModel.h new file mode 100644 index 0000000..670a610 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/ScreenModel.h @@ -0,0 +1,64 @@ +/*************************************************************************** +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef NSS_SCREENMODEL_H +#define NSS_SCREENMODEL_H + +#include + +#include + +#include + +class QScreen; + +namespace NSS { + class ScreenModelPrivate; + + class ScreenModel : public QAbstractListModel { + Q_OBJECT + Q_DISABLE_COPY(ScreenModel) + Q_PROPERTY(int primary READ primary NOTIFY primaryChanged) + public: + enum ScreenRoles { + NameRole = Qt::UserRole + 1, + GeometryRole + }; + + ScreenModel(QScreen *screen, QObject *parent = 0); + ~ScreenModel(); + + QHash roleNames() const override; + int primary() const; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + public slots: + const QRect geometry(int index = -1) const; + + signals: + void primaryChanged(); + + private: + ScreenModelPrivate *d { nullptr }; + }; +} + +#endif // NSS_SCREENMODEL_H diff --git a/nde-screensaver-0.1.0/src/greeter/SessionModel.cpp b/nde-screensaver-0.1.0/src/greeter/SessionModel.cpp new file mode 100644 index 0000000..2a3c091 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/SessionModel.cpp @@ -0,0 +1,159 @@ +/*************************************************************************** +* Copyright (c) 2015-2016 Pier Luigi Fiorini +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include "SessionModel.h" + +#include "Configuration.h" + +#include +#include +#include + +namespace SDDM { + class SessionModelPrivate { + public: + ~SessionModelPrivate() { + qDeleteAll(sessions); + sessions.clear(); + } + + int lastIndex { 0 }; + QVector sessions; + }; + + SessionModel::SessionModel(QObject *parent) : QAbstractListModel(parent), d(new SessionModelPrivate()) { + // initial population + beginResetModel(); + populate(Session::X11Session, mainConfig.X11.SessionDir.get()); + populate(Session::WaylandSession, mainConfig.Wayland.SessionDir.get()); + endResetModel(); + + // refresh everytime a file is changed, added or removed + QFileSystemWatcher *watcher = new QFileSystemWatcher(this); + connect(watcher, &QFileSystemWatcher::directoryChanged, [this](const QString &path) { + beginResetModel(); + d->sessions.clear(); + populate(Session::X11Session, mainConfig.X11.SessionDir.get()); + populate(Session::WaylandSession, mainConfig.Wayland.SessionDir.get()); + endResetModel(); + }); + watcher->addPath(mainConfig.X11.SessionDir.get()); + watcher->addPath(mainConfig.Wayland.SessionDir.get()); + } + + SessionModel::~SessionModel() { + delete d; + } + + QHash SessionModel::roleNames() const { + // set role names + QHash roleNames; + roleNames[DirectoryRole] = QByteArrayLiteral("directory"); + roleNames[FileRole] = QByteArrayLiteral("file"); + roleNames[TypeRole] = QByteArrayLiteral("type"); + roleNames[NameRole] = QByteArrayLiteral("name"); + roleNames[ExecRole] = QByteArrayLiteral("exec"); + roleNames[CommentRole] = QByteArrayLiteral("comment"); + + return roleNames; + } + + const int SessionModel::lastIndex() const { + return d->lastIndex; + } + + int SessionModel::rowCount(const QModelIndex &parent) const { + return d->sessions.length(); + } + + QVariant SessionModel::data(const QModelIndex &index, int role) const { + if (index.row() < 0 || index.row() >= d->sessions.count()) + return QVariant(); + + // get session + Session *session = d->sessions[index.row()]; + + // return correct value + switch (role) { + case DirectoryRole: + return session->directory().absolutePath(); + case FileRole: + return session->fileName(); + case TypeRole: + return session->type(); + case NameRole: + return session->displayName(); + case ExecRole: + return session->exec(); + case CommentRole: + return session->comment(); + default: + break; + } + + // return empty value + return QVariant(); + } + + void SessionModel::populate(Session::Type type, const QString &path) { + // read session files + QDir dir(path); + dir.setNameFilters(QStringList() << QStringLiteral("*.desktop")); + dir.setFilter(QDir::Files); + // read session + foreach(const QString &session, dir.entryList()) { + if (!dir.exists(session)) + continue; + + Session *si = new Session(type, session); + bool execAllowed = true; + QFileInfo fi(si->tryExec()); + if (fi.isAbsolute()) { + if (!fi.exists() || !fi.isExecutable()) + execAllowed = false; + } else { + execAllowed = false; + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + QString envPath = env.value(QStringLiteral("PATH")); + QStringList pathList = envPath.split(QLatin1Char(':')); + foreach(const QString &path, pathList) { + QDir pathDir(path); + fi.setFile(pathDir, si->tryExec()); + if (fi.exists() && fi.isExecutable()) { + execAllowed = true; + break; + } + } + } + // add to sessions list + if (!si->isHidden() && !si->isNoDisplay() && execAllowed) + d->sessions.push_back(si); + else + delete si; + } + // find out index of the last session + for (int i = 0; i < d->sessions.size(); ++i) { + if (d->sessions.at(i)->fileName() == stateConfig.Last.Session.get()) { + d->lastIndex = i; + break; + } + } + } +} diff --git a/nde-screensaver-0.1.0/src/greeter/SessionModel.h b/nde-screensaver-0.1.0/src/greeter/SessionModel.h new file mode 100644 index 0000000..33becd3 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/SessionModel.h @@ -0,0 +1,64 @@ +/*************************************************************************** +* Copyright (c) 2015-2016 Pier Luigi Fiorini +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef NSS_SESSIONMODEL_H +#define NSS_SESSIONMODEL_H + +#include "Session.h" + +#include + +#include + +namespace NSS { + class SessionModelPrivate; + + class SessionModel : public QAbstractListModel { + Q_OBJECT + Q_DISABLE_COPY(SessionModel) + Q_PROPERTY(int lastIndex READ lastIndex CONSTANT) + public: + enum SessionRole { + DirectoryRole = Qt::UserRole + 1, + FileRole, + TypeRole, + NameRole, + ExecRole, + CommentRole + }; + + SessionModel(QObject *parent = 0); + ~SessionModel(); + + QHash roleNames() const override; + + const int lastIndex() const; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + private: + SessionModelPrivate *d { nullptr }; + + void populate(Session::Type type, const QString &path); + }; +} + +#endif // NSS_SESSIONMODEL_H diff --git a/nde-screensaver-0.1.0/src/greeter/UserModel.cpp b/nde-screensaver-0.1.0/src/greeter/UserModel.cpp new file mode 100644 index 0000000..eab0fd4 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/UserModel.cpp @@ -0,0 +1,176 @@ +/*************************************************************************** +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include "UserModel.h" + +#include "Constants.h" +//#include "Configuration.h" + +#include +#include +#include +#include +#include + +#include +#include + +namespace NSS { + class User { + public: + QString name; + QString realName; + QString homeDir; + QString icon; + bool needsPassword { false }; + int uid { 0 }; + int gid { 0 }; + }; + + typedef std::shared_ptr UserPtr; + + class UserModelPrivate { + public: + int lastIndex { 0 }; + QList users; + }; + + UserModel::UserModel(QObject *parent) : QAbstractListModel(parent), d(new UserModelPrivate()) { + const QString defaultFace = QStringLiteral("%1/%2/.face.icon").arg(DATA_INSTALL_DIR).arg("faces"); + const QString iconURI = QStringLiteral("file://%1").arg(defaultFace); + QByteArray user = qgetenv("USER"); + //AD Users + struct passwd *current_pw = nullptr; + QProcess process; + QStringList args; + args << QStringLiteral("list"); + process.start(QStringLiteral("/usr/sbin/realm"), args); + process.waitForFinished(-1); + QList output = process.readAllStandardOutput().split('\n'); + for(int i = 0 ; i < output.size() ; i++) + { + QByteArray line = output.at(i).trimmed(); + QList userNameList = line.split(':'); + QByteArray name = userNameList.last().trimmed(); + if(line.startsWith("permitted-logins") && + !name.isEmpty() && (current_pw = getpwnam(name.data()))) + { + if(current_pw->pw_name != user) + continue; + UserPtr user { new User() }; + user->name = QString::fromLocal8Bit(current_pw->pw_name); + user->realName = QString::fromLocal8Bit(current_pw->pw_gecos).split(QLatin1Char(',')).first(); + user->homeDir = QString::fromLocal8Bit(current_pw->pw_dir); + user->uid = int(current_pw->pw_uid); + user->gid = int(current_pw->pw_gid); + + user->needsPassword = strcmp(current_pw->pw_passwd, "") != 0; + user->icon = iconURI; + + d->users << user; + break; + } + } + while ((current_pw = getpwent()) != nullptr) { + // skip entries with uids smaller than minimum uid + if (int(current_pw->pw_uid) < UID_MIN) + continue; + + // skip entries with uids greater than maximum uid + if (int(current_pw->pw_uid) > UID_MAX) + continue; + if(current_pw->pw_name != user) + continue; + // create user + UserPtr user { new User() }; + user->name = QString::fromLocal8Bit(current_pw->pw_name); + user->realName = QString::fromLocal8Bit(current_pw->pw_gecos).split(QLatin1Char(',')).first(); + user->homeDir = QString::fromLocal8Bit(current_pw->pw_dir); + user->uid = int(current_pw->pw_uid); + user->gid = int(current_pw->pw_gid); + // if shadow is used pw_passwd will be 'x' nevertheless, so this + // will always be true + user->needsPassword = strcmp(current_pw->pw_passwd, "") != 0; + user->icon = iconURI; + + // add user + d->users << user; + } + endpwent(); + for (int i = 0; i < d->users.size(); ++i) { + UserPtr user { d->users.at(i) }; + const QString userFace = QStringLiteral("%1/.face.icon").arg(user->homeDir); + const QString systemFace = QStringLiteral("%1/%2.face.icon").arg(DATA_INSTALL_DIR).arg(user->name); + QString accountsServiceFace = QStringLiteral("/var/lib/AccountsService/icons/%1").arg(user->name); + + if (QFile::exists(userFace)) + user->icon = QStringLiteral("file://%1").arg(userFace); + else if (QFile::exists(accountsServiceFace)) + user->icon = accountsServiceFace; + else if (QFile::exists(systemFace)) + user->icon = QStringLiteral("file://%1").arg(systemFace); + } + } + + UserModel::~UserModel() { + delete d; + } + + QHash UserModel::roleNames() const { + // set role names + QHash roleNames; + roleNames[NameRole] = QByteArrayLiteral("name"); + roleNames[RealNameRole] = QByteArrayLiteral("realName"); + roleNames[HomeDirRole] = QByteArrayLiteral("homeDir"); + roleNames[IconRole] = QByteArrayLiteral("icon"); + roleNames[NeedsPasswordRole] = QByteArrayLiteral("needsPassword"); + + return roleNames; + } + QString UserModel::currentUser() const + { + return d->users.first()->name; + } + int UserModel::rowCount(const QModelIndex &parent) const { + return d->users.length(); + } + + QVariant UserModel::data(const QModelIndex &index, int role) const { + if (index.row() < 0 || index.row() > d->users.count()) + return QVariant(); + + // get user + UserPtr user = d->users[index.row()]; + + // return correct value + if (role == NameRole) + return user->name; + else if (role == RealNameRole) + return user->realName; + else if (role == HomeDirRole) + return user->homeDir; + else if (role == IconRole) + return user->icon; + else if (role == NeedsPasswordRole) + return user->needsPassword; + + // return empty value + return QVariant(); + } +} diff --git a/nde-screensaver-0.1.0/src/greeter/UserModel.h b/nde-screensaver-0.1.0/src/greeter/UserModel.h new file mode 100644 index 0000000..f5fb6c9 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/UserModel.h @@ -0,0 +1,57 @@ +/*************************************************************************** +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef NSS_USERMODEL_H +#define NSS_USERMODEL_H + +#include + +#include + +namespace NSS { + class UserModelPrivate; + + class UserModel : public QAbstractListModel { + Q_OBJECT + Q_DISABLE_COPY(UserModel) + Q_PROPERTY(QString currentUser READ currentUser CONSTANT) + Q_PROPERTY(int count READ rowCount CONSTANT) + public: + enum UserRoles { + NameRole = Qt::UserRole + 1, + RealNameRole, + HomeDirRole, + IconRole, + NeedsPasswordRole + }; + + UserModel(QObject *parent = 0); + ~UserModel(); + + QHash roleNames() const override; + QString currentUser() const; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + private: + UserModelPrivate *d { nullptr }; + }; +} + +#endif // NSS_USERMODEL_H diff --git a/nde-screensaver-0.1.0/src/greeter/XcbKeyboardBackend.cpp b/nde-screensaver-0.1.0/src/greeter/XcbKeyboardBackend.cpp new file mode 100644 index 0000000..24634e3 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/XcbKeyboardBackend.cpp @@ -0,0 +1,333 @@ +/*************************************************************************** +* Copyright (c) 2013 Nikita Mikhaylov +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include +#include + +#include "KeyboardModel.h" +#include "KeyboardModel_p.h" +#include "KeyboardLayout.h" +#include "XcbKeyboardBackend.h" + +#include + +namespace NSS { + XcbKeyboardBackend::XcbKeyboardBackend(KeyboardModelPrivate *kmp) : KeyboardBackend(kmp) { + } + + XcbKeyboardBackend::~XcbKeyboardBackend() { + } + + void XcbKeyboardBackend::init() { + connectToDisplay(); + if (d->enabled) + initLedMap(); + if (d->enabled) + initLayouts(); + if (d->enabled) + initState(); + } + + void XcbKeyboardBackend::disconnect() { + delete m_socket; + xcb_disconnect(m_conn); + } + + void XcbKeyboardBackend::sendChanges() { + xcb_void_cookie_t cookie; + xcb_generic_error_t *error = nullptr; + + // Compute masks + uint8_t mask_full = d->numlock.mask | d->capslock.mask, + mask_cur = (d->numlock.enabled ? d->numlock.mask : 0) | + (d->capslock.enabled ? d->capslock.mask : 0); + + // Change state + cookie = xcb_xkb_latch_lock_state(m_conn, + XCB_XKB_ID_USE_CORE_KBD, + mask_full, + mask_cur, + 1, + d->layout_id, + 0, 0, 0); + error = xcb_request_check(m_conn, cookie); + + if (error) { + qWarning() << "Can't update state: " << error->error_code; + } + } + + void XcbKeyboardBackend::connectToDisplay() { + // Connect and initialize xkb extension + xcb_xkb_use_extension_cookie_t cookie; + xcb_generic_error_t *error = nullptr; + + m_conn = xcb_connect(nullptr, nullptr); + if (m_conn == nullptr) { + qCritical() << "xcb_connect failed, keyboard extension disabled"; + d->enabled = false; + return; + } + + // Initialize xkb extension + cookie = xcb_xkb_use_extension(m_conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION); + xcb_xkb_use_extension_reply(m_conn, cookie, &error); + + if (error != nullptr) { + qCritical() << "xcb_xkb_use_extension failed, extension disabled, error code" + << error->error_code; + d->enabled = false; + return; + } + } + + void XcbKeyboardBackend::initLedMap() { + // Get indicator names atoms + xcb_xkb_get_names_cookie_t cookie; + xcb_xkb_get_names_reply_t *reply = nullptr; + xcb_generic_error_t *error = nullptr; + + cookie = xcb_xkb_get_names(m_conn, + XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_NAME_DETAIL_INDICATOR_NAMES); + reply = xcb_xkb_get_names_reply(m_conn, cookie, &error); + + if (error) { + qCritical() << "Can't init led map: " << error->error_code; + d->enabled = false; + return; + } + + // Unpack + xcb_xkb_get_names_value_list_t list; + const void *buffer = xcb_xkb_get_names_value_list(reply); + xcb_xkb_get_names_value_list_unpack(buffer, reply->nTypes, reply->indicators, + reply->virtualMods, reply->groupNames, reply->nKeys, reply->nKeyAliases, + reply->nRadioGroups, reply->which, &list); + + // Get indicators count + int ind_cnt = xcb_xkb_get_names_value_list_indicator_names_length(reply, &list); + + // Loop through indicators and get their properties + QList cookies; + for (int i = 0; i < ind_cnt; i++) { + cookies << xcb_get_atom_name(m_conn, list.indicatorNames[i]); + } + + for (int i = 0; i < ind_cnt; i++) { + QString name = atomName(cookies[i]); + + if (name == QLatin1String("Num Lock")) { + d->numlock.mask = getIndicatorMask(i); + } else if (name == QLatin1String("Caps Lock")) { + d->capslock.mask = getIndicatorMask(i); + } + } + + // Free memory + free(reply); + } + + void XcbKeyboardBackend::initLayouts() { + xcb_xkb_get_names_cookie_t cookie; + xcb_xkb_get_names_reply_t *reply = nullptr; + xcb_generic_error_t *error = nullptr; + + // Get atoms for short and long names + cookie = xcb_xkb_get_names(m_conn, + XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_NAME_DETAIL_GROUP_NAMES | XCB_XKB_NAME_DETAIL_SYMBOLS); + reply = xcb_xkb_get_names_reply(m_conn, cookie, nullptr); + + if (error) { + // Log and disable + qCritical() << "Can't init layouts: " << error->error_code; + return; + } + + // Unpack + const void *buffer = xcb_xkb_get_names_value_list(reply); + xcb_xkb_get_names_value_list_t res_list; + xcb_xkb_get_names_value_list_unpack(buffer, reply->nTypes, reply->indicators, + reply->virtualMods, reply->groupNames, reply->nKeys, reply->nKeyAliases, + reply->nRadioGroups, reply->which, &res_list); + + // Get short names + QList short_names = parseShortNames(atomName(res_list.symbolsName)); + + // Loop through group names + d->layouts.clear(); + int groups_cnt = xcb_xkb_get_names_value_list_groups_length(reply, &res_list); + + QList cookies; + for (int i = 0; i < groups_cnt; i++) { + cookies << xcb_get_atom_name(m_conn, res_list.groups[i]); + } + + for (int i = 0; i < groups_cnt; i++) { + QString nshort, nlong = atomName(cookies[i]); + if (i < short_names.length()) + nshort = short_names[i]; + + d->layouts << new KeyboardLayout(nshort, nlong); + } + + // Free + free(reply); + } + + void XcbKeyboardBackend::initState() { + xcb_xkb_get_state_cookie_t cookie; + xcb_xkb_get_state_reply_t *reply = nullptr; + xcb_generic_error_t *error = nullptr; + + // Get xkb state + cookie = xcb_xkb_get_state(m_conn, XCB_XKB_ID_USE_CORE_KBD); + reply = xcb_xkb_get_state_reply(m_conn, cookie, &error); + + if (reply) { + // Set locks state + d->capslock.enabled = reply->lockedMods & d->capslock.mask; + d->numlock.enabled = reply->lockedMods & d->numlock.mask; + + // Set current layout + d->layout_id = reply->group; + + // Free + free(reply); + } else { + // Log error and disable extension + qCritical() << "Can't load leds state - " << error->error_code; + d->enabled = false; + } + } + + QString XcbKeyboardBackend::atomName(xcb_get_atom_name_cookie_t cookie) const { + xcb_get_atom_name_reply_t *reply = nullptr; + xcb_generic_error_t *error = nullptr; + + // Get atom name + reply = xcb_get_atom_name_reply(m_conn, cookie, &error); + + QString res; + + if (reply) { + QByteArray replyText(xcb_get_atom_name_name(reply), + xcb_get_atom_name_name_length(reply)); + res = QString::fromLocal8Bit(replyText); + free(reply); + } else { + // Log error + qWarning() << "Failed to get atom name: " << error->error_code; + } + return res; + } + + QString XcbKeyboardBackend::atomName(xcb_atom_t atom) const { + return atomName(xcb_get_atom_name(m_conn, atom)); + } + + uint8_t XcbKeyboardBackend::getIndicatorMask(uint8_t i) const { + xcb_xkb_get_indicator_map_cookie_t cookie; + xcb_xkb_get_indicator_map_reply_t *reply = nullptr; + xcb_generic_error_t *error = nullptr; + uint8_t mask = 0; + + cookie = xcb_xkb_get_indicator_map(m_conn, XCB_XKB_ID_USE_CORE_KBD, 1 << i); + reply = xcb_xkb_get_indicator_map_reply(m_conn, cookie, &error); + + + if (reply) { + xcb_xkb_indicator_map_t *map = xcb_xkb_get_indicator_map_maps(reply); + + mask = map->mods; + + free(reply); + } else { + // Log error + qWarning() << "Can't get indicator mask " << error->error_code; + } + return mask; + } + + QList XcbKeyboardBackend::parseShortNames(QString text) { + QRegExp re(QStringLiteral(R"(\+([a-z]+))")); + re.setCaseSensitivity(Qt::CaseInsensitive); + + QList res; + QSet blackList; // blacklist wrong tokens + blackList << QStringLiteral("inet") << QStringLiteral("group"); + + // Loop through matched substrings + int pos = 0; + while ((pos = re.indexIn(text, pos)) != -1) { + if (!blackList.contains(re.cap(1))) + res << re.cap(1); + pos += re.matchedLength(); + } + return res; + } + + void XcbKeyboardBackend::dispatchEvents() { + // Pool events + while (xcb_generic_event_t *event = xcb_poll_for_event(m_conn)) { + // Check event types + if (event->response_type != 0 && event->pad0 == XCB_XKB_STATE_NOTIFY) { + xcb_xkb_state_notify_event_t *e = (xcb_xkb_state_notify_event_t *)event; + + // Update state + d->capslock.enabled = e->lockedMods & d->capslock.mask; + d->numlock.enabled = e->lockedMods & d->numlock.mask; + + d->layout_id = e->group; + } else if (event->response_type != 0 && event->pad0 == XCB_XKB_NEW_KEYBOARD_NOTIFY) { + // Keyboards changed, reinit layouts + initLayouts(); + } + free(event); + } + } + + void XcbKeyboardBackend::connectEventsDispatcher(KeyboardModel *model) { + // Setup events filter + xcb_void_cookie_t cookie; + xcb_xkb_select_events_details_t foo; + xcb_generic_error_t *error = nullptr; + + cookie = xcb_xkb_select_events(m_conn, XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY, 0, + XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY, 0, 0, &foo); + // Check errors + error = xcb_request_check(m_conn, cookie); + if (error) { + qCritical() << "Can't select xck-xkb events: " << error->error_code; + d->enabled = false; + return; + } + + // Flush connection + xcb_flush(m_conn); + + // Get file descripor and init socket listener + int fd = xcb_get_file_descriptor(m_conn); + m_socket = new QSocketNotifier(fd, QSocketNotifier::Read); + + QObject::connect(m_socket, SIGNAL(activated(int)), model, SLOT(dispatchEvents())); + } +} diff --git a/nde-screensaver-0.1.0/src/greeter/XcbKeyboardBackend.h b/nde-screensaver-0.1.0/src/greeter/XcbKeyboardBackend.h new file mode 100644 index 0000000..6efc742 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/XcbKeyboardBackend.h @@ -0,0 +1,69 @@ +/*************************************************************************** +* Copyright (c) 2013 Nikita Mikhaylov +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef XCBKEYBOARDBACKEND_H +#define XCBKEYBOARDBACKEND_H + +#include + +#include "KeyboardBackend.h" + +#define explicit explicit_is_keyword_in_cpp +#include +#undef explicit + +class QSocketNotifier; + +namespace NSS { + class XcbKeyboardBackend : public KeyboardBackend { + public: + XcbKeyboardBackend(KeyboardModelPrivate *kmp); + virtual ~XcbKeyboardBackend(); + + void init() override; + void disconnect() override; + void sendChanges() override; + void dispatchEvents() override; + + void connectEventsDispatcher(KeyboardModel *model) override; + + static QList parseShortNames(QString text); + + private: + // Initializers + void connectToDisplay(); + void initLedMap(); + void initLayouts(); + void initState(); + + // Helpers + QString atomName(xcb_atom_t atom) const; + QString atomName(xcb_get_atom_name_cookie_t cookie) const; + + uint8_t getIndicatorMask(uint8_t id) const; + + // Connection + xcb_connection_t *m_conn { nullptr }; + + // Socket listener + QSocketNotifier *m_socket { nullptr }; + }; +} + +#endif // XCBKEYBOARDBACKEND_H diff --git a/nde-screensaver-0.1.0/src/greeter/theme.qrc b/nde-screensaver-0.1.0/src/greeter/theme.qrc new file mode 100644 index 0000000..ccefffa --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/theme.qrc @@ -0,0 +1,10 @@ + + + ${CMAKE_CURRENT_SOURCE_DIR}/theme/keyboard.png + ${CMAKE_CURRENT_SOURCE_DIR}/theme/Main.qml + ${CMAKE_CURRENT_SOURCE_DIR}/theme/poweroff.png + ${CMAKE_CURRENT_SOURCE_DIR}/theme/reboot.png + ${CMAKE_CURRENT_SOURCE_DIR}/theme/sleep.png + ${CMAKE_CURRENT_SOURCE_DIR}/theme/VirtualKeyboard.qml + + diff --git a/nde-screensaver-0.1.0/src/greeter/theme/Main.qml b/nde-screensaver-0.1.0/src/greeter/theme/Main.qml new file mode 100644 index 0000000..92c044d --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/theme/Main.qml @@ -0,0 +1,345 @@ +import QtQuick 2.8 +import QtQuick.Layouts 1.1 +import QtQuick.Controls 2.0 +import QtGraphicalEffects 1.0 +import QtQuick.VirtualKeyboard.Settings 2.2 +import SddmComponents 2.0 + +Rectangle { + id: root + width: 1660 + height: 900 + property string notificationMessage + + readonly property int longDuration:120 + readonly property int gridUnit:18 + readonly property int largeSpacing:18 + readonly property int smallSpacing:4 + readonly property int fontSize:10 + readonly property string backgroundColor: "#f1f1f1" + + readonly property bool lightBackground: Math.max(backgroundColor.r, backgroundColor.g, backgroundColor.b) > 0.5 + readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software + LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft + LayoutMirroring.childrenInherit: true + + Item { + id: wallpaper + anchors.fill: parent + Repeater { + model: screenModel + Background { + //x: geometry.x; y: geometry.y; width: geometry.width; height: geometry.height + anchors.fill: parent + source: "/usr/share/backgrounds/default.png" + fillMode: Image.PreserveAspectCrop + } + } + } + + MouseArea{ + id: loginScreenRoot + + property bool uiVisible: true + anchors.fill: parent + property bool blockUI: userListComponent.mainPasswordBox.text.length > 0 || inputPanel.keyboardActive + hoverEnabled: true + drag.filterChildren: true + onPressed: uiVisible = true + onPositionChanged: uiVisible = true + onUiVisibleChanged: { + if (blockUI) { + fadeoutTimer.running = false + } else if (uiVisible) { + fadeoutTimer.restart() + } + } + onBlockUIChanged: { + if (blockUI) { + fadeoutTimer.running = false + uiVisible = true + } else { + fadeoutTimer.restart() + } + } + + Keys.onPressed: { + uiVisible = true + event.accepted = false + } + + Timer { + id: fadeoutTimer + running: true + interval: 5 * 60 * 1000 + onTriggered: { + if (!loginScreenRoot.blockUI) { + loginScreenRoot.uiVisible = false + if(inputPanel.state == "visible") + inputPanel.showHide() + } + } + } + + WallpaperFader { + anchors.fill: parent + state: loginScreenRoot.uiVisible ? "on" : "off" + source: wallpaper + mainStack: mainStack + footer: footer + clock: clock + } + + StackView { + id: mainStack + anchors { + left: parent.left + right: parent.right + } + height: root.height + + focus: true + + Timer { + running: true + repeat: false + interval: 200 + onTriggered: mainStack.forceActiveFocus() + } + initialItem: Login { + id: userListComponent + userListModel: userModel + loginScreenUiVisible: loginScreenRoot.uiVisible + userListCurrentIndex: userModel.lastIndex >= 0 ? userModel.lastIndex : 0 + placeholderText: qsTr("Password") + notificationMessage: root.notificationMessage + userPlaceholderText: qsTr("User") + + onLoginRequest: { + root.notificationMessage = "" + nss.login(username, password) + } + } + + Behavior on opacity { + OpacityAnimator { + duration: longDuration + } + } + } + Loader { + id: inputPanel + state: "hidden" + property bool keyboardActive: false + onKeyboardActiveChanged: { + if (keyboardActive) { + state = "visible" + } else { + state = "hidden"; + } + } + Component.onCompleted: { + VirtualKeyboardSettings.locale = "lang_en" + } + + source: "VirtualKeyboard.qml" + width: 500 + anchors.horizontalCenter: parent.horizontalCenter + function showHide() { + state = state == "hidden" ? "visible" : "hidden"; + } + + states: [ + State { + name: "visible" + PropertyChanges { + target: inputPanel + y: root.height - inputPanel.height - (root.height - footer.y) + opacity: 1 + } + }, + State { + name: "hidden" + PropertyChanges { + target: inputPanel + y: root.height - (root.height - footer.y) + opacity: 0 + } + } + ] + transitions: [ + Transition { + from: "hidden" + to: "visible" + SequentialAnimation { + ScriptAction { + script: { + inputPanel.item.activated = true + Qt.inputMethod.show(); + } + } + ParallelAnimation { + NumberAnimation { + target: inputPanel + property: "y" + duration: longDuration + easing.type: Easing.OutQuad + } + OpacityAnimator { + target: inputPanel + duration: longDuration + easing.type: Easing.OutQuad + } + } + } + }, + Transition { + from: "visible" + to: "hidden" + SequentialAnimation { + ParallelAnimation { + NumberAnimation { + target: inputPanel + property: "y" + duration: longDuration + easing.type: Easing.InQuad + } + OpacityAnimator { + target: inputPanel + duration: longDuration + easing.type: Easing.InQuad + } + } + ScriptAction { + script: { + inputPanel.item.activated = false + Qt.inputMethod.hide(); + } + } + } + } + ] + } + Clock { + id: clock + anchors{ + left: parent.left + bottom: parent.bottom + } + anchors.leftMargin: 30 + anchors.bottomMargin: 15 + color: "white" + timeFont.family: "Oxygen" + property Item shadow: clockShadow + } + DropShadow { + id: clockShadow + anchors.fill: clock + source: clock + horizontalOffset: 1 + verticalOffset: 1 + visible: !softwareRendering + radius: 6 + samples: 14 + spread: 0.3 + color: root.lightBackground ? backgroundColor : "black" + Behavior on opacity { + OpacityAnimator { + duration: 1000 + easing.type: Easing.InOutQuad + } + } + } + Item{ + id: footer + anchors{ + left: parent.left + right: parent.right + bottom: parent.bottom + } + anchors{ + leftMargin: 30 + rightMargin: 30 + } + height: 100 + IconButton { + id: sleep + anchors.centerIn: parent + iconSource: "sleep.png" + text: qsTr("Sleep") + width: gridUnit * 3 + smallSpacing + height: gridUnit * 3 + smallSpacing + visible: nss.canHibernate && !nss.isVirtualMachine + onClicked: nss.hibernate() + } + IconButton { + id: reboot + anchors.right: parent.horizontalCenter + anchors.rightMargin: nss.isVirtualMachine ? width/2 : width + anchors.verticalCenter: parent.verticalCenter + iconSource: "reboot.png" + text: qsTr("Reboot") + width: gridUnit * 3 + smallSpacing + height: gridUnit * 3 + smallSpacing + visible: nss.canReboot + onClicked: nss.reboot() + } + IconButton { + anchors.left: parent.horizontalCenter + anchors.leftMargin: nss.isVirtualMachine ? width /2 : width + anchors.verticalCenter: parent.verticalCenter + iconSource: "poweroff.png" + text: qsTr("Shutdown") + width: gridUnit * 3 + smallSpacing + height: gridUnit * 3 + smallSpacing + visible: nss.canPowerOff + onClicked: nss.powerOff() + } + IconButton { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + iconSource: "keyboard.png" + width: gridUnit * 2 + smallSpacing + height: gridUnit * 2 + smallSpacing + onClicked: inputPanel.showHide() + } + } + } + + Connections { + target: nss + onLoginFailed: { + notificationMessage = qsTr("Login Failed") + + footer.enabled = true + mainStack.enabled = true + userListComponent.userList.opacity = 1 + userListComponent.isOn = false + userListComponent.mainPasswordBox.enabled = true + loginScreenRoot.blockUI = false; + } + onLoginSucceeded: { + mainStack.opacity = 0 + footer.opacity = 0 + userListComponent.isOn = false + userListComponent.mainPasswordBox.enabled = true + loginScreenRoot.blockUI = false; + } + onLoggingIn: { + userListComponent.mainPasswordBox.enabled = false + userListComponent.mainUserBox.enabled = false + userListComponent.isOn = true + loginScreenRoot.blockUI = true; + } + } + Connections { + target: keyboard + onCapsLockStateChanged: { + var text = "" + if(keyboard.capsLock){ + text += qsTr("Caps Lock is on") + } + notificationMessage = text + } + } +} diff --git a/nde-screensaver-0.1.0/src/greeter/theme/VirtualKeyboard.qml b/nde-screensaver-0.1.0/src/greeter/theme/VirtualKeyboard.qml new file mode 100644 index 0000000..ba1df44 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/theme/VirtualKeyboard.qml @@ -0,0 +1,8 @@ +import QtQuick 2.5 +import QtQuick.VirtualKeyboard 2.1 +InputPanel { + id: inputPanel + property bool activated: false + active: activated && Qt.inputMethod.visible + visible: active +} diff --git a/nde-screensaver-0.1.0/src/greeter/theme/keyboard.png b/nde-screensaver-0.1.0/src/greeter/theme/keyboard.png new file mode 100644 index 0000000000000000000000000000000000000000..710cda8de6f1b33cd3b1823885f33e822cf4b78f GIT binary patch literal 1391 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFe_z-M3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcpgi&u1T;Y}Gc(1?%-GG;)zrw;(Ztc&(9qS<$-vpn($Lw_(8S!p z+{nTWrq?AuximL5uLPzy1)fmg#GAw>wYxwf|!9cF(+W&54`aReFuiS6Pj-tg#M^o&h{}g-hA5V%({6`v~SG4`_uCOn=^AdOLxa=dkOyLZwgXi&oSU%c2MGO zHM{=<#*l-u8T?)sbZ)R|E4=(XlTV|$_`?eC3kDhuz6K%}I`az{`woWNH>EjDTys(I z%qi#4Z6Qr!2L)$bvdNo&&~C+7rHz?wjX1-js{aVE>`py+&E%oz&MvS2vTkyn`+r(>7MHdgqH&X#fFnc_BmP02HUo#Kmc9hxT@ zar?&ft*|7MB6mVhVTFKxA!3fI>7s>&`kkuOf*Uegpf|NMqo zuV?W|OR4oGi@mT&oAYk(#lkatJ0H(DAs4}GQpYO6U|O|o=UJtwqo5+t)78&qol`;+ E03hJ@M*si- literal 0 HcmV?d00001 diff --git a/nde-screensaver-0.1.0/src/greeter/theme/poweroff.png b/nde-screensaver-0.1.0/src/greeter/theme/poweroff.png new file mode 100644 index 0000000000000000000000000000000000000000..69db222910bfeae0b3ff6a99fe725d69f8ff9079 GIT binary patch literal 1329 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDi`YUpNQVPS6SXyWK>Xz1!_Vd-RS;cVbyWbR~X zU}|6q)9aF-T$-DjR|3v4~Pj*wm=R%;iu*SQ+p9GSxe4~5NBXuTc4;syW3AKHJoU$OpW-zIp)%klS##$I^Yixw}0p9iH91Gdw)xNmipbuSUN3Itml%}!H%^n9;i;Z?euJ7m;AT2HPamz z9$$ZfFSlAc%UyU6UI zGmEXzs=m21l2&&Jixsn6fB45UVv|ZKCtJtw2LIEl5sG&XZG7wTLU_t?Z5_wB#SgUR z{A$VYa1@+>Xuan3ubXZ#$qVjl%h6K$Co$hVw{!=Oo&L(na~reG4qASw^=vACP`Ohe zlP~yzy8j|==V;@b3^tjc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDi`;^JiCWMORNXyWK>Xz1$b=xk=;V(RK_Z0uxd z;9_YA)9aF-T$-DjR|3Q!gkfv4~Pj*wm=R%;iu*SQ+p9GS$n^KRKvi)xX#nXF{I+w zooQ#i4m*gnN?%+T6SXiTNlee>=+tQOT1LSbiQimYN|)>cO-%w{3P&vTj(rs-DB>D> zvv*Ohjk3A{?@OP5Zw@u~b00oqd(x-qooUT|{hneUkz+P$$?J?Ac|#5gX*BA8V0d?s zHKWlwSFLafmrnuDzS_Spir20@wNmId!+W1^oKXqv5eqn$9aMTAvrcgF@trPBziW~V z&mCxbrot6de9D%&Kp?zew)7E0vm}nz%!2m~JEt_M^&j!qRO@Ctp1q2tf5(N>3Stio zryF|}%=@mUSFgu@kgNFX%-`j4|32nQH6H)3{knohulQD=UvO&9^9-H00q+zKiXJ;H z!@AySXFE%}#C&D5vR2K^7jAE=lXO;|**)V^ZqJfuf7!Ga@Kh}knw7w?Cb$%h0oBlmG{y)Jld&*YJEz0KXj^XLKiJ#Y{3#>kFn%}59 zb@^VAq}@T4n=Xqyn9Ra@V=~u=#A{-UIk){_^bzbXJ{!;-=zaMzOZh90{MFfuWMYL= zkL0vGH7k@nQ}nO3?P8+luB*T9?|;9io<)K|>VrIE*U<%MK&6?dtDnm{r-UW|!1LcR literal 0 HcmV?d00001 diff --git a/nde-screensaver-0.1.0/src/greeter/theme/sleep.png b/nde-screensaver-0.1.0/src/greeter/theme/sleep.png new file mode 100644 index 0000000000000000000000000000000000000000..a63394639841b6177ce4ef174999e5dae6082f28 GIT binary patch literal 1432 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDi`Vrgb-U|?wJXyWK>Xz1$bWa((&XlP>S=xkv4~Pj*wm=R%;iu*SQ+p9GS;x3V`7tms@p!s8hE&|T zGtFDuB~jw|bA!Oi6O}Zb6E``AEs~hBXo^X)>QS!N)~Wgrn13)_OG#a$ax(Q`Qrg2y z9LdK_4j)TZl$v$oWBu#(e#XzO=B7Pd8-IRI<^0n-_xyies~R~?wpGTpkEy>&yd-Le zp}Yi3?g8Fqj%SKoKk}ANI3Ut-a%b`-g)q^*>TB3uCp27NuE5deC|}gIdHUNt?|mm7vCj=7K;cI2FSg8jvi648 zSA||Ut`e=rW#u^IpZkKyqs!&*Tw3nz`{U`BOyT%P(mxLByx>+i&31X|(+JF67K|2hJ6NuOfopv@hCyr4DpQqO&#r`1Rmi^V~(M1x64v>GJE31MZ0#Y vZrxbjalpOc;Bu>H^}jm*{XO|Ryn&HH;QsNJ%QM?nfXYfwS3j3^P6 + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/bn.ts b/nde-screensaver-0.1.0/src/greeter/translations/bn.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/bn.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/ca.ts b/nde-screensaver-0.1.0/src/greeter/translations/ca.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/ca.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/cs.ts b/nde-screensaver-0.1.0/src/greeter/translations/cs.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/cs.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/da.ts b/nde-screensaver-0.1.0/src/greeter/translations/da.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/da.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/de.ts b/nde-screensaver-0.1.0/src/greeter/translations/de.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/de.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/es.ts b/nde-screensaver-0.1.0/src/greeter/translations/es.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/es.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/et.ts b/nde-screensaver-0.1.0/src/greeter/translations/et.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/et.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/fi.ts b/nde-screensaver-0.1.0/src/greeter/translations/fi.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/fi.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/fr.ts b/nde-screensaver-0.1.0/src/greeter/translations/fr.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/fr.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/hi_IN.ts b/nde-screensaver-0.1.0/src/greeter/translations/hi_IN.ts new file mode 100644 index 0000000..7f0f20e --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/hi_IN.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/hu.ts b/nde-screensaver-0.1.0/src/greeter/translations/hu.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/hu.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/is.ts b/nde-screensaver-0.1.0/src/greeter/translations/is.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/is.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/it.ts b/nde-screensaver-0.1.0/src/greeter/translations/it.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/it.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/ja.ts b/nde-screensaver-0.1.0/src/greeter/translations/ja.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/ja.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/kk.ts b/nde-screensaver-0.1.0/src/greeter/translations/kk.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/kk.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/ko.ts b/nde-screensaver-0.1.0/src/greeter/translations/ko.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/ko.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/lt.ts b/nde-screensaver-0.1.0/src/greeter/translations/lt.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/lt.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/lv.ts b/nde-screensaver-0.1.0/src/greeter/translations/lv.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/lv.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/nb.ts b/nde-screensaver-0.1.0/src/greeter/translations/nb.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/nb.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/nl.ts b/nde-screensaver-0.1.0/src/greeter/translations/nl.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/nl.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/nn.ts b/nde-screensaver-0.1.0/src/greeter/translations/nn.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/nn.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/pl.ts b/nde-screensaver-0.1.0/src/greeter/translations/pl.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/pl.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/pt_BR.ts b/nde-screensaver-0.1.0/src/greeter/translations/pt_BR.ts new file mode 100644 index 0000000..ad1f8e6 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/pt_BR.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/pt_PT.ts b/nde-screensaver-0.1.0/src/greeter/translations/pt_PT.ts new file mode 100644 index 0000000..839f597 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/pt_PT.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/ro.ts b/nde-screensaver-0.1.0/src/greeter/translations/ro.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/ro.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/ru.ts b/nde-screensaver-0.1.0/src/greeter/translations/ru.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/ru.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/sk.ts b/nde-screensaver-0.1.0/src/greeter/translations/sk.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/sk.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/sr.ts b/nde-screensaver-0.1.0/src/greeter/translations/sr.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/sr.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/sr@ijekavian.ts b/nde-screensaver-0.1.0/src/greeter/translations/sr@ijekavian.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/sr@ijekavian.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/sr@ijekavianlatin.ts b/nde-screensaver-0.1.0/src/greeter/translations/sr@ijekavianlatin.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/sr@ijekavianlatin.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/sr@latin.ts b/nde-screensaver-0.1.0/src/greeter/translations/sr@latin.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/sr@latin.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/sv.ts b/nde-screensaver-0.1.0/src/greeter/translations/sv.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/sv.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/tr.ts b/nde-screensaver-0.1.0/src/greeter/translations/tr.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/tr.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/uk.ts b/nde-screensaver-0.1.0/src/greeter/translations/uk.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/uk.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/zh_CN.ts b/nde-screensaver-0.1.0/src/greeter/translations/zh_CN.ts new file mode 100644 index 0000000..1b84dae --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/zh_CN.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + 密码 + + + User + 用户 + + + Sleep + 睡眠 + + + Reboot + 重启 + + + Shutdown + 关机 + + + Login Failed + 登录失败 + + + Login failed,Please contact support + 登录失败,请联系支持 + + + Login failed,Please try again later + 登录失败,请稍后重试 + + + Caps Lock is on + 大小写锁定 + + + + QObject + + %1 (Wayland) + %1 (Wayland) + + + diff --git a/nde-screensaver-0.1.0/src/greeter/translations/zh_TW.ts b/nde-screensaver-0.1.0/src/greeter/translations/zh_TW.ts new file mode 100644 index 0000000..d60d577 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/translations/zh_TW.ts @@ -0,0 +1,50 @@ + + + + + Main + + Password + + + + User + + + + Sleep + + + + Reboot + + + + Shutdown + + + + Login Failed + + + + Login failed,Please contact support + + + + Login failed,Please try again later + + + + Caps Lock is on + + + + + QObject + + %1 (Wayland) + + + + diff --git a/nde-screensaver-0.1.0/src/greeter/xservergrabber.cpp b/nde-screensaver-0.1.0/src/greeter/xservergrabber.cpp new file mode 100644 index 0000000..9b98927 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/xservergrabber.cpp @@ -0,0 +1,73 @@ +#include "xservergrabber.h" +#include +#include +#include +#include +namespace NSS { + +static bool grabKeyboard() +{ + int rv = XGrabKeyboard( QX11Info::display(), QX11Info::appRootWindow(), + True, GrabModeAsync, GrabModeAsync, CurrentTime ); + + return (rv == GrabSuccess); +} + +static bool grabMouse() +{ +#define GRABEVENTS ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \ + EnterWindowMask | LeaveWindowMask + int rv = XGrabPointer( QX11Info::display(), QX11Info::appRootWindow(), + True, GRABEVENTS, GrabModeAsync, GrabModeAsync, None, + None, CurrentTime ); +#undef GRABEVENTS + + return (rv == GrabSuccess); +} + +class XServerGrabber +{ +public: + XServerGrabber() { + xcb_grab_server(QX11Info::connection()); + } + ~XServerGrabber() { + xcb_ungrab_server(QX11Info::connection()); + xcb_flush(QX11Info::connection()); + } +}; +bool closeGrab() +{ + XSync(QX11Info::display(), False); + XServerGrabber xserverGraber; + + Q_UNUSED(xserverGraber) + + XUngrabKeyboard(QX11Info::display(), CurrentTime); + XUngrabPointer(QX11Info::display(), CurrentTime); + XFlush(QX11Info::display()); + return true; +} +bool establishGrab() +{ + XWindowAttributes rootAttr; + XGetWindowAttributes(QX11Info::display(), QX11Info::appRootWindow(), &rootAttr); + XSelectInput( QX11Info::display(), QX11Info::appRootWindow(), + SubstructureNotifyMask|rootAttr.your_event_mask ); + if (!QX11Info::isPlatformX11()) { + return true; + } + XSync(QX11Info::display(), False); + XServerGrabber serverGrabber; + if (!grabKeyboard()) { + return false; + } + + if (!grabMouse()) { + XUngrabKeyboard(QX11Info::display(), CurrentTime); + XFlush(QX11Info::display()); + return false; + } + return true; +} +} diff --git a/nde-screensaver-0.1.0/src/greeter/xservergrabber.h b/nde-screensaver-0.1.0/src/greeter/xservergrabber.h new file mode 100644 index 0000000..cf96ec8 --- /dev/null +++ b/nde-screensaver-0.1.0/src/greeter/xservergrabber.h @@ -0,0 +1,8 @@ +#ifndef XSERVERGRABBER_H +#define XSERVERGRABBER_H + +namespace NSS { +bool establishGrab(); +bool closeGrab(); +} +#endif // XSERVERGRABBER_H diff --git a/nde-screensaver-0.1.0/src/helper/Backend.cpp b/nde-screensaver-0.1.0/src/helper/Backend.cpp new file mode 100644 index 0000000..17f510c --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/Backend.cpp @@ -0,0 +1,47 @@ +/* + * Base backend class to be inherited further + * Copyright (C) 2013 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "Backend.h" +#include "HelperApp.h" + +#include "backend/PamBackend.h" +#include "backend/PasswdBackend.h" +//#include "Configuration.h" +//#include "UserSession.h" + +#include + +#include + +namespace NSS { + Backend::Backend(HelperApp* parent) + : QObject(parent) + , m_app(parent) { + } + + Backend *Backend::get(HelperApp* parent) + { + #ifdef USE_PAM + return new PamBackend(parent); + #else + return new PasswdBackend(parent); + #endif + } +} diff --git a/nde-screensaver-0.1.0/src/helper/Backend.h b/nde-screensaver-0.1.0/src/helper/Backend.h new file mode 100644 index 0000000..6154e4e --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/Backend.h @@ -0,0 +1,51 @@ +/* + * Base backend class to be inherited further + * Copyright (C) 2013 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef BACKEND_H +#define BACKEND_H + +#include + +namespace NSS { + class HelperApp; + class Backend : public QObject + { + Q_OBJECT + public: + /** + * Requests allocation of a new backend instance. + * The method chooses the most suitable one for the current system. + */ + static Backend *get(HelperApp *parent); + + public slots: + virtual bool start(const QString &user = QString()) = 0; + virtual bool authenticate() = 0; + + + virtual QString userName() = 0; + + protected: + Backend(HelperApp *parent); + HelperApp *m_app; + }; +} + +#endif // BACKEND_H diff --git a/nde-screensaver-0.1.0/src/helper/CMakeLists.txt b/nde-screensaver-0.1.0/src/helper/CMakeLists.txt new file mode 100644 index 0000000..cfdcc82 --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/CMakeLists.txt @@ -0,0 +1,42 @@ +include_directories( + "${CMAKE_SOURCE_DIR}/src/common" + "${CMAKE_SOURCE_DIR}/src/auth" +) +include_directories("${CMAKE_BINARY_DIR}/src/common") + +set(HELPER_SOURCES + ${CMAKE_SOURCE_DIR}/src/common/SafeDataStream.cpp + Backend.cpp + HelperApp.cpp +) + +if(PAM_FOUND) + set(HELPER_SOURCES + ${HELPER_SOURCES} + backend/PamHandle.cpp + backend/PamBackend.cpp + ) +else() + set(HELPER_SOURCES + ${HELPER_SOURCES} + backend/PasswdBackend.cpp + ) + + if(HAVE_GETSPNAM) + add_definitions(-DHAVE_GETSPNAM=1) + endif() +endif() + +add_executable(nde-screensaver-helper ${HELPER_SOURCES}) +target_link_libraries(nde-screensaver-helper Qt5::Network Qt5::DBus Qt5::Qml ${LIBXAU_LIBRARIES}) +if(PAM_FOUND) + target_link_libraries(nde-screensaver-helper ${PAM_LIBRARIES}) +else() + target_link_libraries(nde-screensaver-helper crypt) +endif() + +if(JOURNALD_FOUND) + target_link_libraries(nde-screensaver-helper ${JOURNALD_LIBRARIES}) +endif() + +install(TARGETS nde-screensaver-helper RUNTIME DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}") diff --git a/nde-screensaver-0.1.0/src/helper/HelperApp.cpp b/nde-screensaver-0.1.0/src/helper/HelperApp.cpp new file mode 100644 index 0000000..a9048b6 --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/HelperApp.cpp @@ -0,0 +1,176 @@ +/* + * Main authentication application class + * Copyright (C) 2013 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "HelperApp.h" +#include "Backend.h" +#include "SafeDataStream.h" +#include "MessageHandler.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace NSS { + HelperApp::HelperApp(int& argc, char** argv) + : QCoreApplication(argc, argv) + , m_backend(Backend::get(this)) + , m_socket(new QLocalSocket(this)) { + qInstallMessageHandler(HelperMessageHandler); + + QTimer::singleShot(0, this, SLOT(setUp())); + } + + void HelperApp::setUp() { + QStringList args = QCoreApplication::arguments(); + QString server; + int pos; + + if ((pos = args.indexOf(QStringLiteral("--socket"))) >= 0) { + if (pos >= args.length() - 1) { + qCritical() << "This application is not supposed to be executed manually"; + exit(Auth::HELPER_OTHER_ERROR); + return; + } + server = args[pos + 1]; + } + + if ((pos = args.indexOf(QStringLiteral("--id"))) >= 0) { + if (pos >= args.length() - 1) { + qCritical() << "This application is not supposed to be executed manually"; + exit(Auth::HELPER_OTHER_ERROR); + return; + } + m_id = QString(args[pos + 1]).toLongLong(); + } + + if ((pos = args.indexOf(QStringLiteral("--user"))) >= 0) { + if (pos >= args.length() - 1) { + qCritical() << "This application is not supposed to be executed manually"; + exit(Auth::HELPER_OTHER_ERROR); + return; + } + m_user = args[pos + 1]; + } + + if (server.isEmpty() || m_id <= 0) { + qCritical() << "This application is not supposed to be executed manually"; + exit(Auth::HELPER_OTHER_ERROR); + return; + } + connect(m_socket, SIGNAL(connected()), this, SLOT(doAuth())); + m_socket->connectToServer(server, QIODevice::ReadWrite | QIODevice::Unbuffered); + } + + void HelperApp::doAuth() { + SafeDataStream str(m_socket); + str << Msg::HELLO << m_id; + str.send(); + if (str.status() != QDataStream::Ok) + qCritical() << "Couldn't write initial message:" << str.status(); + + if (!m_backend->start(m_user)) { + authenticated(QString()); + exit(Auth::HELPER_AUTH_ERROR); + return; + } + if (!m_backend->authenticate()) { + authenticated(QString()); + exit(Auth::HELPER_AUTH_ERROR); + return; + } + + m_user = m_backend->userName(); + QProcessEnvironment env = authenticated(m_user); + exit(Auth::HELPER_SUCCESS); + return; + } + void HelperApp::info(const QString& message, Auth::Info type) { + SafeDataStream str(m_socket); + str << Msg::INFO << message << type; + str.send(); + m_socket->waitForBytesWritten(); + } + + void HelperApp::error(const QString& message, Auth::Error type) { + SafeDataStream str(m_socket); + str << Msg::ERROR << message << type; + str.send(); + m_socket->waitForBytesWritten(); + } + + Request HelperApp::request(const Request& request) { + Msg m = Msg::MSG_UNKNOWN; + Request response; + SafeDataStream str(m_socket); + str << Msg::REQUEST << request; + str.send(); + str.receive(); + str >> m >> response; + if (m != REQUEST) { + response = Request(); + qCritical() << "Received a wrong opcode instead of REQUEST:" << m; + } + return response; + } + + QProcessEnvironment HelperApp::authenticated(const QString &user) { + Msg m = Msg::MSG_UNKNOWN; + QProcessEnvironment env; + SafeDataStream str(m_socket); + str << Msg::AUTHENTICATED << user; + str.send(); + if (user.isEmpty()) + return env; + str.receive(); + str >> m >> env >> m_cookie; + if (m != AUTHENTICATED) { + env = QProcessEnvironment(); + m_cookie = QString(); + qCritical() << "Received a wrong opcode instead of AUTHENTICATED:" << m; + } + return env; + } + const QString& HelperApp::user() const { + return m_user; + } + + const QString& HelperApp::cookie() const { + return m_cookie; + } + + HelperApp::~HelperApp() { + + } +} + +int main(int argc, char** argv) { + NSS::HelperApp app(argc, argv); + return app.exec(); +} diff --git a/nde-screensaver-0.1.0/src/helper/HelperApp.h b/nde-screensaver-0.1.0/src/helper/HelperApp.h new file mode 100644 index 0000000..bc21b68 --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/HelperApp.h @@ -0,0 +1,67 @@ +/* + * Main authentication application class + * Copyright (C) 2013 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef Auth_H +#define Auth_H + +#include +#include + +#include "AuthMessages.h" + +class QLocalSocket; + +namespace NSS { + class Backend; + class UserSession; + class HelperApp : public QCoreApplication + { + Q_OBJECT + public: + HelperApp(int& argc, char** argv); + virtual ~HelperApp(); + + UserSession *session(); + const QString &user() const; + const QString &cookie() const; + + public slots: + Request request(const Request &request); + void info(const QString &message, Auth::Info type); + void error(const QString &message, Auth::Error type); + QProcessEnvironment authenticated(const QString &user); + + private slots: + void setUp(); + void doAuth(); + +// void sessionFinished(int status); + + private: + qint64 m_id { -1 }; + Backend *m_backend { nullptr }; + QLocalSocket *m_socket { nullptr }; + QString m_user { }; + + QString m_cookie { }; + }; +} + +#endif // Auth_H diff --git a/nde-screensaver-0.1.0/src/helper/backend/PamBackend.cpp b/nde-screensaver-0.1.0/src/helper/backend/PamBackend.cpp new file mode 100644 index 0000000..8847f3a --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/backend/PamBackend.cpp @@ -0,0 +1,305 @@ +/* + * PAM authentication backend + * Copyright (C) 2013 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "PamBackend.h" +#include "PamHandle.h" +#include "HelperApp.h" +//#include "UserSession.h" +#include "Auth.h" + +#include +#include + +#include + +namespace NSS { + static Request loginRequest { + { { AuthPrompt::LOGIN_USER, QStringLiteral("login:"), false }, + { AuthPrompt::LOGIN_PASSWORD, QStringLiteral("Password: "), true } + } + }; + + static Request changePassRequest { + { { AuthPrompt::CHANGE_CURRENT, QStringLiteral("(current) UNIX password: "), true }, + { AuthPrompt::CHANGE_NEW, QStringLiteral("New password: "), true }, + { AuthPrompt::CHANGE_REPEAT, QStringLiteral("Retype new password: "), true } + } + }; + + static Request changePassNoOldRequest { + { { AuthPrompt::CHANGE_NEW, QStringLiteral("New password: "), true }, + { AuthPrompt::CHANGE_REPEAT, QStringLiteral("Retype new password: "), true } + } + }; + + static Request invalidRequest { {} }; + + static Prompt invalidPrompt {}; + + PamData::PamData() { } + + AuthPrompt::Type PamData::detectPrompt(const struct pam_message* msg) const { + if (msg->msg_style == PAM_PROMPT_ECHO_OFF) { + QString message = QString::fromLocal8Bit(msg->msg); + if (message.indexOf(QRegExp(QStringLiteral("\\bpassword\\b"), Qt::CaseInsensitive)) >= 0) { + if (message.indexOf(QRegExp(QStringLiteral("\\b(re-?(enter|type)|again|confirm|repeat)\\b"), Qt::CaseInsensitive)) >= 0) { + return AuthPrompt::CHANGE_REPEAT; + } + else if (message.indexOf(QRegExp(QStringLiteral("\\bnew\\b"), Qt::CaseInsensitive)) >= 0) { + return AuthPrompt::CHANGE_NEW; + } + else if (message.indexOf(QRegExp(QStringLiteral("\\b(old|current)\\b"), Qt::CaseInsensitive)) >= 0) { + return AuthPrompt::CHANGE_CURRENT; + } + else { + return AuthPrompt::LOGIN_PASSWORD; + } + } + } + else { + return AuthPrompt::LOGIN_USER; + } + + return AuthPrompt::UNKNOWN; + } + + const Prompt& PamData::findPrompt(const struct pam_message* msg) const { + AuthPrompt::Type type = detectPrompt(msg); + + for (const Prompt &p : m_currentRequest.prompts) { + if (type == p.type && p.message == QString::fromLocal8Bit(msg->msg)) + return p; + } + + return invalidPrompt; + } + + Prompt& PamData::findPrompt(const struct pam_message* msg) { + AuthPrompt::Type type = detectPrompt(msg); + + for (Prompt &p : m_currentRequest.prompts) { + if (type == AuthPrompt::UNKNOWN && QString::fromLocal8Bit(msg->msg) == p.message) + return p; + if (type == p.type) + return p; + } + + return invalidPrompt; + } + + /* + * Expects an empty prompt list if the previous request has been processed + */ + bool PamData::insertPrompt(const struct pam_message* msg, bool predict) { + Prompt &p = findPrompt(msg); + + // first, check if we already have stored this propmpt + if (p.valid()) { + // we have a response already - do nothing + if (m_sent) + return false; + // we don't have a response yet - replace the message and prepare to send it + p.message = QString::fromLocal8Bit(msg->msg); + return true; + } + // this prompt is not stored but we have some prompts + else if (m_currentRequest.prompts.length() != 0) { + // check if we have already sent this - if we did, get rid of the answers + if (m_sent) { + m_currentRequest.clear(); + m_sent = false; + } + } + + // we'll predict what will come next + if (predict) { + AuthPrompt::Type type = detectPrompt(msg); + switch (type) { + case AuthPrompt::LOGIN_USER: + m_currentRequest = Request(loginRequest); + return true; + case AuthPrompt::CHANGE_CURRENT: + m_currentRequest = Request(changePassRequest); + return true; + case AuthPrompt::CHANGE_NEW: + m_currentRequest = Request(changePassNoOldRequest); + return true; + default: + break; + } + } + + // or just add whatever comes exactly as it comes + m_currentRequest.prompts.append(Prompt(detectPrompt(msg), QString::fromLocal8Bit(msg->msg), msg->msg_style == PAM_PROMPT_ECHO_OFF)); + + return true; + } + + Auth::Info PamData::handleInfo(const struct pam_message* msg, bool predict) { + if (QString::fromLocal8Bit(msg->msg).indexOf(QRegExp(QStringLiteral("^Changing password for [^ ]+$")))) { + if (predict) + m_currentRequest = Request(changePassRequest); + return Auth::INFO_PASS_CHANGE_REQUIRED; + } + return Auth::INFO_UNKNOWN; + } + + /* + * Destroys the prompt with that response + */ + QByteArray PamData::getResponse(const struct pam_message* msg) { + QByteArray response = findPrompt(msg).response; + m_currentRequest.prompts.removeOne(findPrompt(msg)); + if (m_currentRequest.prompts.length() == 0) + m_sent = false; + return response; + } + + const Request& PamData::getRequest() const { + if (!m_sent) + return m_currentRequest; + else + return invalidRequest; + } + + void PamData::completeRequest(const Request& request) { + if (request.prompts.length() != m_currentRequest.prompts.length()) { + qWarning() << "[PAM] Different request/response list length, ignoring"; + return; + } + + for (int i = 0; i < request.prompts.length(); i++) { + if (request.prompts[i].type != m_currentRequest.prompts[i].type + || request.prompts[i].message != m_currentRequest.prompts[i].message + || request.prompts[i].hidden != m_currentRequest.prompts[i].hidden) { + qWarning() << "[PAM] Order or type of the messages doesn't match, ignoring"; + return; + } + } + + m_currentRequest = request; + m_sent = true; + } + PamBackend::PamBackend(HelperApp *parent) + : Backend(parent) + , m_data(new PamData()) + , m_pam(new PamHandle(this)) { + } + + PamBackend::~PamBackend() { + delete m_data; + delete m_pam; + } + + bool PamBackend::start(const QString &user) { + bool result; + + QString service = QStringLiteral("nde-screensaver"); + result = m_pam->start(service, user); + + if (!result) + m_app->error(m_pam->errorString(), Auth::ERROR_INTERNAL); + + return result; + } + + bool PamBackend::authenticate() { + if (!m_pam->authenticate()) { + m_app->error(m_pam->errorString(), Auth::ERROR_AUTHENTICATION); + return false; + } + if (!m_pam->acctMgmt()) { + m_app->error(m_pam->errorString(), Auth::ERROR_AUTHENTICATION); + return false; + } + return true; + } + + QString PamBackend::userName() { + return QString::fromLocal8Bit((const char*) m_pam->getItem(PAM_USER)); + } + + int PamBackend::converse(int n, const struct pam_message **msg, struct pam_response **resp) { + qDebug() << "[PAM] Conversation with" << n << "messages"; + + bool newRequest = false; + + if (n <= 0 || n > PAM_MAX_NUM_MSG) + return PAM_CONV_ERR; + + for (int i = 0; i < n; i++) { + switch(msg[i]->msg_style) { + case PAM_PROMPT_ECHO_OFF: + case PAM_PROMPT_ECHO_ON: + newRequest = m_data->insertPrompt(msg[i], n == 1); + break; + case PAM_ERROR_MSG: + m_app->error(QString::fromLocal8Bit(msg[i]->msg), Auth::ERROR_AUTHENTICATION); + break; + case PAM_TEXT_INFO: + // if there's only the info message, let's predict the prompts too + m_app->info(QString::fromLocal8Bit(msg[i]->msg), m_data->handleInfo(msg[i], n == 1)); + break; + default: + break; + } + } + + if (newRequest) { + Request sent = m_data->getRequest(); + Request received; + + if (sent.valid()) { + received = m_app->request(sent); + + if (!received.valid()) + return PAM_CONV_ERR; + + m_data->completeRequest(received); + } + } + + *resp = (struct pam_response *) calloc(n, sizeof(struct pam_response)); + if (!*resp) { + return PAM_BUF_ERR; + } + + for (int i = 0; i < n; i++) { + QByteArray response = m_data->getResponse(msg[i]); + + resp[i]->resp = (char *) malloc(response.length() + 1); + // on error, get rid of everything + if (!resp[i]->resp) { + for (int j = 0; j < n; j++) { + free(resp[i]->resp); + resp[i]->resp = nullptr; + } + free(*resp); + *resp = nullptr; + return PAM_BUF_ERR; + } + + memcpy(resp[i]->resp, response.constData(), response.length()); + resp[i]->resp[response.length()] = '\0'; + } + + return PAM_SUCCESS; + } +} diff --git a/nde-screensaver-0.1.0/src/helper/backend/PamBackend.h b/nde-screensaver-0.1.0/src/helper/backend/PamBackend.h new file mode 100644 index 0000000..521c41b --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/backend/PamBackend.h @@ -0,0 +1,76 @@ +/* + * PAM authentication backend + * Copyright (C) 2013 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#if !defined(PAMBACKEND_H) && defined(USE_PAM) +#define PAMBACKEND_H + +#include "Constants.h" +#include "AuthMessages.h" +#include "../Backend.h" + +#include + +#include + +namespace NSS { + class PamHandle; + class PamBackend; + class PamData { + public: + PamData(); + + bool insertPrompt(const struct pam_message *msg, bool predict = true); + Auth::Info handleInfo(const struct pam_message *msg, bool predict); + + const Request& getRequest() const; + void completeRequest(const Request& request); + + QByteArray getResponse(const struct pam_message *msg); + + private: + AuthPrompt::Type detectPrompt(const struct pam_message *msg) const; + + const Prompt& findPrompt(const struct pam_message *msg) const; + Prompt& findPrompt(const struct pam_message *msg); + + bool m_sent { false }; + Request m_currentRequest { }; + }; + + class PamBackend : public Backend + { + Q_OBJECT + public: + explicit PamBackend(HelperApp *parent); + virtual ~PamBackend(); + int converse(int n, const struct pam_message **msg, struct pam_response **resp); + + public slots: + virtual bool start(const QString &user = QString()); + virtual bool authenticate(); + virtual QString userName(); + + private: + PamData *m_data { nullptr }; + PamHandle *m_pam { nullptr }; + }; +} + +#endif // PAMBACKEND_H diff --git a/nde-screensaver-0.1.0/src/helper/backend/PamHandle.cpp b/nde-screensaver-0.1.0/src/helper/backend/PamHandle.cpp new file mode 100644 index 0000000..bbd0a54 --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/backend/PamHandle.cpp @@ -0,0 +1,189 @@ +/* + * PAM API Qt wrapper + * Copyright (C) 2013 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#include "PamHandle.h" +#include "PamBackend.h" + +#include + +namespace NSS { + bool PamHandle::putEnv(const QProcessEnvironment& env) { + foreach (const QString& s, env.toStringList()) { + m_result = pam_putenv(m_handle, qPrintable(s)); + if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] putEnv:" << pam_strerror(m_handle, m_result); + return false; + } + } + return true; + } + + QProcessEnvironment PamHandle::getEnv() { + QProcessEnvironment env; + // get pam environment + char **envlist = pam_getenvlist(m_handle); + if (envlist == NULL) { + qWarning() << "[PAM] getEnv: Returned NULL"; + return env; + } + + // copy it to the env map + for (int i = 0; envlist[i] != nullptr; ++i) { + QString s = QString::fromLocal8Bit(envlist[i]); + + // find equal sign + int index = s.indexOf(QLatin1Char('=')); + + // add to the hash + if (index != -1) + env.insert(s.left(index), s.mid(index + 1)); + + free(envlist[i]); + } + free(envlist); + return env; + } + + bool PamHandle::chAuthTok(int flags) { + m_result = pam_chauthtok(m_handle, flags | m_silent); + if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] chAuthTok:" << pam_strerror(m_handle, m_result); + } + return m_result == PAM_SUCCESS; + } + + bool PamHandle::acctMgmt(int flags) { + m_result = pam_acct_mgmt(m_handle, flags | m_silent); + if (m_result == PAM_NEW_AUTHTOK_REQD) { + // TODO see if this should really return the value or just true regardless of the outcome + return chAuthTok(PAM_CHANGE_EXPIRED_AUTHTOK); + } + else if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] acctMgmt:" << pam_strerror(m_handle, m_result); + return false; + } + return true; + } + + bool PamHandle::authenticate(int flags) { + qDebug() << "[PAM] Authenticating..."; + m_result = pam_authenticate(m_handle, flags | m_silent); + if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] authenticate:" << pam_strerror(m_handle, m_result); + } + qDebug() << "[PAM] returning."; + return m_result == PAM_SUCCESS; + } + + bool PamHandle::setCred(int flags) { + m_result = pam_setcred(m_handle, flags | m_silent); + if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] setCred:" << pam_strerror(m_handle, m_result); + } + return m_result == PAM_SUCCESS; + } + + bool PamHandle::openSession() { + m_result = pam_open_session(m_handle, m_silent); + if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] openSession:" << pam_strerror(m_handle, m_result); + } + m_open = m_result == PAM_SUCCESS; + return m_open; + } + + bool PamHandle::closeSession() { + m_result = pam_close_session(m_handle, m_silent); + if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] closeSession:" << pam_strerror(m_handle, m_result); + } + return m_result == PAM_SUCCESS; + } + + bool PamHandle::isOpen() const { + return m_open; + } + + bool PamHandle::setItem(int item_type, const void* item) { + m_result = pam_set_item(m_handle, item_type, item); + if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] setItem:" << pam_strerror(m_handle, m_result); + } + return m_result == PAM_SUCCESS; + } + + const void* PamHandle::getItem(int item_type) { + const void *item; + m_result = pam_get_item(m_handle, item_type, &item); + if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] getItem:" << pam_strerror(m_handle, m_result); + } + return item; + } + + int PamHandle::converse(int n, const struct pam_message **msg, struct pam_response **resp, void *data) { + qDebug() << "[PAM] Preparing to converse..."; + PamBackend *c = static_cast(data); + return c->converse(n, msg, resp); + } + + bool PamHandle::start(const QString &service, const QString &user) { + if (user.isEmpty()) + m_result = pam_start(qPrintable(service), NULL, &m_conv, &m_handle); + else + m_result = pam_start(qPrintable(service), qPrintable(user), &m_conv, &m_handle); + if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] start" << pam_strerror(m_handle, m_result); + return false; + } + else { + qDebug() << "[PAM] Starting..."; + } + return true; + } + + bool PamHandle::end(int flags) { + if (!m_handle) + return false; + m_result = pam_end(m_handle, m_result | flags); + if (m_result != PAM_SUCCESS) { + qWarning() << "[PAM] end:" << pam_strerror(m_handle, m_result); + return false; + } + else { + qDebug() << "[PAM] Ended."; + } + m_handle = NULL; + return true; + } + + QString PamHandle::errorString() { + return QString::fromLocal8Bit(pam_strerror(m_handle, m_result)); + } + + PamHandle::PamHandle(PamBackend *parent) { + // create context + m_conv = { &PamHandle::converse, parent }; + } + + PamHandle::~PamHandle() { + // stop service + end(); + } +} diff --git a/nde-screensaver-0.1.0/src/helper/backend/PamHandle.h b/nde-screensaver-0.1.0/src/helper/backend/PamHandle.h new file mode 100644 index 0000000..360dcec --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/backend/PamHandle.h @@ -0,0 +1,200 @@ +/* + * PAM API Qt wrapper + * Copyright (C) 2013 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef PAMHANDLE_H +#define PAMHANDLE_H + +#include +#include +#include + +namespace NSS { + class PamBackend; + /** + * Class wrapping the standard Linux-PAM library calls + * + * Almost everything is left the same except the following things: + * + * Mainly, state returns - if you call pam_start, pam_open_session and then + * pam_start again, the session will get closed and the conversation closed + * + * You don't need to pass PAM_SILENT to every call if you want PAM to be quiet. + * You can set the flag globally by using the \ref setSilence method. + * + * \ref acctMgmt doesn't require you to handle the PAM_NEW_AUTHTOK_REQD condition, + * it calls chAuthTok on its own. + * + * Error messages are automatically reported to qDebug + */ + class PamHandle { + public: + /** + * ctor + * \param parent parent backend + */ + explicit PamHandle(PamBackend *parent = 0); + + virtual ~PamHandle(); + + /** + * Returns whether the session is open. + * \sa openSession + */ + bool isOpen() const; + + /** + * pam_set_item - set and update PAM informations + * + * \param item_type PAM item type + * \param item item pointer + * + * \return true on success + */ + bool setItem(int item_type, const void *item); + + /** + * pam_get_item - getting PAM informations + * + * \param item_type + * + * \return item pointer or NULL on failure + */ + const void *getItem(int item_type); + + /** + * pam_open_session - start PAM session management + * + * \return true on success + */ + bool openSession(); + + /** + * pam_close_session - terminate PAM session management + * + * \return true on success + */ + bool closeSession(); + + /** + * pam_setcred - establish / delete user credentials + * + * \param flags PAM flag(s) + * + * \return true on success + */ + bool setCred(int flags = 0); + + /** + * pam_authenticate - account authentication + * + * \param flags PAM flag(s) + * + * \return true on success + */ + bool authenticate(int flags = 0); + + /** + * pam_acct_mgmt - PAM account validation management + * + * @note Automatically calls \ref chAuthTok if the password is expired + * + * \param flags PAM flag(s) + * + * \return true on success + */ + bool acctMgmt(int flags = 0); + + /** + * pam_chauthtok - updating authentication tokens + * + * \param flags PAM flag(s) + * + * \return true on success + */ + bool chAuthTok(int flags = 0); + + /** + * pam_getenv - get PAM environment + * + * \return Complete process environment + */ + QProcessEnvironment getEnv(); + + /** + * pam_putenv - set or change PAM environment + * + * \param env environment to be merged into the PAM one + * + * \return true on success + */ + bool putEnv(const QProcessEnvironment& env); + + /** + * pam_end - termination of PAM transaction + * + * \param flags to be OR'd with the status (PAM_DATA_SILENT) + * \return true on success + */ + bool end(int flags = 0); + + /** + * pam_start - initialization of PAM transaction + * + * \param service PAM service name, e.g. "/etc/pam.d/nde-screensaver" + * \param pam_conversation pointer to the PAM conversation structure to be used + * \param user username + * + * \return true on success + */ + bool start(const QString &service, const QString &user = QString()); + + /** + * Set PAM_SILENT upon the contained calls + * \param silent true if silent + */ + void setSilence(bool silent); + + /** + * Generates an error message according to the internal state + * + * \return error string + */ + QString errorString(); + + private: + /** + * Conversation function for the pam_conv structure + * + * Calls ((PamHandle*)pam_conv.appdata_ptr)->doConverse() with its parameters + * + * Not to be called directly, therefore private + */ + static int converse(int n, const struct pam_message **msg, struct pam_response **resp, void *data); + + int m_silent { 0 }; ///< flag mask for silence of the contained calls + + struct pam_conv m_conv; ///< the current conversation + pam_handle_t *m_handle { nullptr }; ///< the actual PAM handle + int m_result { 0 }; ///< PAM result + bool m_open { false }; ///< whether the session is open + }; +} + +#endif // PAMHANDLE_H diff --git a/nde-screensaver-0.1.0/src/helper/backend/PasswdBackend.cpp b/nde-screensaver-0.1.0/src/helper/backend/PasswdBackend.cpp new file mode 100644 index 0000000..8a0b8c9 --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/backend/PasswdBackend.cpp @@ -0,0 +1,109 @@ +/* + * /etc/passwd authentication backend + * Copyright (C) 2014 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "PasswdBackend.h" + +#include "AuthMessages.h" +#include "HelperApp.h" + +#include + +#include +#include +#include + +#ifdef HAVE_GETSPNAM +#include +#endif + +namespace SDDM { + PasswdBackend::PasswdBackend(HelperApp *parent) + : Backend(parent) { } + + bool PasswdBackend::authenticate() { + if (m_autologin) + return true; + + if (m_user == QLatin1String("sddm")) { + if (m_greeter) + return true; + else + return false; + } + + Request r; + QString password; + + if (m_user.isEmpty()) + r.prompts << Prompt(AuthPrompt::LOGIN_USER, QStringLiteral("Login"), false); + r.prompts << Prompt(AuthPrompt::LOGIN_PASSWORD, QStringLiteral("Password"), true); + + Request response = m_app->request(r); + Q_FOREACH(const Prompt &p, response.prompts) { + switch (p.type) { + case AuthPrompt::LOGIN_USER: + m_user = QString::fromUtf8(p.response); + break; + case AuthPrompt::LOGIN_PASSWORD: + password = QString::fromUtf8(p.response); + break; + default: + break; + } + } + + struct passwd *pw = getpwnam(qPrintable(m_user)); + if (!pw) { + m_app->error(QStringLiteral("Wrong user/password combination"), Auth::ERROR_AUTHENTICATION); + return false; + } + const char *system_passwd = pw->pw_passwd; + +#ifdef HAVE_GETSPNAM + struct spwd *spw = getspnam(pw->pw_name); + if (!spw) { + qWarning() << "[Passwd] Could get passwd but not shadow"; + return false; + } + + if(!spw->sp_pwdp || !spw->sp_pwdp[0]) + return true; + + system_passwd = spw->sp_pwdp; +#endif + + const char * const crypted = crypt(qPrintable(password), system_passwd); + if (0 == strcmp(crypted, system_passwd)) { + return true; + } + + m_app->error(QStringLiteral("Wrong user/password combination"), Auth::ERROR_AUTHENTICATION); + return false; + } + + bool PasswdBackend::start(const QString& user) { + m_user = user; + return true; + } + + QString PasswdBackend::userName() { + return m_user; + } +} diff --git a/nde-screensaver-0.1.0/src/helper/backend/PasswdBackend.h b/nde-screensaver-0.1.0/src/helper/backend/PasswdBackend.h new file mode 100644 index 0000000..74d1ac6 --- /dev/null +++ b/nde-screensaver-0.1.0/src/helper/backend/PasswdBackend.h @@ -0,0 +1,43 @@ +/* + * /etc/passwd authentication backend + * Copyright (C) 2014 Martin Bříza + * + * 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#if !defined(PASSWDBACKEND_H) && !defined(USE_PAM) +#define PASSWDBACKEND_H + +#include "../Backend.h" + +namespace NSS { + class PasswdBackend : public Backend { + Q_OBJECT + public: + PasswdBackend(HelperApp *parent); + + public slots: + virtual bool start(const QString &user = QString()); + virtual bool authenticate(); + + virtual QString userName(); + + private: + QString m_user { }; + }; +} + +#endif // PASSWDBACKEND_H diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/CMakeLists.txt b/nde-screensaver-0.1.0/src/nde-screensaver/CMakeLists.txt new file mode 100644 index 0000000..670830a --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/CMakeLists.txt @@ -0,0 +1,36 @@ +include_directories( + "${CMAKE_SOURCE_DIR}/src/common" + "${CMAKE_SOURCE_DIR}/src/auth" + "${CMAKE_BINARY_DIR}/src/common" + "${LIBXCB_INCLUDE_DIR}" +) +set(SCREENSAVER_SOURCES + ${CMAKE_SOURCE_DIR}/src/common/SocketWriter.cpp + ${CMAKE_SOURCE_DIR}/src/auth/Auth.cpp + ${CMAKE_SOURCE_DIR}/src/auth/AuthPrompt.cpp + ${CMAKE_SOURCE_DIR}/src/auth/AuthRequest.cpp + ${CMAKE_SOURCE_DIR}/src/common/SafeDataStream.cpp + ScreenSaverApp.cpp + SocketServer.cpp + PowerManager.cpp + idlewatcher.cpp + lockscreenshortcut.cpp + lockscreenmanager.cpp + ) +qt5_add_dbus_interface(SCREENSAVER_SOURCES ${CMAKE_SOURCE_DIR}/src/common/com.vm.daemon.xml vmdaemon_interface) +add_executable(nde-screensaver ${SCREENSAVER_SOURCES}) +target_link_libraries(nde-screensaver + Qt5::DBus + Qt5::Gui + Qt5::Network + Qt5::Qml + nde + KF5::IdleTime + nde-globalkeys + ${LIBXCB_LIBRARIES} + ${LIBXAU_LIBRARIES} +) +if(JOURNALD_FOUND) + target_link_libraries(nde-screensaver ${JOURNALD_LIBRARIES}) +endif() +install(TARGETS nde-screensaver DESTINATION "${CMAKE_INSTALL_BINDIR}") diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/PowerManager.cpp b/nde-screensaver-0.1.0/src/nde-screensaver/PowerManager.cpp new file mode 100644 index 0000000..e968f69 --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/PowerManager.cpp @@ -0,0 +1,266 @@ +/*************************************************************************** +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include "PowerManager.h" +#include "Constants.h" +#include "Messages.h" + +#include +#include +#include +#include + +namespace NSS { + /************************************************/ + /* POWER MANAGER BACKEND */ + /************************************************/ + class PowerManagerBackend { + public: + PowerManagerBackend() { + } + + virtual ~PowerManagerBackend() { + } + + virtual Capabilities capabilities() const = 0; + + virtual void powerOff() const = 0; + virtual void reboot() const = 0; + virtual void suspend() const = 0; + virtual void hibernate() const = 0; + virtual void hybridSleep() const = 0; + }; + + /**********************************************/ + /* UPOWER BACKEND */ + /**********************************************/ + +const QString UPOWER_PATH = QStringLiteral("/org/freedesktop/UPower"); +const QString UPOWER_SERVICE = QStringLiteral("org.freedesktop.UPower"); +const QString UPOWER_OBJECT = QStringLiteral("org.freedesktop.UPower"); + + class UPowerBackend : public PowerManagerBackend { + public: + UPowerBackend(const QString & service, const QString & path, const QString & interface) { + m_interface = new QDBusInterface(service, path, interface, QDBusConnection::systemBus()); + } + + ~UPowerBackend() { + delete m_interface; + } + + Capabilities capabilities() const { + Capabilities caps = Capability::PowerOff | Capability::Reboot; + + QDBusReply reply; + + // suspend + reply = m_interface->call(QStringLiteral("SuspendAllowed")); + if (reply.isValid() && reply.value()) + caps |= Capability::Suspend; + + // hibernate + reply = m_interface->call(QStringLiteral("HibernateAllowed")); + if (reply.isValid() && reply.value()) + caps |= Capability::Hibernate; + + // return capabilities + return caps; + } + + void powerOff() const { + QProcess::execute(HALT_COMMAND); + } + + void reboot() const { + QProcess::execute(REBOOT_COMMAND); + } + + void suspend() const { + m_interface->call(QStringLiteral("Suspend")); + } + + void hibernate() const { + m_interface->call(QStringLiteral("Hibernate")); + } + + void hybridSleep() const { + } + + private: + QDBusInterface *m_interface { nullptr }; + }; + + /**********************************************/ + /* LOGIN1 && ConsoleKit2 BACKEND */ + /**********************************************/ + +const QString LOGIN1_SERVICE = QStringLiteral("org.freedesktop.login1"); +const QString LOGIN1_PATH = QStringLiteral("/org/freedesktop/login1"); +const QString LOGIN1_OBJECT = QStringLiteral("org.freedesktop.login1.Manager"); + +const QString CK2_SERVICE = QStringLiteral("org.freedesktop.ConsoleKit"); +const QString CK2_PATH = QStringLiteral("/org/freedesktop/ConsoleKit/Manager"); +const QString CK2_OBJECT = QStringLiteral("org.freedesktop.ConsoleKit.Manager"); + + class SeatManagerBackend : public PowerManagerBackend { + public: + SeatManagerBackend(const QString & service, const QString & path, const QString & interface) { + m_interface = new QDBusInterface(service, path, interface, QDBusConnection::systemBus()); + } + + ~SeatManagerBackend() { + delete m_interface; + } + + Capabilities capabilities() const { + Capabilities caps = Capability::None; + + QDBusReply reply; + + // power off + reply = m_interface->call(QStringLiteral("CanPowerOff")); + if (reply.isValid() && (reply.value() == QLatin1String("yes"))) + caps |= Capability::PowerOff; + + // reboot + reply = m_interface->call(QStringLiteral("CanReboot")); + if (reply.isValid() && (reply.value() == QLatin1String("yes"))) + caps |= Capability::Reboot; + + // suspend + reply = m_interface->call(QStringLiteral("CanSuspend")); + if (reply.isValid() && (reply.value() == QLatin1String("yes"))) + caps |= Capability::Suspend; + + // hibernate + reply = m_interface->call(QStringLiteral("CanHibernate")); + if (reply.isValid() && (reply.value() == QLatin1String("yes"))) + caps |= Capability::Hibernate; + + // hybrid sleep + reply = m_interface->call(QStringLiteral("CanHybridSleep")); + if (reply.isValid() && (reply.value() == QLatin1String("yes"))) + caps |= Capability::HybridSleep; + + // return capabilities + return caps; + } + + void powerOff() const { + m_interface->call(QStringLiteral("PowerOff"), true); + } + + void reboot() const { + m_interface->call(QStringLiteral("Reboot"), true); + } + + void suspend() const { + m_interface->call(QStringLiteral("Suspend"), true); + } + + void hibernate() const { + m_interface->call(QStringLiteral("Hibernate"), true); + } + + void hybridSleep() const { + m_interface->call(QStringLiteral("HybridSleep"), true); + } + + private: + QDBusInterface *m_interface { nullptr }; + }; + + /**********************************************/ + /* POWER MANAGER */ + /**********************************************/ + PowerManager::PowerManager(QObject *parent) : QObject(parent) { + QDBusConnectionInterface *interface = QDBusConnection::systemBus().interface(); + + // check if login1 interface exists + if (interface->isServiceRegistered(LOGIN1_SERVICE)) + m_backends << new SeatManagerBackend(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_OBJECT); + + // check if ConsoleKit2 interface exists + if (interface->isServiceRegistered(CK2_SERVICE)) + m_backends << new SeatManagerBackend(CK2_SERVICE, CK2_PATH, CK2_OBJECT); + + // check if upower interface exists + if (interface->isServiceRegistered(UPOWER_SERVICE)) + m_backends << new UPowerBackend(UPOWER_SERVICE, UPOWER_PATH, UPOWER_OBJECT); + } + + PowerManager::~PowerManager() { + while (!m_backends.empty()) + delete m_backends.takeFirst(); + } + + Capabilities PowerManager::capabilities() const { + Capabilities caps = Capability::None; + + for (PowerManagerBackend *backend: m_backends) + caps |= backend->capabilities(); + return caps; + } + + void PowerManager::powerOff() const { + for (PowerManagerBackend *backend: m_backends) { + if (backend->capabilities() & Capability::PowerOff) { + backend->powerOff(); + break; + } + } + } + + void PowerManager::reboot() const { + for (PowerManagerBackend *backend: m_backends) { + if (backend->capabilities() & Capability::Reboot) { + backend->reboot(); + break; + } + } + } + + void PowerManager::suspend() const { + for (PowerManagerBackend *backend: m_backends) { + if (backend->capabilities() & Capability::Suspend) { + backend->suspend(); + break; + } + } + } + + void PowerManager::hibernate() const { + for (PowerManagerBackend *backend: m_backends) { + if (backend->capabilities() & Capability::Hibernate) { + backend->hibernate(); + break; + } + } + } + + void PowerManager::hybridSleep() const { + for (PowerManagerBackend *backend: m_backends) { + if (backend->capabilities() & Capability::HybridSleep) { + backend->hybridSleep(); + break; + } + } + } +} diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/PowerManager.h b/nde-screensaver-0.1.0/src/nde-screensaver/PowerManager.h new file mode 100644 index 0000000..543a8fa --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/PowerManager.h @@ -0,0 +1,52 @@ +/*************************************************************************** +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef NSS_POWERMANAGER_H +#define NSS_POWERMANAGER_H + +#include +#include + +#include "Messages.h" + +namespace NSS { + class PowerManagerBackend; + + class PowerManager : public QObject { + Q_OBJECT + Q_DISABLE_COPY(PowerManager) + public: + PowerManager(QObject *parent = 0); + ~PowerManager(); + + public slots: + Capabilities capabilities() const; + + void powerOff() const; + void reboot() const; + void suspend() const; + void hibernate() const; + void hybridSleep() const; + + private: + QVector m_backends; + }; +} + +#endif // NSS_POWERMANAGER_H diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/ScreenSaverApp.cpp b/nde-screensaver-0.1.0/src/nde-screensaver/ScreenSaverApp.cpp new file mode 100644 index 0000000..18e5aaf --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/ScreenSaverApp.cpp @@ -0,0 +1,171 @@ +#include "ScreenSaverApp.h" +#include "SocketServer.h" + +#include "Constants.h" +#include "PowerManager.h" +#include "Utils.h" +#include "lockscreenshortcut.h" +#include "lockscreenmanager.h" +#include +#include +#include "idlewatcher.h" +#include +#include "MessageHandler.h" + +namespace NSS { + +ScreenSaverApp *ScreenSaverApp::self = nullptr; +ScreenSaverApp::ScreenSaverApp(int &argc, char **argv) : + QGuiApplication(argc, argv), + m_auth(new Auth (this)), + m_socketServer(new SocketServer (this)), + mLockGreeter(new QProcess (this)), + mIdleTime(3 * 60), + mLockScreenManager(new LockScreenManager (this)) +{ + self = this; + qInstallMessageHandler(NSS::DaemonMessageHandler); + + m_auth->setVerbose(true); + connect(m_auth, SIGNAL(requestChanged()), this, SLOT(slotRequestChanged())); + connect(m_auth, SIGNAL(authentication(QString,bool)), this, SLOT(slotAuthenticationFinished(QString,bool))); + connect(m_auth, SIGNAL(finished(Auth::HelperExitStatus)), this, SLOT(slotHelperFinished(Auth::HelperExitStatus))); + connect(m_auth, SIGNAL(info(QString,Auth::Info)), this, SLOT(slotAuthInfo(QString,Auth::Info))); + connect(m_auth, SIGNAL(error(QString,Auth::Error)), this, SLOT(slotAuthError(QString,Auth::Error))); + connect(this, SIGNAL(loginFailed(QLocalSocket*)), m_socketServer, SLOT(loginFailed(QLocalSocket*))); + connect(this, SIGNAL(loginSucceeded(QLocalSocket*)), m_socketServer, SLOT(loginSucceeded(QLocalSocket*))); + connect(this, SIGNAL(loggingIn(QLocalSocket*)), m_socketServer, SLOT(loggingIn(QLocalSocket*))); + connect(m_socketServer, &SocketServer::login, this, &ScreenSaverApp::login); + m_socketServer->start(QString(qgetenv("DISPLAY"))); + mShortcut = new LockScreenShortcut; + connect(mShortcut, &LockScreenShortcut::globalKeyActivated, this, &ScreenSaverApp::lockSession); + mIdleWatcher = new IdleWatcher(mIdleTime, this); + mPowerManager = new PowerManager (this); + connect(mIdleWatcher, &IdleWatcher::requestLock, this, &ScreenSaverApp::lockSession); + connect(mLockGreeter, QOverload::of(&QProcess::finished), + this, [=](int exitCode, QProcess::ExitStatus exitStatus){ + Q_UNUSED(exitCode) + if(exitStatus == QProcess::CrashExit) + { + mIdleWatcher->reset(mIdleTime); + } + }); + if (mLockScreenManager->startup(true, 0)) + qDebug() << "LockScreenManager started successfully"; + else + qWarning() << "LockScreenManager couldn't start"; + unLock(); +} +ScreenSaverApp::~ScreenSaverApp() +{ + m_socketServer->stop(); + mShortcut->deleteLater(); +} + +void ScreenSaverApp::lockSession() +{ + mLockGreeter->start(QString("%1/nde-screensaver-greeter").arg(QStringLiteral(LIBEXEC_INSTALL_DIR)), + QStringList {} << "--socket" << m_socketServer->socketAddress()); + mLockScreenManager->saveLockStatus(LockScreenManager::LOCKED); + mIdleWatcher->removeIdleTimeout(); +} +void ScreenSaverApp::unLock() +{ + daemonInterface = new com::vm::daemon("com.vm.daemon", + "/daemon",QDBusConnection::systemBus(), this); + //token解锁 + connect(daemonInterface, &com::vm::daemon::tokenSuccess, this, [=]{ + qDebug() << "ScreenSaverApp: unlock Screen"; + mLockGreeter->kill(); + mLockScreenManager->saveLockStatus(LockScreenManager::UNLOCKED); + mIdleWatcher->reset(mIdleTime); + }); + //密码解锁 + connect(daemonInterface, &com::vm::daemon::autoLogin, this, [=]{ + qWarning() << "ScreenSaverApp: auto login"; + QString userName = daemonInterface->userName(); + QString password = daemonInterface->password(); + m_socket = m_socketServer->currentSocket(); + if(m_socket && locked()) + { + login(m_socket, userName, password); + } + }); + +} +void ScreenSaverApp::login(QLocalSocket *socket, + const QString &user, const QString &password) { + m_socket = socket; + emit loggingIn(m_socket); + m_passPhrase = password; + + m_auth->setUser(user); + m_auth->start(); +} + +void ScreenSaverApp::slotAuthenticationFinished(const QString &user, bool success) { + Q_UNUSED(user) + if (success) { + qDebug() << "Authenticated successfully"; + if (m_socket) + { + emit loginSucceeded(m_socket); + mLockScreenManager->saveLockStatus(LockScreenManager::UNLOCKED); + mIdleWatcher->reset(mIdleTime); + } + } else if (m_socket) { + qDebug() << "Authentication failure"; + emit loginFailed(m_socket); + } + m_socket = nullptr; +} + +void ScreenSaverApp::slotAuthInfo(const QString &message, Auth::Info info) { + // TODO: presentable to the user, eventually + Q_UNUSED(info) + qWarning() << "Authentication information:" << message; +} + +void ScreenSaverApp::slotAuthError(const QString &message, Auth::Error error) { + // TODO: handle more errors + qWarning() << "Authentication error:" << message; + emit loginFailed(m_socket); +// if (!m_socket) +// return; + +// if (error == Auth::ERROR_AUTHENTICATION) +// emit loginFailed(m_socket); +} + +void ScreenSaverApp::slotHelperFinished(Auth::HelperExitStatus status) { + Q_UNUSED(status) +} + +void ScreenSaverApp::slotRequestChanged() { + if (m_auth->request()->prompts().length() == 1) { + m_auth->request()->prompts()[0]->setResponse(qPrintable(m_passPhrase)); + m_auth->request()->done(); + } else if (m_auth->request()->prompts().length() == 2) { + m_auth->request()->prompts()[0]->setResponse(qPrintable(m_auth->user())); + m_auth->request()->prompts()[1]->setResponse(qPrintable(m_passPhrase)); + m_auth->request()->done(); + } +} +PowerManager *ScreenSaverApp::powerManager() const { + return mPowerManager; +} +bool ScreenSaverApp::locked() const +{ + qWarning() << mLockGreeter->state(); + if(mLockGreeter->state() == QProcess::NotRunning) + return false; + if(mLockGreeter->state() == QProcess::Running || + mLockGreeter->state() == QProcess::Starting) + return true; + return false; +} +} +int main(int argc, char **argv) { + NSS::ScreenSaverApp app(argc, argv); + return app.exec(); +} diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/ScreenSaverApp.h b/nde-screensaver-0.1.0/src/nde-screensaver/ScreenSaverApp.h new file mode 100644 index 0000000..882aa4d --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/ScreenSaverApp.h @@ -0,0 +1,58 @@ +#ifndef SCREENSAVERAPP_H +#define SCREENSAVERAPP_H + +#include +#include "vmdaemon_interface.h" +#include "Auth.h" +#define SaverApp ScreenSaverApp::instance() +class QLocalSocket; +class IdleWatcher; +class QProcess; + +namespace NSS { +class PowerManager; +class SocketServer; +class LockScreenShortcut; +class LockScreenManager; +class ScreenSaverApp : public QGuiApplication +{ + Q_OBJECT +public: + explicit ScreenSaverApp(int &argc, char **argv); + ~ScreenSaverApp(); + static ScreenSaverApp *instance() { return self; } + + PowerManager *powerManager() const; + bool locked() const; +signals: + void stopped(); + void loggingIn(QLocalSocket *socket); + void loginFailed(QLocalSocket *socket); + void loginSucceeded(QLocalSocket *socket); + +public slots: + void slotRequestChanged(); + void slotAuthenticationFinished(const QString &user, bool success); + void slotHelperFinished(Auth::HelperExitStatus status); + void slotAuthInfo(const QString &message, Auth::Info info); + void slotAuthError(const QString &message, Auth::Error error); + void login(QLocalSocket *socket, + const QString &user, const QString &password); + void lockSession(); +private: + void unLock(); + static ScreenSaverApp *self; + Auth *m_auth { nullptr }; + SocketServer *m_socketServer { nullptr }; + PowerManager *mPowerManager { nullptr }; + QLocalSocket *m_socket { nullptr }; + QString m_passPhrase; + IdleWatcher *mIdleWatcher; + QProcess *mLockGreeter; + int mIdleTime; + LockScreenShortcut *mShortcut; + com::vm::daemon *daemonInterface; + LockScreenManager *mLockScreenManager; +}; +} +#endif // SCREENSAVERAPP_H diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/SocketServer.cpp b/nde-screensaver-0.1.0/src/nde-screensaver/SocketServer.cpp new file mode 100644 index 0000000..88f33ab --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/SocketServer.cpp @@ -0,0 +1,181 @@ +/*************************************************************************** +* Copyright (c) 2015 Pier Luigi Fiorini +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#include "SocketServer.h" +#include "ScreenSaverApp.h" +#include "Messages.h" +#include "PowerManager.h" +#include "SocketWriter.h" +#include "Utils.h" + +#include + +namespace NSS { + SocketServer::SocketServer(QObject *parent) : QObject(parent) { + } + + QString SocketServer::socketAddress() const { + if (m_server) + return m_server->fullServerName(); + return QString(); + } + QLocalSocket * SocketServer::currentSocket() const + { + if(m_socket) + return m_socket; + return nullptr; + } + bool SocketServer::start(const QString &displayName) { + // check if the server has been created already + if (m_server) + return false; + + QString socketName = QStringLiteral("nss-%1-%2").arg(displayName).arg(generateName(6)); + + // log message + qDebug() << "Socket server starting..." << socketName; + + // create server + m_server = new QLocalServer(this); + + // start listening + if (!m_server->listen(socketName)) { + // log message + qCritical() << "Failed to start socket server."; + + // return fail + return false; + } + + + // log message + qDebug() << "Socket server started."; + + // connect signals + connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection())); + + // return success + return true; + } + + void SocketServer::stop() { + // check flag + if (!m_server) + return; + + // log message + qDebug() << "Socket server stopping..."; + + // delete server + m_server->deleteLater(); + m_server = nullptr; + + // log message + qDebug() << "Socket server stopped."; + } + + void SocketServer::newConnection() { + // get pending connection + m_socket = m_server->nextPendingConnection(); + qDebug() << "new connection coming"; + // connect signals + connect(m_socket, SIGNAL(readyRead()), this, SLOT(readyRead())); + connect(m_socket, SIGNAL(disconnected()), m_socket, SLOT(deleteLater())); + } + + void SocketServer::readyRead() { + QLocalSocket *socket = qobject_cast(sender()); + + if (!socket) + return; + QDataStream input(socket); + quint32 message; + QString user, password; + + input >> message; + input >> user >> password; + + switch (GreeterMessages(message)) { + case GreeterMessages::Connect: { + qDebug() << "Message received from greeter: Connect"; + SocketWriter(socket) << quint32(DaemonMessages::Capabilities) << quint32(SaverApp->powerManager()->capabilities()); + emit connected(); + } + break; + case GreeterMessages::Login: { + qDebug() << "Message received from greeter: Login"; + if(!user.isEmpty() && !password.isEmpty()) + emit login(socket, user, password); + } + break; + case GreeterMessages::PowerOff: { + qDebug() << "Message received from greeter: PowerOff"; + SaverApp->powerManager()->powerOff(); + } + break; + case GreeterMessages::Reboot: { + // log message + qDebug() << "Message received from greeter: Reboot"; + + // reboot + SaverApp->powerManager()->reboot(); + } + break; + case GreeterMessages::Suspend: { + // log message + qDebug() << "Message received from greeter: Suspend"; + + // suspend + SaverApp->powerManager()->suspend(); + } + break; + case GreeterMessages::Hibernate: { + // log message + qDebug() << "Message received from greeter: Hibernate"; + + // hibernate + SaverApp->powerManager()->hibernate(); + } + break; + case GreeterMessages::HybridSleep: { + // log message + qDebug() << "Message received from greeter: HybridSleep"; + + // hybrid sleep + SaverApp->powerManager()->hybridSleep(); + } + break; + default: { + qWarning() << "Unknown message" << message; + } + } + } + + void SocketServer::loginFailed(QLocalSocket *socket) { + SocketWriter(socket) << quint32(DaemonMessages::LoginFailed); + } + + void SocketServer::loginSucceeded(QLocalSocket *socket) { + SocketWriter(socket) << quint32(DaemonMessages::LoginSucceeded); + } + void SocketServer::loggingIn(QLocalSocket *socket) { + SocketWriter(socket) << quint32(DaemonMessages::LoggingIn); + } +} diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/SocketServer.h b/nde-screensaver-0.1.0/src/nde-screensaver/SocketServer.h new file mode 100644 index 0000000..4880e37 --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/SocketServer.h @@ -0,0 +1,60 @@ +/*************************************************************************** +* Copyright (c) 2015 Pier Luigi Fiorini +* Copyright (c) 2013 Abdurrahman AVCI +* +* 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, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +***************************************************************************/ + +#ifndef NSS_SOCKETSERVER_H +#define NSS_SOCKETSERVER_H + +#include +#include + +class QLocalServer; +class QLocalSocket; + +namespace NSS { + class SocketServer : public QObject { + Q_OBJECT + Q_DISABLE_COPY(SocketServer) + public: + explicit SocketServer(QObject *parent = 0); + + bool start(const QString &displayName); + void stop(); + + QString socketAddress() const; + QLocalSocket *currentSocket() const; + private slots: + void newConnection(); + void readyRead(); + + void loginFailed(QLocalSocket *socket); + void loginSucceeded(QLocalSocket *socket); + void loggingIn(QLocalSocket *socket); + signals: + void login(QLocalSocket *socket, + const QString &user, const QString &password); + void connected(); + + private: + QLocalServer *m_server { nullptr }; + QLocalSocket *m_socket { nullptr }; + }; +} + +#endif // NSS_SOCKETSERVER_H diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/idlewatcher.cpp b/nde-screensaver-0.1.0/src/nde-screensaver/idlewatcher.cpp new file mode 100644 index 0000000..72642ae --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/idlewatcher.cpp @@ -0,0 +1,53 @@ +#include "idlewatcher.h" +#include +#include +#include + +IdleWatcher::IdleWatcher(int secs, QObject *parent): + QObject(parent), + mSecs(secs) +{ + connect(KIdleTime::instance(), + &KIdleTime::resumingFromIdle, + this, + &IdleWatcher::onResumingFromIdle); + connect(KIdleTime::instance(), + static_cast(&KIdleTime::timeoutReached), + this, + &IdleWatcher::onTimeoutReached); + setup(); +} + +IdleWatcher::~IdleWatcher() +{ + KIdleTime::instance()->removeAllIdleTimeouts(); +} + +void IdleWatcher::reset(int secs) +{ + KIdleTime::instance()->removeAllIdleTimeouts(); + mSecs = secs; + setup(); +} + +void IdleWatcher::onResumingFromIdle() +{ + qDebug() << "Somethings happened"; +} + +void IdleWatcher::onTimeoutReached(int identifier) +{ + mIdentifier = identifier; + qDebug() << "Timeout Reached, id=" << identifier; + KIdleTime::instance()->removeIdleTimeout(mIdentifier); + emit requestLock(); +} +void IdleWatcher::removeIdleTimeout() +{ + if(mIdentifier > 0) + KIdleTime::instance()->removeIdleTimeout(mIdentifier); +} +void IdleWatcher::setup() +{ + KIdleTime::instance()->addIdleTimeout(1000 * mSecs); +} diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/idlewatcher.h b/nde-screensaver-0.1.0/src/nde-screensaver/idlewatcher.h new file mode 100644 index 0000000..9bf59e7 --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/idlewatcher.h @@ -0,0 +1,28 @@ +#ifndef IDLEWATCHER_H +#define IDLEWATCHER_H + +#include + +class IdleWatcher : public QObject +{ + Q_OBJECT +public: + explicit IdleWatcher(int secs, QObject *parent = nullptr); + virtual ~IdleWatcher(); +public Q_SLOTS: + void reset(int secs); + void removeIdleTimeout(); +private Q_SLOTS: + void onResumingFromIdle(); + void onTimeoutReached(int identifier); + void setup(); + +Q_SIGNALS: + void requestLock(); + +private: + int mSecs; + int mIdentifier { 0 }; +}; + +#endif // IDLEWATCHER_H diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenmanager.cpp b/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenmanager.cpp new file mode 100644 index 0000000..1e384f8 --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenmanager.cpp @@ -0,0 +1,245 @@ +#include "lockscreenmanager.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "ScreenSaverApp.h" + +namespace NSS { +LockScreenManager::LockScreenManager(QObject *parent) : + QObject(parent) + , mProvider{nullptr} + , mLockedBeforeSleep{false} +{ +} + +LockScreenManager::~LockScreenManager() +{ + delete mProvider; +} + +bool LockScreenManager::startup(bool lockBeforeSleep, int powerAfterLockDelay) +{ + Q_UNUSED(powerAfterLockDelay) + mProvider = new LogindProvider; + if (!mProvider->isValid()) + { + mProvider->deleteLater(); + mProvider = new ConsoleKit2Provider; + if (!mProvider->isValid()) + { + mProvider->deleteLater(); + mProvider = nullptr; + } + } + saveLockStatus(UNLOCKED); + if (!mProvider) + { + qDebug() << "LockScreenManager: no valid provider"; + return false; + } + qDebug() << "LockScreenManager:" + << mProvider->metaObject()->className() + << "will be used"; + + connect(mProvider, &LockScreenProvider::lockRequested, [] { + qDebug() << "LockScreenManager: lock requested"; + SaverApp->lockSession(); + }); + + if (lockBeforeSleep) + { + connect(mProvider, + &LockScreenProvider::aboutToSleep, + [this] (bool beforeSleep) + { + if (beforeSleep) + { + qDebug() << "LockScreenManager: system is about to sleep"; + + mLockedBeforeSleep = true; + SaverApp->lockSession(); + qDebug() << "LockScreenManager: after lockScreen"; + } else + { + inhibit(); + } + }); + + inhibit(); + } + + return true; +} +void LockScreenManager::saveLockStatus(LOCK_STATUS status) +{ + QString lockStatus = "/etc/lock-status.conf"; + QFile file(lockStatus); + if(file.open(QIODevice::WriteOnly | QIODevice::Text)) + { + QTextStream out(&file); + out << "status=" << status; + } + file.close(); +} +void LockScreenManager::inhibit() +{ + if (!mProvider->inhibit()) + qDebug() << "LockScreenManager: could not inhibit session provider"; +} + +/* + * Logind Provider + */ + +LogindProvider::LogindProvider() : + mInterface(QStringLiteral("org.freedesktop.login1"), + QStringLiteral("/org/freedesktop/login1"), + QStringLiteral("org.freedesktop.login1.Manager"), + QDBusConnection::systemBus()) +{ + if (mInterface.isValid()) + { + connect(&mInterface, SIGNAL(PrepareForSleep(bool)), + this, SIGNAL(aboutToSleep(bool))); + + QString sessionId = QDBusInterface( + QStringLiteral("org.freedesktop.login1"), + QStringLiteral("/org/freedesktop/login1/session/self"), + QStringLiteral("org.freedesktop.login1.Session"), + QDBusConnection::systemBus()) + .property("Id").toString(); + + // listen to Lock signal as well + mInterface.connection().connect( + QStringLiteral("org.freedesktop.login1"), + QStringLiteral("/org/freedesktop/login1/session/") + sessionId, + QStringLiteral("org.freedesktop.login1.Session"), + QStringLiteral("Lock"), + this, + SIGNAL(lockRequested())); + } +} + +LogindProvider::~LogindProvider() +{ + release(); +} + +bool LogindProvider::isValid() +{ + return mInterface.isValid(); +} + +bool LogindProvider::inhibit() +{ + if (mFileDescriptor) + return false; + + QDBusReply reply = mInterface.call( + QStringLiteral("Inhibit"), + QStringLiteral("sleep"), + QStringLiteral("Nde Session"), + QStringLiteral("Start screen locker before sleep."), + QStringLiteral("delay")); + + if (!reply.isValid()) + { + qDebug() << "LockScreenManager: " << reply.error(); + return false; + } + + mFileDescriptor.reset(new QDBusUnixFileDescriptor{reply.value()}); + return true; +} + +void LogindProvider::release() +{ + mFileDescriptor.reset(nullptr); +} + +/* + * ConsoleKit2 provider + */ + +ConsoleKit2Provider::ConsoleKit2Provider() : + mInterface(QStringLiteral("org.freedesktop.ConsoleKit"), + QStringLiteral("/org/freedesktop/ConsoleKit/Manager"), + QStringLiteral("org.freedesktop.ConsoleKit.Manager"), + QDBusConnection::systemBus()), + mMethodInhibitPresent(false) + +{ + // validate interface, look for melhod Inhibit + if (mInterface.isValid()) + { + // this is needed to differentiate ConsoleKit2 from ConsoleKit + QDBusReply reply = QDBusInterface( + QStringLiteral("org.freedesktop.ConsoleKit"), + QStringLiteral("/org/freedesktop/ConsoleKit/Manager"), + QStringLiteral("org.freedesktop.DBus.Introspectable"), + QDBusConnection::systemBus()) + .call(QStringLiteral("Introspect")); + mMethodInhibitPresent = reply.value().contains(QL1S("Inhibit")); + + if (mMethodInhibitPresent) + { + connect(&mInterface, SIGNAL(PrepareForSleep(bool)), + this, SIGNAL(aboutToSleep(bool))); + + QDBusReply sessionObjectPath = mInterface + .call(QSL("GetCurrentSession")); + + // listen to Lock signal as well + mInterface.connection().connect( + QStringLiteral("org.freedesktop.ConsoleKit"), + sessionObjectPath.value().path(), + QStringLiteral("org.freedesktop.ConsoleKit.Session"), + QStringLiteral("Lock"), + this, + SIGNAL(lockRequested())); + } + } +} + +ConsoleKit2Provider::~ConsoleKit2Provider() +{ + release(); +} + +bool ConsoleKit2Provider::isValid() +{ + return mInterface.isValid() && mMethodInhibitPresent; +} + +bool ConsoleKit2Provider::inhibit() +{ + if (mFileDescriptor) + return false; + + QDBusReply reply = mInterface.call( + QStringLiteral("Inhibit"), + QStringLiteral("sleep"), + QStringLiteral("Nde Power Management"), + QStringLiteral("Start screen locker before sleep."), + QStringLiteral("delay")); + + if (!reply.isValid()) + { + qDebug() << "LockScreenWatcher: " << reply.error(); + return false; + } + + mFileDescriptor.reset(new QDBusUnixFileDescriptor{reply.value()}); + return true; +} + +void ConsoleKit2Provider::release() +{ + mFileDescriptor.reset(nullptr); +} +} diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenmanager.h b/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenmanager.h new file mode 100644 index 0000000..2f131f4 --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenmanager.h @@ -0,0 +1,83 @@ +#ifndef LOCKSCREENMANAGER_H +#define LOCKSCREENMANAGER_H + +#include +#include +#include +#include +class QDBusUnixFileDescriptor; +namespace NSS { + +class LockScreenProvider : public QObject +{ + Q_OBJECT + +public: + virtual ~LockScreenProvider() {} + + virtual bool isValid() = 0; + virtual bool inhibit() = 0; + virtual void release() = 0; + +signals: + void aboutToSleep(bool beforeSleep); + void lockRequested(); +}; + +class LogindProvider : public LockScreenProvider +{ + Q_OBJECT + +public: + explicit LogindProvider(); + virtual ~LogindProvider(); + + bool isValid() override; + bool inhibit() override; + void release() override; + +private: + QDBusInterface mInterface; + QScopedPointer mFileDescriptor; +}; + +class ConsoleKit2Provider : public LockScreenProvider +{ + Q_OBJECT + +public: + explicit ConsoleKit2Provider(); + virtual ~ConsoleKit2Provider(); + + bool isValid() override; + bool inhibit() override; + void release() override; + +private: + QDBusInterface mInterface; + bool mMethodInhibitPresent; + QScopedPointer mFileDescriptor; +}; + +class LockScreenManager : public QObject +{ + Q_OBJECT +public: + enum LOCK_STATUS{ + UNLOCKED = 1, + LOCKED + + }; + explicit LockScreenManager(QObject *parent = nullptr); + virtual ~LockScreenManager(); + + bool startup(bool lockBeforeSleep, int powerAfterLockDelay/*!< ms*/); + void saveLockStatus(LOCK_STATUS status); +private: + void inhibit(); +private: + LockScreenProvider *mProvider; + bool mLockedBeforeSleep; +}; +} +#endif diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenshortcut.cpp b/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenshortcut.cpp new file mode 100644 index 0000000..57ab1bb --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenshortcut.cpp @@ -0,0 +1,34 @@ +#include "lockscreenshortcut.h" +#include +#include + +namespace NSS { +#define DEFAULT_SHORTCUT "Control+Alt+L" +#define DEFAULT_SHORTCUT_1 "Meta+L" +LockScreenShortcut::LockScreenShortcut(QObject *parent) : QObject(parent) +{ + mLockShortcut = GlobalKeyShortcut::Client::instance()->addAction( + QString(), QString("/nde/screensaver/greeter"), tr("Activate Lock Screen"), this); + if (mLockShortcut) + { + connect(mLockShortcut, &GlobalKeyShortcut::Action::registrationFinished, this, [=]{ + if (mLockShortcut->shortcut().isEmpty()) + { + mLockShortcut->changeShortcut(DEFAULT_SHORTCUT); + } + }); + connect(mLockShortcut, SIGNAL(activated()), this, SIGNAL(globalKeyActivated())); + } + + mLockShortcut1 = GlobalKeyShortcut::Client::instance()->addAction( + QString(), QString("/nde/screensaver/greeter1"), tr("Activate Lock Screen"), this); + if(mLockShortcut1) + { + connect(mLockShortcut1, &GlobalKeyShortcut::Action::registrationFinished, [this] { + if(mLockShortcut1->shortcut().isEmpty()) + mLockShortcut1->changeShortcut(DEFAULT_SHORTCUT_1); + }); + connect(mLockShortcut1, SIGNAL(activated()), this, SIGNAL(globalKeyActivated())); + } +} +} diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenshortcut.h b/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenshortcut.h new file mode 100644 index 0000000..6791b76 --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/lockscreenshortcut.h @@ -0,0 +1,26 @@ +#ifndef LOCKSCREENSHORTCUT_H +#define LOCKSCREENSHORTCUT_H + +#include + +namespace GlobalKeyShortcut +{ +class Action; +} +namespace NSS { + + +class LockScreenShortcut : public QObject +{ + Q_OBJECT +public: + explicit LockScreenShortcut(QObject *parent = nullptr); + +signals: + void globalKeyActivated(); +private: + GlobalKeyShortcut::Action * mLockShortcut; + GlobalKeyShortcut::Action * mLockShortcut1; +}; +} +#endif // LOCKSCREENSHORTCUT_H diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/org.nde.screensaver.xml b/nde-screensaver-0.1.0/src/nde-screensaver/org.nde.screensaver.xml new file mode 100644 index 0000000..bc119d9 --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/org.nde.screensaver.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/screensaver.cpp b/nde-screensaver-0.1.0/src/nde-screensaver/screensaver.cpp new file mode 100644 index 0000000..11b9449 --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/screensaver.cpp @@ -0,0 +1,32 @@ +#include "screensaver.h" +#include "screensaveradaptor.h" +#include "ScreenSaverApp.h" + +ScreenSaver::ScreenSaver(QObject *parent) : QObject(parent) +{ + new ScreenSaverAdaptor(this); + if (!QDBusConnection::sessionBus().isConnected()) { + qWarning() << "Cannot connect to the D-Bus session bus."; + } + + if (!QDBusConnection::sessionBus().registerService(QStringLiteral("org.nde.ScreenSaver"))) { + qWarning() << QDBusConnection::systemBus().lastError().message(); + } + QDBusConnection::sessionBus().registerObject(QStringLiteral("/ScreenSaver"), QStringLiteral("org.nde.ScreenSaver"), this); +} + +void ScreenSaver::lock() +{ + NSS::SaverApp->lockSession(); +} +void ScreenSaver::setIdleTime(int secs) +{ + QSettings setting("nde", "screensaver"); + setting.setValue("idleTime", secs); + NSS::SaverApp->setIdleTime(secs); +} +bool ScreenSaver::getLockState() +{ + return NSS::SaverApp->locked(); +} + diff --git a/nde-screensaver-0.1.0/src/nde-screensaver/screensaver.h b/nde-screensaver-0.1.0/src/nde-screensaver/screensaver.h new file mode 100644 index 0000000..bea9197 --- /dev/null +++ b/nde-screensaver-0.1.0/src/nde-screensaver/screensaver.h @@ -0,0 +1,17 @@ +#ifndef SCREENSAVER_H +#define SCREENSAVER_H + +#include +class ScreenSaver : public QObject +{ + Q_OBJECT +public: + explicit ScreenSaver(QObject *parent = nullptr); + +public slots: + void lock(); + bool getLockState(); + void setIdleTime(int secs); +}; + +#endif diff --git a/nde-screensaver.spec b/nde-screensaver.spec new file mode 100644 index 0000000..f8f5576 --- /dev/null +++ b/nde-screensaver.spec @@ -0,0 +1,76 @@ +Name: nde-screensaver +Version: 0.1.0 +Release: 1%{?dist} +License: GPLv2+ +Summary: QML based X11 screen saver and screen lock +Source0: %{name}-%{version}.tar.gz + +BuildRequires: cmake >= 2.8.8 +BuildRequires: extra-cmake-modules +BuildRequires: kf5-kidletime-devel +BuildRequires: libxcb-devel +BuildRequires: nde-lib-devel +BuildRequires: pam-devel +BuildRequires: pkgconfig(libsystemd) +BuildRequires: pkgconfig(systemd) + +BuildRequires: qt5-qtbase-devel >= 5.6 +BuildRequires: qt5-qtdeclarative-devel >= 5.6 +BuildRequires: qt5-qttools-devel >= 5.6 +BuildRequires: kf5-kwindowsystem-devel >= 5.5.0 +BuildRequires: pkgconfig(nde-globalkeys) +BuildRequires: pkgconfig(libstatgrab) +BuildRequires: shadow-utils +BuildRequires: systemd + + +%if 0%{?fedora} +BuildRequires: nde-backgrounds +Requires: system-logos +%endif +Requires: systemd +Requires: xorg-x11-xinit +Requires: libstatgrab +%ifnarch s390 s390x +Requires: xorg-x11-server-Xorg +Requires: kf5-kidletime +Requires: nde-lib + +Suggests: qt5-qtvirtualkeyboard%{?_isa} +%endif +%{?systemd_requires} + +Requires(pre): shadow-utils + +%description +newstart desktop environment screen saver and lock + + +%prep +%setup -q + +%build +mkdir %{_target_platform} +pushd %{_target_platform} +%{cmake} .. \ + -DBUILD_MAN_PAGES:BOOL=ON \ + -DCMAKE_BUILD_TYPE:STRING="Release" \ + -DENABLE_JOURNALD:BOOL=ON \ + -DSESSION_COMMAND:PATH=/etc/X11/xinit/Xsession +popd + +%make_build -C %{_target_platform} + + +%install +make install/fast DESTDIR=%{buildroot} -C %{_target_platform} + +%files +%{_datadir}/nde-screensaver/* +%{_sysconfdir}/xdg/autostart/nde-screensaver.desktop +%{_sysconfdir}/pam.d/nde-screensaver +%{_libexecdir}/nde-screensaver-greeter +%{_libexecdir}/nde-screensaver-helper +%{_bindir}/nde-screensaver + +%changelog -- Gitee