refactor!: rename to face-unlock
This commit is contained in:
1 parent
44449f103b
commit
6e6a6e6d03
66 files changed
+1709
-1709
No files matched your search
@@ -60,8 +60,8 @@ body:
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: The output of `plasma-face-unlock --version`.
|
||||
placeholder: plasma-face-unlock 1.0.1
|
||||
description: The output of `face-unlock --version`.
|
||||
placeholder: face-unlock 1.0.1
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
@@ -88,7 +88,7 @@ body:
|
||||
id: logs
|
||||
attributes:
|
||||
label: Status and logs
|
||||
description: The output of `plasma-face-unlock status`. If a scan goes wrong, also `journalctl -b -u plasma-face-unlockd` and `journalctl --user -b -u plasma-face-unlock-agent`.
|
||||
description: The output of `face-unlock status`. If a scan goes wrong, also `journalctl -b -u face-unlockd` and `journalctl --user -b -u face-unlock-agent`.
|
||||
render: shell
|
||||
- type: textarea
|
||||
id: more
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: 💡 Feature request
|
||||
description: An idea to make plasma-face-unlock better.
|
||||
description: An idea to make face-unlock better.
|
||||
labels:
|
||||
- enhancement
|
||||
body:
|
||||
|
||||
@@ -116,8 +116,8 @@ jobs:
|
||||
|
||||
- name: Look inside what was built
|
||||
run: |
|
||||
rpm -qip dist/plasma-face-unlock-[0-9]*.rpm
|
||||
rpm -qlp dist/plasma-face-unlock-[0-9]*.rpm
|
||||
rpm -qip dist/face-unlock-[0-9]*.rpm
|
||||
rpm -qlp dist/face-unlock-[0-9]*.rpm
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
@@ -254,13 +254,13 @@ jobs:
|
||||
run: |
|
||||
apt-get update -qq && apt-get install -y --no-install-recommends gpg
|
||||
install -d -m 0755 /etc/apt/keyrings
|
||||
gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg < pages/KEY.gpg
|
||||
echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] file://$PWD/pages/deb/${{ matrix.codename }} ./" \
|
||||
> /etc/apt/sources.list.d/plasma-face-unlock.list
|
||||
gpg --dearmor -o /etc/apt/keyrings/face-unlock.gpg < pages/KEY.gpg
|
||||
echo "deb [signed-by=/etc/apt/keyrings/face-unlock.gpg] file://$PWD/pages/deb/${{ matrix.codename }} ./" \
|
||||
> /etc/apt/sources.list.d/face-unlock.list
|
||||
apt-get update
|
||||
apt-get install -y plasma-face-unlock
|
||||
apt-get install -y face-unlock
|
||||
useradd -m tester
|
||||
runuser -u tester -- plasma-face-unlock --version
|
||||
runuser -u tester -- face-unlock --version
|
||||
|
||||
verify-dnf:
|
||||
name: Install from the RPM repository
|
||||
@@ -281,15 +281,15 @@ jobs:
|
||||
run: |
|
||||
rpm --import pages/KEY.gpg
|
||||
rpm --import signer/rpm-signer.asc
|
||||
cat > /etc/yum.repos.d/plasma-face-unlock.repo <<EOF
|
||||
[plasma-face-unlock]
|
||||
name=plasma-face-unlock
|
||||
cat > /etc/yum.repos.d/face-unlock.repo <<EOF
|
||||
[face-unlock]
|
||||
name=face-unlock
|
||||
baseurl=file://$PWD/pages/rpm
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
repo_gpgcheck=1
|
||||
gpgkey=file://$PWD/pages/KEY.gpg
|
||||
EOF
|
||||
dnf install -y plasma-face-unlock util-linux
|
||||
dnf install -y face-unlock util-linux
|
||||
useradd -m tester
|
||||
runuser -u tester -- plasma-face-unlock --version
|
||||
runuser -u tester -- face-unlock --version
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# Changelog
|
||||
|
||||
What each release brings, newest first. The [GitHub releases](https://github.com/LoonixTools/plasma-face-unlock/releases) add every commit that went into it.
|
||||
What each release brings, newest first. The [GitHub releases](https://github.com/LoonixTools/face-unlock/releases) add every commit that went into it.
|
||||
|
||||
## v1.0.1
|
||||
|
||||
@@ -17,7 +17,7 @@ _2026-09-23_
|
||||
Welcome to the very first release of plasma-face-unlock! It brings Face ID to KDE Plasma: look at the screen and it unlocks. The lock screen, sudo and admin prompts can all take your face instead of a password.
|
||||
|
||||
<p align="center">
|
||||
<img width="480" alt="The bubble drops down over the lock screen, finds the face and shows a green tick" src="https://raw.githubusercontent.com/LoonixTools/plasma-face-unlock/v1.0.0/res/screenshots/unlock.webp">
|
||||
<img width="480" alt="The bubble drops down over the lock screen, finds the face and shows a green tick" src="https://raw.githubusercontent.com/LoonixTools/face-unlock/v1.0.0/res/screenshots/unlock.webp">
|
||||
</p>
|
||||
|
||||
### Highlights
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
## Layout
|
||||
|
||||
- `src/plasma-face-unlock` and `src/lib/*.sh`: the command and its menu, plain bash.
|
||||
- `src/face-unlock` and `src/lib/*.sh`: the command and its menu, plain bash.
|
||||
- `src/core`: camera, detection, recognition, liveness, face store. Used by the daemon and the tests.
|
||||
- `src/daemon`: the root service. It owns the camera and the face data.
|
||||
- `src/agent`: the Qt/QML program in the session: bubble, lock screen, setup window.
|
||||
@@ -48,10 +48,10 @@ A minor or major release (has `### Highlights`, gets a heading and the support s
|
||||
|
||||
_2026-09-24_
|
||||
|
||||
Welcome to plasma-face-unlock `v1.4.0`! One or two sentences on what this release is about.
|
||||
Welcome to face-unlock `v1.4.0`! One or two sentences on what this release is about.
|
||||
|
||||
<p align="center">
|
||||
<img width="480" alt="What the picture shows" src="https://raw.githubusercontent.com/LoonixTools/plasma-face-unlock/v1.4.0/<path>">
|
||||
<img width="480" alt="What the picture shows" src="https://raw.githubusercontent.com/LoonixTools/face-unlock/v1.4.0/<path>">
|
||||
</p>
|
||||
|
||||
### 🚨 Breaking changes
|
||||
@@ -85,7 +85,7 @@ Never test against the real setup: enrolling and the PAM files belong to the use
|
||||
PAM file editing against copies of real PAM files. No camera, no root.
|
||||
- Without a camera, point the daemon at pictures or a video: `Camera=images:<dir>` or
|
||||
`Camera=file:<video>` in the config passed to `--config`.
|
||||
- A development daemon needs no root: `plasma-face-unlockd --socket $XDG_RUNTIME_DIR/pfu/socket
|
||||
- A development daemon needs no root: `face-unlockd --socket $XDG_RUNTIME_DIR/fu/socket
|
||||
--state-dir DIR --config FILE --models DIR`. It skips polkit when it does not run as root. Point
|
||||
the other parts at it with `PFU_SOCKET`.
|
||||
the other parts at it with `FU_SOCKET`.
|
||||
- `make check` after every change. New strings: `po/update-pot.sh`, then translate them in every `po/*.po`.
|
||||
+56
-56
@@ -1,4 +1,4 @@
|
||||
# plasma-face-unlock: the compiled half
|
||||
# face-unlock: the compiled half
|
||||
#
|
||||
# The Makefile is the entry point and calls this. Everything that has to be
|
||||
# compiled lives here: the daemon, the agent, the client the shell code uses,
|
||||
@@ -6,9 +6,9 @@
|
||||
# installed by the Makefile, which is where the paths come from.
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
project(plasma-face-unlock VERSION 1.0.1 LANGUAGES C CXX)
|
||||
project(face-unlock VERSION 1.0.1 LANGUAGES C CXX)
|
||||
|
||||
set(PFU_VERSION "${PROJECT_VERSION}" CACHE STRING "Version reported by every binary")
|
||||
set(FU_VERSION "${PROJECT_VERSION}" CACHE STRING "Version reported by every binary")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
@@ -21,19 +21,19 @@ endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
option(PFU_BUILD_AGENT "Build the Plasma agent (bubble, lock screen, set up window)" ON)
|
||||
option(PFU_BUILD_PAM "Build the PAM module" ON)
|
||||
option(PFU_BUILD_TESTS "Build the tests" ON)
|
||||
option(FU_BUILD_AGENT "Build the Plasma agent (bubble, lock screen, set up window)" ON)
|
||||
option(FU_BUILD_PAM "Build the PAM module" ON)
|
||||
option(FU_BUILD_TESTS "Build the tests" ON)
|
||||
|
||||
# Where things go at run time. The defaults suit a normal install into /usr;
|
||||
# the Makefile passes its own values so the two never disagree.
|
||||
set(PFU_LIBEXECDIR "${CMAKE_INSTALL_PREFIX}/lib/plasma-face-unlock" CACHE PATH "Helper programs")
|
||||
set(PFU_MODELDIR "${CMAKE_INSTALL_FULL_DATADIR}/plasma-face-unlock/models" CACHE PATH "Neural network models")
|
||||
set(PFU_LOCALEDIR "${CMAKE_INSTALL_FULL_LOCALEDIR}" CACHE PATH "Translations")
|
||||
set(PFU_SOCKET "/run/plasma-face-unlock/socket" CACHE STRING "The daemon's socket")
|
||||
set(PFU_STATEDIR "/var/lib/plasma-face-unlock" CACHE PATH "Face data")
|
||||
set(PFU_CONFIG "/etc/plasma-face-unlock/config" CACHE FILEPATH "System settings")
|
||||
set(PFU_PAMDIR "${CMAKE_INSTALL_PREFIX}/lib/security" CACHE PATH "Where PAM modules live")
|
||||
set(FU_LIBEXECDIR "${CMAKE_INSTALL_PREFIX}/lib/face-unlock" CACHE PATH "Helper programs")
|
||||
set(FU_MODELDIR "${CMAKE_INSTALL_FULL_DATADIR}/face-unlock/models" CACHE PATH "Neural network models")
|
||||
set(FU_LOCALEDIR "${CMAKE_INSTALL_FULL_LOCALEDIR}" CACHE PATH "Translations")
|
||||
set(FU_SOCKET "/run/face-unlock/socket" CACHE STRING "The daemon's socket")
|
||||
set(FU_STATEDIR "/var/lib/face-unlock" CACHE PATH "Face data")
|
||||
set(FU_CONFIG "/etc/face-unlock/config" CACHE FILEPATH "System settings")
|
||||
set(FU_PAMDIR "${CMAKE_INSTALL_PREFIX}/lib/security" CACHE PATH "Where PAM modules live")
|
||||
|
||||
configure_file(src/shared/buildconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/buildconfig.h @ONLY)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} src/shared)
|
||||
@@ -47,35 +47,35 @@ add_compile_options(-Wall -Wextra -Wno-unused-parameter)
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Core DBus Network)
|
||||
# OpenCV 5 split the contour and transform helpers into "geometry".
|
||||
find_package(OpenCV REQUIRED COMPONENTS core)
|
||||
set(PFU_OPENCV_MODULES core imgproc imgcodecs videoio objdetect dnn)
|
||||
set(FU_OPENCV_MODULES core imgproc imgcodecs videoio objdetect dnn)
|
||||
if(OpenCV_VERSION_MAJOR GREATER_EQUAL 5)
|
||||
list(APPEND PFU_OPENCV_MODULES geometry)
|
||||
list(APPEND FU_OPENCV_MODULES geometry)
|
||||
endif()
|
||||
find_package(OpenCV REQUIRED COMPONENTS ${PFU_OPENCV_MODULES})
|
||||
find_package(OpenCV REQUIRED COMPONENTS ${FU_OPENCV_MODULES})
|
||||
|
||||
# The settings file reader, shared with the agent (which has no use for
|
||||
# OpenCV).
|
||||
add_library(pfu_common STATIC src/core/keyvalue.cpp)
|
||||
target_include_directories(pfu_common PUBLIC src/core)
|
||||
target_link_libraries(pfu_common PUBLIC Qt6::Core)
|
||||
set_target_properties(pfu_common PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
add_library(fu_common STATIC src/core/keyvalue.cpp)
|
||||
target_include_directories(fu_common PUBLIC src/core)
|
||||
target_link_libraries(fu_common PUBLIC Qt6::Core)
|
||||
set_target_properties(fu_common PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
add_library(pfu_core STATIC
|
||||
add_library(fu_core STATIC
|
||||
src/core/settings.cpp
|
||||
src/core/camera.cpp
|
||||
src/core/vision.cpp
|
||||
src/core/liveness.cpp
|
||||
src/core/store.cpp
|
||||
)
|
||||
target_include_directories(pfu_core PUBLIC src/core ${OpenCV_INCLUDE_DIRS})
|
||||
target_link_libraries(pfu_core PUBLIC pfu_common Qt6::Core ${OpenCV_LIBS})
|
||||
set_target_properties(pfu_core PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
target_include_directories(fu_core PUBLIC src/core ${OpenCV_INCLUDE_DIRS})
|
||||
target_link_libraries(fu_core PUBLIC fu_common Qt6::Core ${OpenCV_LIBS})
|
||||
set_target_properties(fu_core PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# The daemon
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
add_executable(plasma-face-unlockd
|
||||
add_executable(face-unlockd
|
||||
src/daemon/job.h
|
||||
src/daemon/agentlink.cpp
|
||||
src/daemon/main.cpp
|
||||
@@ -87,38 +87,38 @@ add_executable(plasma-face-unlockd
|
||||
src/daemon/userstate.cpp
|
||||
src/daemon/system.cpp
|
||||
)
|
||||
target_link_libraries(plasma-face-unlockd PRIVATE pfu_core Qt6::DBus Qt6::Network)
|
||||
install(TARGETS plasma-face-unlockd DESTINATION ${PFU_LIBEXECDIR})
|
||||
target_link_libraries(face-unlockd PRIVATE fu_core Qt6::DBus Qt6::Network)
|
||||
install(TARGETS face-unlockd DESTINATION ${FU_LIBEXECDIR})
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# The client the shell code uses
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
add_executable(plasma-face-unlock-ctl src/ctl/main.cpp)
|
||||
target_link_libraries(plasma-face-unlock-ctl PRIVATE Qt6::Core Qt6::Network)
|
||||
install(TARGETS plasma-face-unlock-ctl DESTINATION ${PFU_LIBEXECDIR})
|
||||
add_executable(face-unlock-ctl src/ctl/main.cpp)
|
||||
target_link_libraries(face-unlock-ctl PRIVATE Qt6::Core Qt6::Network)
|
||||
install(TARGETS face-unlock-ctl DESTINATION ${FU_LIBEXECDIR})
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# The PAM module
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
if(PFU_BUILD_PAM)
|
||||
if(FU_BUILD_PAM)
|
||||
find_path(PAM_INCLUDE_DIR security/pam_modules.h REQUIRED)
|
||||
find_library(PAM_LIBRARY pam REQUIRED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(SYSTEMD IMPORTED_TARGET libsystemd)
|
||||
|
||||
add_library(pam_plasma_face_unlock MODULE src/pam/pam_plasma_face_unlock.c)
|
||||
set_target_properties(pam_plasma_face_unlock PROPERTIES PREFIX "" C_VISIBILITY_PRESET hidden)
|
||||
target_include_directories(pam_plasma_face_unlock PRIVATE ${PAM_INCLUDE_DIR})
|
||||
target_link_libraries(pam_plasma_face_unlock PRIVATE ${PAM_LIBRARY})
|
||||
add_library(pam_face_unlock MODULE src/pam/pam_face_unlock.c)
|
||||
set_target_properties(pam_face_unlock PROPERTIES PREFIX "" C_VISIBILITY_PRESET hidden)
|
||||
target_include_directories(pam_face_unlock PRIVATE ${PAM_INCLUDE_DIR})
|
||||
target_link_libraries(pam_face_unlock PRIVATE ${PAM_LIBRARY})
|
||||
if(SYSTEMD_FOUND)
|
||||
target_compile_definitions(pam_plasma_face_unlock PRIVATE HAVE_SYSTEMD=1)
|
||||
target_link_libraries(pam_plasma_face_unlock PRIVATE PkgConfig::SYSTEMD)
|
||||
target_compile_definitions(pam_face_unlock PRIVATE HAVE_SYSTEMD=1)
|
||||
target_link_libraries(pam_face_unlock PRIVATE PkgConfig::SYSTEMD)
|
||||
endif()
|
||||
install(TARGETS pam_plasma_face_unlock DESTINATION ${PFU_PAMDIR})
|
||||
install(TARGETS pam_face_unlock DESTINATION ${FU_PAMDIR})
|
||||
|
||||
if(PFU_BUILD_TESTS)
|
||||
if(FU_BUILD_TESTS)
|
||||
add_executable(pam_harness tests/pam_harness.c)
|
||||
target_include_directories(pam_harness PRIVATE ${PAM_INCLUDE_DIR})
|
||||
target_link_libraries(pam_harness PRIVATE ${PAM_LIBRARY})
|
||||
@@ -129,7 +129,7 @@ endif()
|
||||
# The agent
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
if(PFU_BUILD_AGENT)
|
||||
if(FU_BUILD_AGENT)
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Gui Quick WaylandClient)
|
||||
# The bubble needs the Wayland surface of its window, which only the
|
||||
# private API hands out. It is the same one Plasma itself uses for this.
|
||||
@@ -142,7 +142,7 @@ if(PFU_BUILD_AGENT)
|
||||
find_package(LayerShellQt REQUIRED)
|
||||
find_package(KF6I18n REQUIRED)
|
||||
|
||||
qt_add_executable(plasma-face-unlock-agent
|
||||
qt_add_executable(face-unlock-agent
|
||||
src/agent/main.cpp
|
||||
src/agent/daemonclient.cpp
|
||||
src/agent/userconfig.cpp
|
||||
@@ -153,27 +153,27 @@ if(PFU_BUILD_AGENT)
|
||||
src/agent/inputwatcher.cpp
|
||||
src/agent/enrollcontroller.cpp
|
||||
)
|
||||
target_include_directories(plasma-face-unlock-agent PRIVATE src/agent)
|
||||
target_include_directories(face-unlock-agent PRIVATE src/agent)
|
||||
if(LayerShellQt_VERSION VERSION_GREATER_EQUAL 6.6)
|
||||
target_compile_definitions(plasma-face-unlock-agent PRIVATE PFU_LAYERSHELL_HAS_SCREEN)
|
||||
target_compile_definitions(face-unlock-agent PRIVATE FU_LAYERSHELL_HAS_SCREEN)
|
||||
endif()
|
||||
|
||||
qt6_generate_wayland_protocol_client_sources(plasma-face-unlock-agent
|
||||
qt6_generate_wayland_protocol_client_sources(face-unlock-agent
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/protocols/kde-lockscreen-overlay-v1.xml
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/protocols/ext-idle-notify-v1.xml)
|
||||
|
||||
# The QML files sit next to the module's qmldir in the resources, so they
|
||||
# see each other (and the Theme singleton) without importing anything.
|
||||
# Under /qt/qml, which the engine searches, or an installed agent finds no
|
||||
# types (the build directory only works by its PlasmaFaceUnlock/qmldir).
|
||||
set(PFU_QML_FILES Theme FaceGlyph LockGlyph Checkmark Bubble TickRing Enroll PillButton)
|
||||
foreach(f ${PFU_QML_FILES})
|
||||
# types (the build directory only works by its FaceUnlock/qmldir).
|
||||
set(FU_QML_FILES Theme FaceGlyph LockGlyph Checkmark Bubble TickRing Enroll PillButton)
|
||||
foreach(f ${FU_QML_FILES})
|
||||
set_source_files_properties(src/agent/qml/${f}.qml PROPERTIES QT_RESOURCE_ALIAS ${f}.qml)
|
||||
endforeach()
|
||||
set_source_files_properties(src/agent/qml/Theme.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
|
||||
|
||||
qt_add_qml_module(plasma-face-unlock-agent
|
||||
URI PlasmaFaceUnlock
|
||||
qt_add_qml_module(face-unlock-agent
|
||||
URI FaceUnlock
|
||||
VERSION 1.0
|
||||
RESOURCE_PREFIX /qt/qml
|
||||
SOURCES
|
||||
@@ -190,31 +190,31 @@ if(PFU_BUILD_AGENT)
|
||||
src/agent/qml/PillButton.qml
|
||||
)
|
||||
|
||||
target_link_libraries(plasma-face-unlock-agent PRIVATE
|
||||
target_link_libraries(face-unlock-agent PRIVATE
|
||||
Qt6::Gui Qt6::GuiPrivate Qt6::Quick Qt6::DBus Qt6::Network
|
||||
Qt6::WaylandClient Qt6::WaylandClientPrivate
|
||||
LayerShellQt::Interface
|
||||
KF6::I18n KF6::I18nQml
|
||||
pfu_common
|
||||
fu_common
|
||||
)
|
||||
install(TARGETS plasma-face-unlock-agent DESTINATION ${PFU_LIBEXECDIR})
|
||||
install(TARGETS face-unlock-agent DESTINATION ${FU_LIBEXECDIR})
|
||||
endif()
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
if(PFU_BUILD_TESTS)
|
||||
if(FU_BUILD_TESTS)
|
||||
enable_testing()
|
||||
|
||||
add_executable(test_liveness tests/test_liveness.cpp)
|
||||
target_link_libraries(test_liveness PRIVATE pfu_core)
|
||||
target_link_libraries(test_liveness PRIVATE fu_core)
|
||||
add_test(NAME liveness COMMAND test_liveness)
|
||||
|
||||
add_executable(test_store tests/test_store.cpp)
|
||||
target_link_libraries(test_store PRIVATE pfu_core)
|
||||
target_link_libraries(test_store PRIVATE fu_core)
|
||||
add_test(NAME store COMMAND test_store)
|
||||
|
||||
add_executable(test_images tests/test_images.cpp)
|
||||
target_link_libraries(test_images PRIVATE pfu_core)
|
||||
target_link_libraries(test_images PRIVATE fu_core)
|
||||
endif()
|
||||
@@ -1,4 +1,4 @@
|
||||
# plasma-face-unlock: build and install
|
||||
# face-unlock: build and install
|
||||
#
|
||||
# The shell front end installs as it is, like middleclick-autoscroll. The rest
|
||||
# is compiled by CMake (the daemon, the agent, the PAM module, the client the
|
||||
@@ -15,9 +15,9 @@ PREFIX ?= /usr
|
||||
DESTDIR ?=
|
||||
BINDIR ?= $(PREFIX)/bin
|
||||
DATADIR ?= $(PREFIX)/share
|
||||
LIBDIR ?= $(DATADIR)/plasma-face-unlock/lib
|
||||
LIBEXECDIR ?= $(PREFIX)/lib/plasma-face-unlock
|
||||
MODELDIR ?= $(DATADIR)/plasma-face-unlock/models
|
||||
LIBDIR ?= $(DATADIR)/face-unlock/lib
|
||||
LIBEXECDIR ?= $(PREFIX)/lib/face-unlock
|
||||
MODELDIR ?= $(DATADIR)/face-unlock/models
|
||||
LOCALEDIR ?= $(DATADIR)/locale
|
||||
MANDIR ?= $(DATADIR)/man
|
||||
APPDIR ?= $(DATADIR)/applications
|
||||
@@ -48,7 +48,7 @@ CMAKE_FLAGS ?=
|
||||
|
||||
LINGUAS := de es fr it ja ko nl pl pt_BR ru tr uk zh_CN
|
||||
MOFILES := $(patsubst %,po/%.mo,$(LINGUAS))
|
||||
MANPAGE := doc/plasma-face-unlock.1
|
||||
MANPAGE := doc/face-unlock.1
|
||||
|
||||
LIBS := $(wildcard src/lib/*.sh)
|
||||
|
||||
@@ -85,11 +85,11 @@ native:
|
||||
$(CMAKE) -S . -B $(BUILDDIR) \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=$(PREFIX) \
|
||||
-DPFU_VERSION=$(VERSION) \
|
||||
-DPFU_LIBEXECDIR=$(LIBEXECDIR) \
|
||||
-DPFU_MODELDIR=$(MODELDIR) \
|
||||
-DPFU_LOCALEDIR=$(LOCALEDIR) \
|
||||
-DPFU_PAMDIR=$(PAMDIR) \
|
||||
-DFU_VERSION=$(VERSION) \
|
||||
-DFU_LIBEXECDIR=$(LIBEXECDIR) \
|
||||
-DFU_MODELDIR=$(MODELDIR) \
|
||||
-DFU_LOCALEDIR=$(LOCALEDIR) \
|
||||
-DFU_PAMDIR=$(PAMDIR) \
|
||||
$(CMAKE_FLAGS)
|
||||
$(CMAKE) --build $(BUILDDIR) --parallel
|
||||
|
||||
@@ -108,7 +108,7 @@ else
|
||||
@echo "msgfmt not found, skipping $@"
|
||||
endif
|
||||
|
||||
$(MANPAGE): doc/plasma-face-unlock.1.scd
|
||||
$(MANPAGE): doc/face-unlock.1.scd
|
||||
ifdef SCDOC
|
||||
$(SCDOC) < $< > $@
|
||||
else
|
||||
@@ -117,11 +117,11 @@ endif
|
||||
|
||||
# Syntax-check every shell file, and run shellcheck when it is available.
|
||||
check:
|
||||
@set -e; for f in src/plasma-face-unlock $(LIBS) tests/*.sh; do \
|
||||
@set -e; for f in src/face-unlock $(LIBS) tests/*.sh; do \
|
||||
bash -n "$$f" && echo "ok $$f"; \
|
||||
done
|
||||
@if command -v shellcheck >/dev/null 2>&1; then \
|
||||
shellcheck -x -e SC1090,SC1091 src/plasma-face-unlock $(LIBS) tests/*.sh; \
|
||||
shellcheck -x -e SC1090,SC1091 src/face-unlock $(LIBS) tests/*.sh; \
|
||||
echo "ok shellcheck"; \
|
||||
else \
|
||||
echo "shellcheck not found, skipped"; \
|
||||
@@ -144,7 +144,7 @@ install: build
|
||||
DESTDIR="$(DESTDIR)" $(CMAKE) --install $(BUILDDIR)
|
||||
|
||||
# the command
|
||||
install -Dm755 src/plasma-face-unlock "$(DESTDIR)$(BINDIR)/plasma-face-unlock"
|
||||
install -Dm755 src/face-unlock "$(DESTDIR)$(BINDIR)/face-unlock"
|
||||
install -d "$(DESTDIR)$(LIBDIR)"
|
||||
install -Dm644 -t "$(DESTDIR)$(LIBDIR)" $(LIBS)
|
||||
sed -i -e 's|@VERSION@|$(VERSION)|g' \
|
||||
@@ -152,7 +152,7 @@ install: build
|
||||
-e 's|@LIBEXECDIR@|$(LIBEXECDIR)|g' \
|
||||
-e 's|@LOCALEDIR@|$(LOCALEDIR)|g' \
|
||||
-e 's|@PAMDIR@|$(PAMDIR)|g' \
|
||||
"$(DESTDIR)$(BINDIR)/plasma-face-unlock" \
|
||||
"$(DESTDIR)$(BINDIR)/face-unlock" \
|
||||
"$(DESTDIR)$(LIBDIR)"/*.sh
|
||||
|
||||
# the models
|
||||
@@ -161,50 +161,50 @@ install: build
|
||||
done
|
||||
|
||||
# the daemon's socket and service, the agent's user service
|
||||
install -Dm644 res/systemd/plasma-face-unlockd.socket "$(DESTDIR)$(SYSTEMUNITDIR)/plasma-face-unlockd.socket"
|
||||
install -Dm644 res/systemd/plasma-face-unlockd.service "$(DESTDIR)$(SYSTEMUNITDIR)/plasma-face-unlockd.service"
|
||||
install -Dm644 res/systemd/plasma-face-unlock-agent.service "$(DESTDIR)$(USERUNITDIR)/plasma-face-unlock-agent.service"
|
||||
install -Dm644 res/systemd/face-unlockd.socket "$(DESTDIR)$(SYSTEMUNITDIR)/face-unlockd.socket"
|
||||
install -Dm644 res/systemd/face-unlockd.service "$(DESTDIR)$(SYSTEMUNITDIR)/face-unlockd.service"
|
||||
install -Dm644 res/systemd/face-unlock-agent.service "$(DESTDIR)$(USERUNITDIR)/face-unlock-agent.service"
|
||||
sed -i -e 's|@LIBEXECDIR@|$(LIBEXECDIR)|g' \
|
||||
"$(DESTDIR)$(SYSTEMUNITDIR)/plasma-face-unlockd.service" \
|
||||
"$(DESTDIR)$(USERUNITDIR)/plasma-face-unlock-agent.service"
|
||||
"$(DESTDIR)$(SYSTEMUNITDIR)/face-unlockd.service" \
|
||||
"$(DESTDIR)$(USERUNITDIR)/face-unlock-agent.service"
|
||||
|
||||
# the desktop file KWin looks for before it lets the bubble above the
|
||||
# lock screen, the polkit action, the icon
|
||||
install -Dm644 res/applications/io.github.loonixtools.plasma-face-unlock-agent.desktop \
|
||||
"$(DESTDIR)$(APPDIR)/io.github.loonixtools.plasma-face-unlock-agent.desktop"
|
||||
sed -i -e 's|@LIBEXECDIR@|$(LIBEXECDIR)|g' "$(DESTDIR)$(APPDIR)/io.github.loonixtools.plasma-face-unlock-agent.desktop"
|
||||
install -Dm644 res/polkit/io.github.loonixtools.plasma-face-unlock.policy \
|
||||
"$(DESTDIR)$(POLKITDIR)/io.github.loonixtools.plasma-face-unlock.policy"
|
||||
install -Dm644 res/plasma-face-unlock.svg "$(DESTDIR)$(ICONDIR)/plasma-face-unlock.svg"
|
||||
install -Dm644 res/applications/io.github.loonixtools.face-unlock-agent.desktop \
|
||||
"$(DESTDIR)$(APPDIR)/io.github.loonixtools.face-unlock-agent.desktop"
|
||||
sed -i -e 's|@LIBEXECDIR@|$(LIBEXECDIR)|g' "$(DESTDIR)$(APPDIR)/io.github.loonixtools.face-unlock-agent.desktop"
|
||||
install -Dm644 res/polkit/io.github.loonixtools.face-unlock.policy \
|
||||
"$(DESTDIR)$(POLKITDIR)/io.github.loonixtools.face-unlock.policy"
|
||||
install -Dm644 res/face-unlock.svg "$(DESTDIR)$(ICONDIR)/face-unlock.svg"
|
||||
|
||||
# translations
|
||||
@for l in $(LINGUAS); do \
|
||||
if [ -f "po/$$l.mo" ]; then \
|
||||
install -Dm644 "po/$$l.mo" \
|
||||
"$(DESTDIR)$(LOCALEDIR)/$$l/LC_MESSAGES/plasma-face-unlock.mo"; \
|
||||
"$(DESTDIR)$(LOCALEDIR)/$$l/LC_MESSAGES/face-unlock.mo"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
# documentation
|
||||
@if [ -f $(MANPAGE) ]; then \
|
||||
install -Dm644 $(MANPAGE) "$(DESTDIR)$(MANDIR)/man1/plasma-face-unlock.1"; \
|
||||
install -Dm644 $(MANPAGE) "$(DESTDIR)$(MANDIR)/man1/face-unlock.1"; \
|
||||
fi
|
||||
install -Dm644 README.md "$(DESTDIR)$(DATADIR)/doc/plasma-face-unlock/README.md"
|
||||
install -Dm644 README.md "$(DESTDIR)$(DATADIR)/doc/face-unlock/README.md"
|
||||
|
||||
uninstall:
|
||||
rm -f "$(DESTDIR)$(BINDIR)/plasma-face-unlock"
|
||||
rm -rf "$(DESTDIR)$(DATADIR)/plasma-face-unlock"
|
||||
rm -f "$(DESTDIR)$(BINDIR)/face-unlock"
|
||||
rm -rf "$(DESTDIR)$(DATADIR)/face-unlock"
|
||||
rm -rf "$(DESTDIR)$(LIBEXECDIR)"
|
||||
rm -f "$(DESTDIR)$(PAMDIR)/pam_plasma_face_unlock.so"
|
||||
rm -f "$(DESTDIR)$(SYSTEMUNITDIR)/plasma-face-unlockd.socket"
|
||||
rm -f "$(DESTDIR)$(SYSTEMUNITDIR)/plasma-face-unlockd.service"
|
||||
rm -f "$(DESTDIR)$(USERUNITDIR)/plasma-face-unlock-agent.service"
|
||||
rm -f "$(DESTDIR)$(APPDIR)/io.github.loonixtools.plasma-face-unlock-agent.desktop"
|
||||
rm -f "$(DESTDIR)$(POLKITDIR)/io.github.loonixtools.plasma-face-unlock.policy"
|
||||
rm -f "$(DESTDIR)$(ICONDIR)/plasma-face-unlock.svg"
|
||||
rm -f "$(DESTDIR)$(MANDIR)/man1/plasma-face-unlock.1"
|
||||
rm -rf "$(DESTDIR)$(DATADIR)/doc/plasma-face-unlock"
|
||||
@for l in $(LINGUAS); do rm -f "$(DESTDIR)$(LOCALEDIR)/$$l/LC_MESSAGES/plasma-face-unlock.mo"; done
|
||||
rm -f "$(DESTDIR)$(PAMDIR)/pam_face_unlock.so"
|
||||
rm -f "$(DESTDIR)$(SYSTEMUNITDIR)/face-unlockd.socket"
|
||||
rm -f "$(DESTDIR)$(SYSTEMUNITDIR)/face-unlockd.service"
|
||||
rm -f "$(DESTDIR)$(USERUNITDIR)/face-unlock-agent.service"
|
||||
rm -f "$(DESTDIR)$(APPDIR)/io.github.loonixtools.face-unlock-agent.desktop"
|
||||
rm -f "$(DESTDIR)$(POLKITDIR)/io.github.loonixtools.face-unlock.policy"
|
||||
rm -f "$(DESTDIR)$(ICONDIR)/face-unlock.svg"
|
||||
rm -f "$(DESTDIR)$(MANDIR)/man1/face-unlock.1"
|
||||
rm -rf "$(DESTDIR)$(DATADIR)/doc/face-unlock"
|
||||
@for l in $(LINGUAS); do rm -f "$(DESTDIR)$(LOCALEDIR)/$$l/LC_MESSAGES/face-unlock.mo"; done
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR) po/*.mo $(MANPAGE)
|
||||
@@ -1,8 +1,8 @@
|
||||
<p align="center">
|
||||
<img width="200" src="res/plasma-face-unlock.svg" alt="plasma-face-unlock">
|
||||
<img width="200" src="res/face-unlock.svg" alt="face-unlock">
|
||||
</p>
|
||||
|
||||
<h1 align="center">plasma-face-unlock</h1>
|
||||
<h1 align="center">face-unlock</h1>
|
||||
|
||||
<h3 align="center">Face ID for KDE Plasma.</h3>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<a href="#install">Install</a> |
|
||||
<a href="#how-to-use">How to use</a> |
|
||||
<a href="#is-it-safe">Is it safe?</a> |
|
||||
<a href="https://github.com/LoonixTools/plasma-face-unlock/issues">Report a bug</a>
|
||||
<a href="https://github.com/LoonixTools/face-unlock/issues">Report a bug</a>
|
||||
</h5>
|
||||
|
||||
<p align="center">
|
||||
@@ -35,7 +35,7 @@
|
||||
<summary><b>Arch</b>, CachyOS, EndeavourOS, Manjaro</summary>
|
||||
|
||||
```bash
|
||||
yay -S plasma-face-unlock
|
||||
yay -S face-unlock
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -44,9 +44,9 @@ yay -S plasma-face-unlock
|
||||
<summary><b>Fedora</b></summary>
|
||||
|
||||
```bash
|
||||
sudo curl -fsSL -o /etc/yum.repos.d/plasma-face-unlock.repo \
|
||||
https://loonixtools.github.io/plasma-face-unlock/plasma-face-unlock.repo
|
||||
sudo dnf install plasma-face-unlock
|
||||
sudo curl -fsSL -o /etc/yum.repos.d/face-unlock.repo \
|
||||
https://loonixtools.github.io/face-unlock/face-unlock.repo
|
||||
sudo dnf install face-unlock
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -57,11 +57,11 @@ sudo dnf install plasma-face-unlock
|
||||
```bash
|
||||
codename="$(sed -n 's/^VERSION_CODENAME=//p' /etc/os-release)"
|
||||
sudo install -d -m 0755 /etc/apt/keyrings
|
||||
curl -fsSL https://loonixtools.github.io/plasma-face-unlock/KEY.gpg \
|
||||
| sudo gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg
|
||||
echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] https://loonixtools.github.io/plasma-face-unlock/deb/$codename ./" \
|
||||
| sudo tee /etc/apt/sources.list.d/plasma-face-unlock.list
|
||||
sudo apt update && sudo apt install plasma-face-unlock
|
||||
curl -fsSL https://loonixtools.github.io/face-unlock/KEY.gpg \
|
||||
| sudo gpg --dearmor -o /etc/apt/keyrings/face-unlock.gpg
|
||||
echo "deb [signed-by=/etc/apt/keyrings/face-unlock.gpg] https://loonixtools.github.io/face-unlock/deb/$codename ./" \
|
||||
| sudo tee /etc/apt/sources.list.d/face-unlock.list
|
||||
sudo apt update && sudo apt install face-unlock
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -71,11 +71,11 @@ Needs Plasma 6 on Wayland and a camera. Updates come with your system updates.
|
||||
## How to use
|
||||
|
||||
```bash
|
||||
plasma-face-unlock
|
||||
face-unlock
|
||||
```
|
||||
|
||||
<p align="center">
|
||||
<img src="res/screenshots/menu.png" alt="The plasma-face-unlock menu in Konsole: face unlock on, one face, lock screen, sudo and admin prompts on" width="560">
|
||||
<img src="res/screenshots/menu.png" alt="The face-unlock menu in Konsole: face unlock on, one face, lock screen, sudo and admin prompts on" width="560">
|
||||
</p>
|
||||
|
||||
Press **1** and look at the camera. Then lock the screen and look at it.
|
||||
@@ -109,13 +109,13 @@ A convenience, not extra security. A webcam only sees a flat picture.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| `plasma-face-unlockd` | The root service. Owns the camera and the face data. |
|
||||
| `plasma-face-unlock-agent` | Runs in your session. Watches the lock screen, draws the bubble. |
|
||||
| `pam_plasma_face_unlock.so` | Lets sudo and admin prompts ask the service. |
|
||||
| `plasma-face-unlock` | The menu. |
|
||||
| `face-unlockd` | The root service. Owns the camera and the face data. |
|
||||
| `face-unlock-agent` | Runs in your session. Watches the lock screen, draws the bubble. |
|
||||
| `pam_face_unlock.so` | Lets sudo and admin prompts ask the service. |
|
||||
| `face-unlock` | The menu. |
|
||||
|
||||
Two small networks from the OpenCV model zoo run on the CPU: YuNet finds the face, SFace turns it
|
||||
into numbers. All details: `man plasma-face-unlock`.
|
||||
into numbers. All details: `man face-unlock`.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
plasma-face-unlock(1)
|
||||
face-unlock(1)
|
||||
|
||||
# NAME
|
||||
|
||||
plasma-face-unlock - face unlock for KDE Plasma
|
||||
face-unlock - face unlock for KDE Plasma
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
*plasma-face-unlock* [_command_]
|
||||
*face-unlock* [_command_]
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
@@ -64,23 +64,23 @@ It is a convenience, not a security upgrade. See *HOW SAFE IS THIS*.
|
||||
|
||||
# THE PIECES
|
||||
|
||||
*plasma-face-unlockd*
|
||||
*face-unlockd*
|
||||
The daemon, running as root and started by its socket
|
||||
(_plasma-face-unlockd.socket_). It is the only thing that opens the camera
|
||||
(_face-unlockd.socket_). It is the only thing that opens the camera
|
||||
and the only thing that can read the face data. It exits after a minute
|
||||
with nothing to do.
|
||||
|
||||
*plasma-face-unlock-agent*
|
||||
*face-unlock-agent*
|
||||
Runs in the Plasma session as a user service
|
||||
(_plasma-face-unlock-agent.service_). It watches the lock screen, asks the
|
||||
(_face-unlock-agent.service_). It watches the lock screen, asks the
|
||||
daemon to scan when somebody comes back, unlocks the session when the face
|
||||
matches, draws the bubble, and is the setup window.
|
||||
|
||||
*pam_plasma_face_unlock.so*
|
||||
*pam_face_unlock.so*
|
||||
The PAM module for sudo and admin prompts. It asks the daemon and turns
|
||||
the answer into a PAM result.
|
||||
|
||||
*plasma-face-unlock-ctl*
|
||||
*face-unlock-ctl*
|
||||
How this command talks to the daemon.
|
||||
|
||||
# RECOGNITION
|
||||
@@ -196,14 +196,14 @@ never lock the account.
|
||||
The bubble is a layer-shell surface that KWin keeps above the lock screen
|
||||
(kde_lockscreen_overlay_v1). KWin only allows that for a program whose desktop
|
||||
file asks for it, which is
|
||||
_io.github.loonixtools.plasma-face-unlock-agent.desktop_.
|
||||
_io.github.loonixtools.face-unlock-agent.desktop_.
|
||||
|
||||
# SUDO AND ADMIN PROMPTS
|
||||
|
||||
Turned on under *Settings*, one line goes in front of the service's PAM stack:
|
||||
|
||||
```
|
||||
-auth sufficient /usr/lib/security/pam_plasma_face_unlock.so
|
||||
-auth sufficient /usr/lib/security/pam_face_unlock.so
|
||||
```
|
||||
|
||||
A match lets the person in; anything else falls through to the password as if
|
||||
@@ -232,27 +232,27 @@ A laptop with its lid shut is not scanned (*Not when the lid is closed*).
|
||||
|
||||
# FILES
|
||||
|
||||
_~/.config/plasma-face-unlock/config_
|
||||
_~/.config/face-unlock/config_
|
||||
This user's settings: the lock screen, the bubble and its animation
|
||||
speed. Written by the menu.
|
||||
|
||||
_/etc/plasma-face-unlock/config_
|
||||
_/etc/face-unlock/config_
|
||||
The system settings: camera, photo check, strictness, attention, scan
|
||||
length. Written by the menu through sudo.
|
||||
|
||||
_/var/lib/plasma-face-unlock/users/<uid>.json_
|
||||
_/var/lib/face-unlock/users/<uid>.json_
|
||||
The face data: numbers, no pictures. Root only.
|
||||
|
||||
_/var/lib/plasma-face-unlock/users/<uid>.state_
|
||||
_/var/lib/face-unlock/users/<uid>.state_
|
||||
Failed scans in a row, the pause they lead to, the last unlock.
|
||||
|
||||
_/usr/share/plasma-face-unlock/models/_
|
||||
_/usr/share/face-unlock/models/_
|
||||
The two networks.
|
||||
|
||||
_/run/plasma-face-unlock/socket_
|
||||
_/run/face-unlock/socket_
|
||||
The daemon's socket.
|
||||
|
||||
_$XDG_RUNTIME_DIR/plasma-face-unlock/agent.socket_
|
||||
_$XDG_RUNTIME_DIR/face-unlock/agent.socket_
|
||||
Where the daemon tells the agent about scans it did not start, for the
|
||||
bubble.
|
||||
|
||||
@@ -273,7 +273,7 @@ Qt 6, LayerShellQt, KI18n, systemd, polkit and Linux-PAM.
|
||||
# AUTHORS
|
||||
|
||||
Felitendo. Source and issue tracker at
|
||||
https://github.com/LoonixTools/plasma-face-unlock
|
||||
https://github.com/LoonixTools/face-unlock
|
||||
|
||||
The liveness model and the look of the bubble follow Glance by Jonathan Zhou
|
||||
(https://github.com/jonnyoo/glance, MIT). The models are YuNet and SFace from
|
||||
+6
-6
@@ -7,13 +7,13 @@ description of the layout, and two descriptions drift.
|
||||
| | |
|
||||
|---|---|
|
||||
| `deb/control`, `deb/copyright` | metadata for the Debian binary package |
|
||||
| `rpm/plasma-face-unlock.spec` | the RPM spec |
|
||||
| `rpm/face-unlock.spec` | the RPM spec |
|
||||
| `build-deb.sh`, `build-rpm.sh` | build one package into `dist/` |
|
||||
| `check-version.sh` | refuses a tag that disagrees with the Makefile |
|
||||
| `publish-repos.sh` | regenerates the APT and RPM repositories |
|
||||
| `pages/` | the landing page and the `.repo` file served from GitHub Pages |
|
||||
|
||||
The AUR package lives in [Felitendo/PKGBUILDS](https://github.com/Felitendo/PKGBUILDS/tree/main/plasma-face-unlock).
|
||||
The AUR package lives in [Felitendo/PKGBUILDS](https://github.com/Felitendo/PKGBUILDS/tree/main/face-unlock).
|
||||
Its CI notices a new GitHub release, updates the checksum and pushes to the AUR.
|
||||
|
||||
Unlike the shell-only LoonixTools, this one is compiled. The packages are per
|
||||
@@ -34,7 +34,7 @@ checksums in the Makefile. The RPM spec and the PKGBUILD list them as sources
|
||||
of their own, with the same checksums.
|
||||
|
||||
Neither the deb nor the rpm switches anything on at install time. The daemon's
|
||||
socket is enabled by `plasma-face-unlock` the first time somebody turns it on,
|
||||
socket is enabled by `face-unlock` the first time somebody turns it on,
|
||||
the agent is a user service each user enables, and the PAM files are only
|
||||
touched when somebody asks for sudo or admin prompts. Removing a package
|
||||
disables the socket.
|
||||
@@ -52,7 +52,7 @@ argument.
|
||||
## Making a release
|
||||
|
||||
1. Bump `VERSION` in the Makefile. The compiled programs get it from there
|
||||
too (`-DPFU_VERSION`).
|
||||
too (`-DFU_VERSION`).
|
||||
2. Add the release to `CHANGELOG.md`, in the format CLAUDE.md describes.
|
||||
3. Commit, then `git tag vX.Y.Z && git push --tags`.
|
||||
|
||||
@@ -75,9 +75,9 @@ repositories. Nothing is pushed and no release is made.
|
||||
|
||||
```bash
|
||||
gpg --batch --passphrase '' --quick-generate-key \
|
||||
'plasma-face-unlock repository <felitendoyt@gmail.com>' rsa4096 sign never
|
||||
'face-unlock repository <felitendoyt@gmail.com>' rsa4096 sign never
|
||||
|
||||
gpg --armor --export-secret-keys 'plasma-face-unlock repository' \
|
||||
gpg --armor --export-secret-keys 'face-unlock repository' \
|
||||
| gh secret set GPG_PRIVATE_KEY
|
||||
```
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ version="${1:-$(make -s -C "$here" version)}"
|
||||
# The package depends on the exact Qt of the distribution it is built on, so
|
||||
# each one gets a build of its own, told apart by a suffix: ~deb13, ~ubuntu26.04.
|
||||
debversion="$version${DEB_SUFFIX:-}"
|
||||
name=plasma-face-unlock
|
||||
name=face-unlock
|
||||
|
||||
# A package without its man page or its translations is not a package this
|
||||
# should be quietly willing to produce.
|
||||
@@ -63,7 +63,7 @@ cat > "$root/DEBIAN/prerm" <<'SH'
|
||||
#!/bin/sh
|
||||
set -e
|
||||
if [ "$1" = remove ] && [ -d /run/systemd/system ]; then
|
||||
systemctl disable --now plasma-face-unlockd.socket plasma-face-unlockd.service >/dev/null 2>&1 || true
|
||||
systemctl disable --now face-unlockd.socket face-unlockd.service >/dev/null 2>&1 || true
|
||||
fi
|
||||
SH
|
||||
chmod 755 "$root/DEBIAN/prerm"
|
||||
|
||||
@@ -14,7 +14,7 @@ set -euo pipefail
|
||||
|
||||
here="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
version="${1:-$(make -s -C "$here" version)}"
|
||||
name=plasma-face-unlock
|
||||
name=face-unlock
|
||||
|
||||
command -v rpmbuild > /dev/null || { echo "$0: rpmbuild is not installed" >&2; exit 1; }
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Package: plasma-face-unlock
|
||||
Package: face-unlock
|
||||
Version: @VERSION@
|
||||
Section: admin
|
||||
Priority: optional
|
||||
@@ -6,7 +6,7 @@ Architecture: @ARCH@
|
||||
Maintainer: Felitendo <felitendoyt@gmail.com>
|
||||
Depends: @DEPENDS@, bash (>= 4.2), coreutils, grep, sed, mawk | gawk, systemd, polkitd | policykit-1, qml6-module-qtquick, qml6-module-qtquick-shapes, qml6-module-qtquick-effects, qml6-module-qtquick-window, qml6-module-qtqml-workerscript
|
||||
Recommends: gettext-base, kscreenlocker
|
||||
Homepage: https://github.com/LoonixTools/plasma-face-unlock
|
||||
Homepage: https://github.com/LoonixTools/face-unlock
|
||||
Description: face unlock for KDE Plasma
|
||||
Look at the screen and it unlocks, the way a phone does. The lock screen,
|
||||
sudo in a terminal and the admin password prompts of Plasma can take a face
|
||||
@@ -21,5 +21,5 @@ Description: face unlock for KDE Plasma
|
||||
through.
|
||||
.
|
||||
Everything runs on the machine. Faces are stored as numbers readable only by
|
||||
root, never as pictures. Run "plasma-face-unlock disable" before removing
|
||||
root, never as pictures. Run "face-unlock disable" before removing
|
||||
this package, so that sudo and polkit go back to the password alone.
|
||||
@@ -1,17 +1,17 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: plasma-face-unlock
|
||||
Source: https://github.com/LoonixTools/plasma-face-unlock
|
||||
Upstream-Name: face-unlock
|
||||
Source: https://github.com/LoonixTools/face-unlock
|
||||
|
||||
Files: *
|
||||
Copyright: 2026 Felitendo
|
||||
License: GPL-3+
|
||||
|
||||
Files: usr/share/plasma-face-unlock/models/face_detection_yunet_2023mar.onnx
|
||||
Files: usr/share/face-unlock/models/face_detection_yunet_2023mar.onnx
|
||||
Copyright: 2021-2023 Shiqi Yu, Wei Wu and the YuNet authors
|
||||
License: MIT
|
||||
Comment: https://github.com/opencv/opencv_zoo/tree/main/models/face_detection_yunet
|
||||
|
||||
Files: usr/share/plasma-face-unlock/models/face_recognition_sface_2021dec.onnx
|
||||
Files: usr/share/face-unlock/models/face_recognition_sface_2021dec.onnx
|
||||
Copyright: 2021 Yaoyao Zhong and Weihong Deng
|
||||
License: Apache-2.0
|
||||
Comment: https://github.com/opencv/opencv_zoo/tree/main/models/face_recognition_sface
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[plasma-face-unlock]
|
||||
name=plasma-face-unlock
|
||||
[face-unlock]
|
||||
name=face-unlock
|
||||
baseurl=@BASEURL@/rpm
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
+17
-17
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>plasma-face-unlock</title>
|
||||
<title>face-unlock</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #ffffff;
|
||||
@@ -62,7 +62,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>plasma-face-unlock</h1>
|
||||
<h1>face-unlock</h1>
|
||||
<p class="lead">
|
||||
Face ID for KDE Plasma: look at the screen and it unlocks. The lock screen,
|
||||
sudo and the admin prompts can take a face instead of a password, and a photo
|
||||
@@ -72,42 +72,42 @@
|
||||
<p>
|
||||
This page is the package repository. Set it up once and every new version
|
||||
arrives with the rest of your system updates. The
|
||||
<a href="https://github.com/LoonixTools/plasma-face-unlock">source and the
|
||||
<a href="https://github.com/LoonixTools/face-unlock">source and the
|
||||
documentation</a> are on GitHub.
|
||||
</p>
|
||||
|
||||
<h2>Debian 13</h2>
|
||||
<pre><code>sudo install -d -m 0755 /etc/apt/keyrings
|
||||
curl -fsSL @BASEURL@/KEY.gpg \
|
||||
| sudo gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg
|
||||
echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] @BASEURL@/deb/trixie ./" \
|
||||
| sudo tee /etc/apt/sources.list.d/plasma-face-unlock.list
|
||||
| sudo gpg --dearmor -o /etc/apt/keyrings/face-unlock.gpg
|
||||
echo "deb [signed-by=/etc/apt/keyrings/face-unlock.gpg] @BASEURL@/deb/trixie ./" \
|
||||
| sudo tee /etc/apt/sources.list.d/face-unlock.list
|
||||
sudo apt update
|
||||
sudo apt install plasma-face-unlock</code></pre>
|
||||
sudo apt install face-unlock</code></pre>
|
||||
|
||||
<h2>Kubuntu 26.04</h2>
|
||||
<pre><code>sudo install -d -m 0755 /etc/apt/keyrings
|
||||
curl -fsSL @BASEURL@/KEY.gpg \
|
||||
| sudo gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg
|
||||
echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] @BASEURL@/deb/resolute ./" \
|
||||
| sudo tee /etc/apt/sources.list.d/plasma-face-unlock.list
|
||||
| sudo gpg --dearmor -o /etc/apt/keyrings/face-unlock.gpg
|
||||
echo "deb [signed-by=/etc/apt/keyrings/face-unlock.gpg] @BASEURL@/deb/resolute ./" \
|
||||
| sudo tee /etc/apt/sources.list.d/face-unlock.list
|
||||
sudo apt update
|
||||
sudo apt install plasma-face-unlock</code></pre>
|
||||
sudo apt install face-unlock</code></pre>
|
||||
|
||||
<h2>Fedora 44 (KDE Plasma)</h2>
|
||||
<pre><code>sudo curl -fsSL -o /etc/yum.repos.d/plasma-face-unlock.repo \
|
||||
@BASEURL@/plasma-face-unlock.repo
|
||||
sudo dnf install plasma-face-unlock</code></pre>
|
||||
<pre><code>sudo curl -fsSL -o /etc/yum.repos.d/face-unlock.repo \
|
||||
@BASEURL@/face-unlock.repo
|
||||
sudo dnf install face-unlock</code></pre>
|
||||
|
||||
<h2>Arch, CachyOS, EndeavourOS, Manjaro</h2>
|
||||
<pre><code>paru -S plasma-face-unlock</code></pre>
|
||||
<pre><code>paru -S face-unlock</code></pre>
|
||||
|
||||
<h2>Then, once</h2>
|
||||
<pre><code>plasma-face-unlock</code></pre>
|
||||
<pre><code>face-unlock</code></pre>
|
||||
<p>
|
||||
Press 1. It sets up your face (look at the camera, move your head in a
|
||||
circle) and turns face unlock on. sudo and the admin prompts are off until
|
||||
you switch them on under Settings. Run <code>plasma-face-unlock disable</code>
|
||||
you switch them on under Settings. Run <code>face-unlock disable</code>
|
||||
before removing the package: it takes face unlock back out of sudo and
|
||||
polkit.
|
||||
</p>
|
||||
|
||||
@@ -19,7 +19,7 @@ pages="$(cd -- "$1" && pwd)"
|
||||
incoming="$(cd -- "$2" && pwd)"
|
||||
here="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
base_url="${PFU_REPO_URL:-https://loonixtools.github.io/plasma-face-unlock}"
|
||||
base_url="${FU_REPO_URL:-https://loonixtools.github.io/face-unlock}"
|
||||
|
||||
keyid="$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/ { print $5; exit }')"
|
||||
[[ -n $keyid ]] || { echo "$0: no secret key in the keyring" >&2; exit 1; }
|
||||
@@ -40,8 +40,8 @@ for suite in trixie:deb13 resolute:ubuntu26.04; do
|
||||
dpkg-scanpackages --multiversion . > Packages
|
||||
gzip -9kf Packages
|
||||
apt-ftparchive \
|
||||
-o APT::FTPArchive::Release::Origin=plasma-face-unlock \
|
||||
-o APT::FTPArchive::Release::Label=plasma-face-unlock \
|
||||
-o APT::FTPArchive::Release::Origin=face-unlock \
|
||||
-o APT::FTPArchive::Release::Label=face-unlock \
|
||||
-o APT::FTPArchive::Release::Suite="$codename" \
|
||||
-o APT::FTPArchive::Release::Codename="$codename" \
|
||||
-o APT::FTPArchive::Release::Architectures=amd64 \
|
||||
@@ -65,8 +65,8 @@ done
|
||||
gpg --armor --export "$keyid" > "$pages/KEY.gpg"
|
||||
|
||||
sed "s|@BASEURL@|$base_url|g" "$here/packaging/pages/index.html" > "$pages/index.html"
|
||||
sed "s|@BASEURL@|$base_url|g" "$here/packaging/pages/plasma-face-unlock.repo" \
|
||||
> "$pages/plasma-face-unlock.repo"
|
||||
sed "s|@BASEURL@|$base_url|g" "$here/packaging/pages/face-unlock.repo" \
|
||||
> "$pages/face-unlock.repo"
|
||||
|
||||
# Pages would otherwise hand the whole directory to Jekyll, which drops every
|
||||
# file whose name starts with an underscore and can rewrite the rest.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# editing this file: the Makefile is where the version is written down.
|
||||
%global upstream_version %{?_version}%{!?_version:1.0.1}
|
||||
|
||||
Name: plasma-face-unlock
|
||||
Name: face-unlock
|
||||
Version: %{upstream_version}
|
||||
Release: 1%{?dist}
|
||||
Summary: Face unlock for KDE Plasma
|
||||
@@ -10,7 +10,7 @@ Summary: Face unlock for KDE Plasma
|
||||
# The program is GPL; the two networks it ships are MIT (YuNet) and
|
||||
# Apache-2.0 (SFace).
|
||||
License: GPL-3.0-or-later AND MIT AND Apache-2.0
|
||||
URL: https://github.com/LoonixTools/plasma-face-unlock
|
||||
URL: https://github.com/LoonixTools/face-unlock
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
Source1: https://github.com/opencv/opencv_zoo/raw/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx
|
||||
Source2: https://github.com/opencv/opencv_zoo/raw/main/models/face_recognition_sface/face_recognition_sface_2021dec.onnx
|
||||
@@ -59,7 +59,7 @@ or the nose moving the way a real nose does when the head turns), which stops a
|
||||
printed photo too. It is a convenience, not a security upgrade: a webcam sees a
|
||||
flat picture, and a video of the person can get through.
|
||||
|
||||
Run "plasma-face-unlock disable" before removing this package, so that sudo
|
||||
Run "face-unlock disable" before removing this package, so that sudo
|
||||
and polkit go back to the password alone.
|
||||
|
||||
%prep
|
||||
@@ -78,10 +78,10 @@ make install DESTDIR=%{buildroot} PREFIX=%{_prefix} VERSION=%{upstream_version}
|
||||
%find_lang %{name}
|
||||
|
||||
%preun
|
||||
%systemd_preun plasma-face-unlockd.socket plasma-face-unlockd.service
|
||||
%systemd_preun face-unlockd.socket face-unlockd.service
|
||||
|
||||
%postun
|
||||
%systemd_postun plasma-face-unlockd.socket plasma-face-unlockd.service
|
||||
%systemd_postun face-unlockd.socket face-unlockd.service
|
||||
|
||||
%files -f %{name}.lang
|
||||
%license LICENSE
|
||||
@@ -89,13 +89,13 @@ make install DESTDIR=%{buildroot} PREFIX=%{_prefix} VERSION=%{upstream_version}
|
||||
%{_bindir}/%{name}
|
||||
%{_prefix}/lib/%{name}/
|
||||
%{_datadir}/%{name}/
|
||||
%{_libdir}/security/pam_plasma_face_unlock.so
|
||||
%{_unitdir}/plasma-face-unlockd.socket
|
||||
%{_unitdir}/plasma-face-unlockd.service
|
||||
%{_userunitdir}/plasma-face-unlock-agent.service
|
||||
%{_datadir}/applications/io.github.loonixtools.plasma-face-unlock-agent.desktop
|
||||
%{_datadir}/polkit-1/actions/io.github.loonixtools.plasma-face-unlock.policy
|
||||
%{_datadir}/icons/hicolor/scalable/apps/plasma-face-unlock.svg
|
||||
%{_libdir}/security/pam_face_unlock.so
|
||||
%{_unitdir}/face-unlockd.socket
|
||||
%{_unitdir}/face-unlockd.service
|
||||
%{_userunitdir}/face-unlock-agent.service
|
||||
%{_datadir}/applications/io.github.loonixtools.face-unlock-agent.desktop
|
||||
%{_datadir}/polkit-1/actions/io.github.loonixtools.face-unlock.policy
|
||||
%{_datadir}/icons/hicolor/scalable/apps/face-unlock.svg
|
||||
%{_mandir}/man1/%{name}.1*
|
||||
|
||||
%changelog
|
||||
@@ -1,11 +1,11 @@
|
||||
# German translation for plasma-face-unlock.
|
||||
# German translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/"
|
||||
"Project-Id-Version: face-unlock 1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/"
|
||||
"issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:46+0200\n"
|
||||
"PO-Revision-Date: 2026-09-23 22:32+0200\n"
|
||||
@@ -16,7 +16,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid ""
|
||||
"Face unlock's service has to be switched on once for this computer. That "
|
||||
"needs your password."
|
||||
@@ -24,12 +24,12 @@ msgstr ""
|
||||
"Der Dienst für die Gesichtsentsperrung muss auf diesem Computer einmal "
|
||||
"eingeschaltet werden. Dafür wird dein Passwort gebraucht."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "Prüfen mit: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid ""
|
||||
"Setting up a face needs the camera picture on screen. Run this inside your "
|
||||
"Plasma session."
|
||||
@@ -37,136 +37,136 @@ msgstr ""
|
||||
"Zum Einrichten eines Gesichts muss das Kamerabild auf dem Bildschirm zu "
|
||||
"sehen sein. Starte das in deiner Plasma-Sitzung."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "Das Einrichtungsfenster ist offen. Folge den Schritten dort."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "Das Gesicht ist eingerichtet."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr ""
|
||||
"Die Gesichtsentsperrung ist noch aus. Schalte sie mit [1] oder `%s enable` "
|
||||
"ein."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "Es wurde kein Gesicht hinzugefügt."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "Richte zuerst dein Gesicht ein."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "Einstellung konnte nicht gespeichert werden."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "Der Sperrbildschirm-Dienst konnte nicht gestartet werden."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr ""
|
||||
"Keine systemd-Benutzersitzung, daher wurde der Sperrbildschirm-Dienst nicht "
|
||||
"gestartet."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr ""
|
||||
"Die Gesichtsentsperrung ist an. Sperre den Bildschirm und schau ihn an, um "
|
||||
"es auszuprobieren."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "Sie kann auch sudo und Admin-Abfragen übernehmen. Siehe Einstellungen."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr ""
|
||||
"Die Gesichtsentsperrung ist aus. Deine Gesichter bleiben erhalten; löschen "
|
||||
"kannst du sie unter Gesichter."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "Es ist noch kein Gesicht eingerichtet."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "an"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "aus"
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "%s Aufnahmen, %s dazugelernt"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "Welches Gesicht? Die IDs zeigt `%s faces`."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "Gelöscht."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "Aufruf: plasma-face-unlock [Befehl]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "Aufruf: face-unlock [Befehl]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "Befehle:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "Gesichtsentsperrung einschalten"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "Ausschalten (Gesichter bleiben erhalten)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "Gesicht hinzufügen"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "Gesichter auflisten"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "Ein Gesicht löschen"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "In die Kamera schauen und sehen, was sie sieht"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "Anzeigen, was eingeschaltet ist"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "Diese Hilfe anzeigen"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "Die Version anzeigen"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "Ohne Befehl wird ein interaktives Menü angezeigt."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid ""
|
||||
"Run this as your own user, not as root. It asks for your password when it "
|
||||
"needs to."
|
||||
@@ -174,7 +174,7 @@ msgstr ""
|
||||
"Starte das als dein eigener Benutzer, nicht als root. Wenn nötig, wird nach "
|
||||
"deinem Passwort gefragt."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "Unbekannter Befehl: %s"
|
||||
@@ -880,21 +880,21 @@ msgstr "Die Animationen der Bubble einmal abspielen."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "Bubble-Stil für die Demo: full oder minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "Schau zum Entsperren in die Kamera."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "Blinzle oder dreh den Kopf ein wenig."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr ""
|
||||
"Die Gesichtsentsperrung ist nach zu vielen Versuchen pausiert. Nutze dein "
|
||||
"Passwort."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "Gesicht nicht erkannt."
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Spanish translation for plasma-face-unlock.
|
||||
# Spanish translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:55+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "El servicio de desbloqueo facial tiene que activarse una vez en este equipo. Para ello hace falta tu contraseña."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "Compruébalo con: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "Para configurar una cara, la imagen de la cámara tiene que verse en pantalla. Ejecuta esto dentro de tu sesión de Plasma."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "La ventana de configuración está abierta. Sigue los pasos allí."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "La cara está configurada."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "El desbloqueo facial sigue desactivado. Actívalo con [1] o `%s enable`."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "No se añadió ninguna cara."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "Primero, configura tu cara."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "No se pudo guardar el ajuste."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "No se pudo iniciar el agente de la pantalla de bloqueo."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "No hay sesión de usuario de systemd, así que no se inició el agente de la pantalla de bloqueo."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "El desbloqueo facial está activado. Bloquea la pantalla y mírala para probarlo."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "También funciona con sudo y las solicitudes de administrador. Consulta Ajustes."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "El desbloqueo facial está desactivado. Tus caras se conservan; bórralas en Caras."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "Todavía no hay ninguna cara configurada."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "activado"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "desactivado"
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "%s muestras, %s aprendidas"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "¿Qué cara? Consulta `%s faces` para ver los ID."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "Borrado."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "Uso: plasma-face-unlock [comando]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "Uso: face-unlock [comando]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "Comandos:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "Activar el desbloqueo facial"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "Desactivarlo (las caras se conservan)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "Añadir una cara"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "Listar las caras"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "Borrar una cara"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "Mirar a la cámara y ver lo que ve"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "Mostrar qué está activado"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "Mostrar esta ayuda"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "Mostrar la versión"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "Sin comando se muestra un menú interactivo."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "Ejecuta esto con tu propio usuario, no como root. Pide tu contraseña cuando la necesita."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "Comando desconocido: %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "Reproducir una vez las animaciones de la burbuja."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "Estilo de burbuja para la demo: full o minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "Mira a la cámara para desbloquear."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "Parpadea o gira un poco la cabeza."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "El desbloqueo facial está en pausa tras demasiados intentos. Usa tu contraseña."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "Cara no reconocida."
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Translation template for plasma-face-unlock.
|
||||
# Translation template for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/"
|
||||
"issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:56+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
@@ -17,151 +17,151 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid ""
|
||||
"Face unlock's service has to be switched on once for this computer. That "
|
||||
"needs your password."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid ""
|
||||
"Setting up a face needs the camera picture on screen. Run this inside your "
|
||||
"Plasma session."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid ""
|
||||
"Run this as your own user, not as root. It asks for your password when it "
|
||||
"needs to."
|
||||
msgstr ""
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr ""
|
||||
@@ -828,19 +828,19 @@ msgstr ""
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr ""
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr ""
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr ""
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr ""
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr ""
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# French translation for plasma-face-unlock.
|
||||
# French translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:55+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "Le service de déverrouillage facial doit être activé une fois sur cet ordinateur. Cela demande votre mot de passe."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "Vérifiez avec : systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "Pour configurer un visage, l'image de la caméra doit s'afficher à l'écran. Lancez ceci dans votre session Plasma."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "La fenêtre de configuration est ouverte. Suivez les étapes qui s'y trouvent."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "Le visage est configuré."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "Le déverrouillage facial est encore désactivé. Activez-le avec [1] ou `%s enable`."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "Aucun visage n'a été ajouté."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "Configurez d'abord votre visage."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "Impossible d'enregistrer le réglage."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "Impossible de démarrer l'agent de l'écran de verrouillage."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "Pas de session utilisateur systemd, l'agent de l'écran de verrouillage n'a donc pas été démarré."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "Le déverrouillage facial est activé. Verrouillez l'écran et regardez-le pour essayer."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "Il fonctionne aussi pour sudo et les demandes d'administration. Voir Réglages."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "Le déverrouillage facial est désactivé. Vos visages sont conservés ; supprimez-les dans Visages."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "Aucun visage n'est encore configuré."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "activé"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "désactivé"
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "%s échantillons, %s appris"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "Quel visage ? Voir `%s faces` pour les identifiants."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "Supprimé."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "Utilisation : plasma-face-unlock [commande]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "Utilisation : face-unlock [commande]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "Commandes :"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "Activer le déverrouillage facial"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "Le désactiver (les visages sont conservés)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "Ajouter un visage"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "Lister les visages"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "Supprimer un visage"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "Regarder la caméra et voir ce qu'elle voit"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "Afficher ce qui est activé"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "Afficher cette aide"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "Afficher la version"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "Sans commande, un menu interactif s'affiche."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "Lancez ceci avec votre propre utilisateur, pas en root. Le mot de passe est demandé quand il le faut."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "Commande inconnue : %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "Jouer une fois les animations de la bulle."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "Style de bulle pour la démo : full ou minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "Regardez la caméra pour déverrouiller."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "Clignez des yeux ou tournez un peu la tête."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "Le déverrouillage facial est en pause après trop d'essais. Utilisez votre mot de passe."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "Visage non reconnu."
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Italian translation for plasma-face-unlock.
|
||||
# Italian translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:55+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "Il servizio di sblocco con il volto va attivato una volta su questo computer. Serve la tua password."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "Controlla con: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "Per configurare un volto, l'immagine della fotocamera deve comparire sullo schermo. Esegui questo comando nella tua sessione Plasma."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "La finestra di configurazione è aperta. Segui i passaggi lì."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "Il volto è configurato."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "Lo sblocco con il volto è ancora disattivato. Attivalo con [1] o `%s enable`."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "Nessun volto aggiunto."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "Per prima cosa, configura il tuo volto."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "Impossibile salvare l'impostazione."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "Impossibile avviare l'agente della schermata di blocco."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "Nessuna sessione utente di systemd, quindi l'agente della schermata di blocco non è stato avviato."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "Lo sblocco con il volto è attivo. Blocca lo schermo e guardalo per provarlo."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "Funziona anche con sudo e le richieste di amministratore. Vedi Impostazioni."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "Lo sblocco con il volto è disattivato. I tuoi volti restano salvati; eliminali in Volti."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "Nessun volto ancora configurato."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "attivo"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "disattivo"
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "%s campioni, %s appresi"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "Quale volto? Vedi `%s faces` per gli ID."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "Eliminato."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "Uso: plasma-face-unlock [comando]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "Uso: face-unlock [comando]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "Comandi:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "Attiva lo sblocco con il volto"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "Disattivalo (i volti restano salvati)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "Aggiungi un volto"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "Elenca i volti"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "Elimina un volto"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "Guarda la fotocamera e vedi cosa vede"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "Mostra cosa è attivo"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "Mostra questo aiuto"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "Mostra la versione"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "Senza comando viene mostrato un menu interattivo."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "Esegui questo con il tuo utente, non come root. Chiede la password quando serve."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "Comando sconosciuto: %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "Riproduci una volta le animazioni della bolla."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "Stile della bolla per la demo: full o minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "Guarda la fotocamera per sbloccare."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "Sbatti le palpebre o gira un po' la testa."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "Lo sblocco con il volto è in pausa dopo troppi tentativi. Usa la tua password."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "Volto non riconosciuto."
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Japanese translation for plasma-face-unlock.
|
||||
# Japanese translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:46+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "顔認証のサービスを、このコンピューターで一度オンにする必要があります。パスワードが必要です。"
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "確認するには: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "顔を登録するには、カメラの映像を画面に表示する必要があります。Plasma セッションの中で実行してください。"
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "登録ウィンドウが開いています。そちらの手順に従ってください。"
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "顔を登録しました。"
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "顔認証はまだオフです。[1] または `%s enable` でオンにしてください。"
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "顔は追加されませんでした。"
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "まず顔を登録してください。"
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "設定を保存できませんでした。"
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "ロック画面エージェントを起動できませんでした。"
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "systemd のユーザーセッションがないため、ロック画面エージェントは起動されませんでした。"
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "顔認証はオンです。画面をロックして、画面を見て試してください。"
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "sudo や管理者の認証にも使えます。「設定」を参照してください。"
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "顔認証はオフです。顔データは残っています。「顔」から削除できます。"
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "まだ顔が登録されていません。"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "オン"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "オフ"
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "サンプル %s 件、学習 %s 件"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "どの顔ですか? ID は `%s faces` で確認できます。"
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "削除しました。"
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "使い方: plasma-face-unlock [コマンド]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "使い方: face-unlock [コマンド]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "コマンド:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "顔認証をオンにする"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "オフにする(顔データは残ります)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "顔を追加"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "顔の一覧"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "顔を削除"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "カメラを見て、カメラに映るものを確認する"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "オンになっている機能を表示"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "このヘルプを表示"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "バージョンを表示"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "コマンドなしで起動すると、対話式メニューが表示されます。"
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "root ではなく、自分のユーザーで実行してください。必要なときはパスワードを尋ねます。"
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "不明なコマンド: %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "バブルのアニメーションを一度再生します。"
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "デモのバブルスタイル: full または minimal。"
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "カメラを見てロックを解除してください。"
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "まばたきするか、少し顔を動かしてください。"
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "試行回数が多すぎるため、顔認証を一時停止しています。パスワードを使ってください。"
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "顔を認識できませんでした。"
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Korean translation for plasma-face-unlock.
|
||||
# Korean translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:46+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "얼굴 잠금 해제 서비스를 이 컴퓨터에서 한 번 켜야 합니다. 이때 비밀번호가 필요합니다."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "확인 방법: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "얼굴을 등록하려면 카메라 화면이 보여야 합니다. Plasma 세션 안에서 실행하세요."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "등록 창이 열려 있습니다. 창의 안내를 따르세요."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "얼굴이 등록되었습니다."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "얼굴 잠금 해제가 아직 꺼져 있습니다. [1] 또는 `%s enable`로 켜세요."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "얼굴이 추가되지 않았습니다."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "먼저 얼굴을 등록하세요."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "설정을 저장하지 못했습니다."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "잠금 화면 에이전트를 시작하지 못했습니다."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "systemd 사용자 세션이 없어 잠금 화면 에이전트를 시작하지 않았습니다."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "얼굴 잠금 해제가 켜졌습니다. 화면을 잠그고 화면을 바라보며 사용해 보세요."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "sudo와 관리자 인증 창에서도 쓸 수 있습니다. 설정을 참고하세요."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "얼굴 잠금 해제가 꺼졌습니다. 얼굴 데이터는 남아 있으며, 얼굴 메뉴에서 삭제할 수 있습니다."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "아직 등록된 얼굴이 없습니다."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "켜짐"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "꺼짐"
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "샘플 %s개, 학습 %s개"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "어떤 얼굴인가요? ID는 `%s faces`에서 확인하세요."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "삭제했습니다."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "사용법: plasma-face-unlock [명령]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "사용법: face-unlock [명령]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "명령:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "얼굴 잠금 해제 켜기"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "끄기 (얼굴 데이터는 유지)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "얼굴 추가"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "얼굴 목록"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "얼굴 삭제"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "카메라를 보고 카메라에 보이는 것을 확인"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "켜져 있는 기능 보기"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "이 도움말 보기"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "버전 보기"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "명령 없이 실행하면 대화형 메뉴가 나옵니다."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "root가 아닌 본인 사용자로 실행하세요. 필요하면 비밀번호를 묻습니다."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "알 수 없는 명령: %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "버블 애니메이션을 한 번 재생합니다."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "데모용 버블 스타일: full 또는 minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "잠금을 해제하려면 카메라를 보세요."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "눈을 깜빡이거나 고개를 살짝 돌리세요."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "시도가 너무 많아 얼굴 잠금 해제가 일시 중지되었습니다. 비밀번호를 사용하세요."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "얼굴을 인식하지 못했습니다."
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Dutch translation for plasma-face-unlock.
|
||||
# Dutch translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:46+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "De dienst voor gezichtsontgrendeling moet één keer op deze computer worden ingeschakeld. Daarvoor is je wachtwoord nodig."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "Controleer met: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "Voor het instellen van een gezicht moet het camerabeeld op het scherm staan. Voer dit uit in je Plasma-sessie."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "Het instelvenster is open. Volg daar de stappen."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "Het gezicht is ingesteld."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "Gezichtsontgrendeling staat nog uit. Zet het aan met [1] of `%s enable`."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "Er is geen gezicht toegevoegd."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "Stel eerst je gezicht in."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "Kon de instelling niet opslaan."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "Kon de agent voor het vergrendelscherm niet starten."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "Geen systemd-gebruikerssessie, dus de agent voor het vergrendelscherm is niet gestart."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "Gezichtsontgrendeling staat aan. Vergrendel het scherm en kijk ernaar om het te proberen."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "Het werkt ook voor sudo en beheerdersvragen. Zie Instellingen."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "Gezichtsontgrendeling staat uit. Je gezichten blijven bewaard; verwijder ze onder Gezichten."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "Er is nog geen gezicht ingesteld."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "aan"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "uit"
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "%s opnames, %s bijgeleerd"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "Welk gezicht? Zie `%s faces` voor de ID's."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "Verwijderd."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "Gebruik: plasma-face-unlock [opdracht]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "Gebruik: face-unlock [opdracht]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "Opdrachten:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "Gezichtsontgrendeling aanzetten"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "Uitzetten (gezichten blijven bewaard)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "Een gezicht toevoegen"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "De gezichten tonen"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "Een gezicht verwijderen"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "In de camera kijken en zien wat hij ziet"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "Tonen wat er aan staat"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "Deze hulp tonen"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "De versie tonen"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "Zonder opdracht verschijnt een interactief menu."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "Voer dit uit als je eigen gebruiker, niet als root. Het vraagt om je wachtwoord als dat nodig is."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "Onbekende opdracht: %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "De animaties van de bubbel één keer afspelen."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "Bubbelstijl voor de demo: full of minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "Kijk in de camera om te ontgrendelen."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "Knipper, of draai je hoofd een beetje."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "Gezichtsontgrendeling is gepauzeerd na te veel pogingen. Gebruik je wachtwoord."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "Gezicht niet herkend."
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Polish translation for plasma-face-unlock.
|
||||
# Polish translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:46+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "Usługę odblokowywania twarzą trzeba raz włączyć na tym komputerze. Potrzebne jest do tego twoje hasło."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "Sprawdź poleceniem: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "Do skonfigurowania twarzy obraz z kamery musi być widoczny na ekranie. Uruchom to w swojej sesji Plasmy."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "Okno konfiguracji jest otwarte. Postępuj zgodnie z nim."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "Twarz jest skonfigurowana."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "Odblokowywanie twarzą jest nadal wyłączone. Włącz je przez [1] lub `%s enable`."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "Nie dodano żadnej twarzy."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "Najpierw skonfiguruj swoją twarz."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "Nie udało się zapisać ustawienia."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "Nie udało się uruchomić agenta ekranu blokady."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "Brak sesji użytkownika systemd, więc agent ekranu blokady nie został uruchomiony."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "Odblokowywanie twarzą jest włączone. Zablokuj ekran i spójrz na niego, aby wypróbować."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "Działa też dla sudo i okien administratora. Zobacz Ustawienia."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "Odblokowywanie twarzą jest wyłączone. Twoje twarze zostają zachowane; usuniesz je w Twarzach."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "Nie skonfigurowano jeszcze żadnej twarzy."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "wł."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "wył."
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "próbki: %s, wyuczone: %s"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "Która twarz? Identyfikatory pokazuje `%s faces`."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "Usunięto."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "Użycie: plasma-face-unlock [polecenie]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "Użycie: face-unlock [polecenie]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "Polecenia:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "Włącz odblokowywanie twarzą"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "Wyłącz je (twarze zostają zachowane)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "Dodaj twarz"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "Pokaż listę twarzy"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "Usuń twarz"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "Spójrz w kamerę i zobacz, co widzi"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "Pokaż, co jest włączone"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "Pokaż tę pomoc"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "Pokaż wersję"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "Bez polecenia wyświetla się interaktywne menu."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "Uruchom to jako swój użytkownik, nie jako root. Hasło zostanie zapytane, gdy będzie potrzebne."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "Nieznane polecenie: %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "Odtwórz raz animacje dymka."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "Styl dymka w demo: full lub minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "Spójrz w kamerę, aby odblokować."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "Mrugnij albo lekko obróć głowę."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "Odblokowywanie twarzą jest wstrzymane po zbyt wielu próbach. Użyj hasła."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "Nie rozpoznano twarzy."
|
||||
|
||||
|
||||
+44
-44
@@ -1,11 +1,11 @@
|
||||
# Brazilian Portuguese translation for plasma-face-unlock.
|
||||
# Brazilian Portuguese translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:55+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "O serviço de desbloqueio facial precisa ser ativado uma vez neste computador. Para isso, é preciso a sua senha."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "Verifique com: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "Para configurar um rosto, a imagem da câmera precisa aparecer na tela. Execute isto dentro da sua sessão do Plasma."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "A janela de configuração está aberta. Siga os passos nela."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "O rosto está configurado."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "O desbloqueio facial ainda está desativado. Ative com [1] ou `%s enable`."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "Nenhum rosto foi adicionado."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "Primeiro, configure o seu rosto."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "Não foi possível salvar a configuração."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "Não foi possível iniciar o agente da tela de bloqueio."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "Sem sessão de usuário do systemd, então o agente da tela de bloqueio não foi iniciado."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "O desbloqueio facial está ativado. Bloqueie a tela e olhe para ela para testar."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "Ele também funciona com sudo e pedidos de administrador. Veja Configurações."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "O desbloqueio facial está desativado. Seus rostos são mantidos; apague-os em Rostos."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "Nenhum rosto configurado ainda."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "ativado"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "desativado"
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "%s amostras, %s aprendidas"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "Qual rosto? Veja `%s faces` para os IDs."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "Apagado."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "Uso: plasma-face-unlock [comando]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "Uso: face-unlock [comando]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "Comandos:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "Ativar o desbloqueio facial"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "Desativar (os rostos são mantidos)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "Adicionar um rosto"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "Listar os rostos"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "Apagar um rosto"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "Olhar para a câmera e ver o que ela vê"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "Mostrar o que está ativado"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "Mostrar esta ajuda"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "Mostrar a versão"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "Sem comando, um menu interativo é exibido."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "Execute isto com o seu próprio usuário, não como root. Ele pede a sua senha quando precisa."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "Comando desconhecido: %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "Reproduzir as animações da bolha uma vez."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "Estilo da bolha para a demonstração: full ou minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "Olhe para a câmera para desbloquear."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "Pisque ou vire um pouco a cabeça."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "O desbloqueio facial está pausado após tentativas demais. Use a sua senha."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "Rosto não reconhecido."
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Russian translation for plasma-face-unlock.
|
||||
# Russian translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:46+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "Службу разблокировки по лицу нужно один раз включить на этом компьютере. Для этого нужен ваш пароль."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "Проверьте командой: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "Для настройки лица изображение с камеры должно быть видно на экране. Запустите это в своём сеансе Plasma."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "Окно настройки открыто. Следуйте шагам в нём."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "Лицо настроено."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "Разблокировка по лицу всё ещё выключена. Включите её через [1] или `%s enable`."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "Лицо не добавлено."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "Сначала настройте своё лицо."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "Не удалось сохранить настройку."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "Не удалось запустить агент экрана блокировки."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "Нет пользовательского сеанса systemd, поэтому агент экрана блокировки не запущен."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "Разблокировка по лицу включена. Заблокируйте экран и посмотрите на него, чтобы попробовать."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "Она работает и для sudo, и для запросов администратора. См. Настройки."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "Разблокировка по лицу выключена. Ваши лица сохранены; удалить их можно в разделе Лица."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "Ещё не настроено ни одного лица."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "вкл."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "выкл."
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "образцов: %s, выучено: %s"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "Какое лицо? Номера показывает `%s faces`."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "Удалено."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "Использование: plasma-face-unlock [команда]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "Использование: face-unlock [команда]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "Команды:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "Включить разблокировку по лицу"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "Выключить её (лица сохраняются)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "Добавить лицо"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "Показать список лиц"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "Удалить лицо"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "Посмотреть в камеру и увидеть, что она видит"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "Показать, что включено"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "Показать эту справку"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "Показать версию"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "Без команды открывается интерактивное меню."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "Запускайте это от своего пользователя, не от root. Пароль будет запрошен, когда он понадобится."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "Неизвестная команда: %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "Один раз проиграть анимации пузыря."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "Стиль пузыря для демо: full или minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "Посмотрите в камеру, чтобы разблокировать."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "Моргните или слегка поверните голову."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "Разблокировка по лицу приостановлена после слишком многих попыток. Введите пароль."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "Лицо не распознано."
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Turkish translation for plasma-face-unlock.
|
||||
# Turkish translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:46+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "Yüzle kilit açma hizmetinin bu bilgisayarda bir kez açılması gerekiyor. Bunun için parolanız gerekli."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "Şununla kontrol edin: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "Yüz kurmak için kamera görüntüsünün ekranda görünmesi gerekir. Bunu Plasma oturumunuzda çalıştırın."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "Kurulum penceresi açık. Oradaki adımları izleyin."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "Yüz kuruldu."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "Yüzle kilit açma hâlâ kapalı. [1] ya da `%s enable` ile açın."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "Hiç yüz eklenmedi."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "Önce yüzünüzü kurun."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "Ayar kaydedilemedi."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "Kilit ekranı aracısı başlatılamadı."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "systemd kullanıcı oturumu yok, bu yüzden kilit ekranı aracısı başlatılmadı."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "Yüzle kilit açma açık. Denemek için ekranı kilitleyin ve ona bakın."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "sudo ve yönetici istemlerinde de çalışabilir. Ayarlar'a bakın."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "Yüzle kilit açma kapalı. Yüzleriniz saklanıyor; Yüzler bölümünden silebilirsiniz."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "Henüz hiç yüz kurulmadı."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "açık"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "kapalı"
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "%s örnek, %s öğrenilen"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "Hangi yüz? Kimlikler için `%s faces` komutuna bakın."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "Silindi."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "Kullanım: plasma-face-unlock [komut]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "Kullanım: face-unlock [komut]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "Komutlar:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "Yüzle kilit açmayı aç"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "Kapat (yüzler saklanır)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "Yüz ekle"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "Yüzleri listele"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "Bir yüzü sil"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "Kameraya bak ve onun ne gördüğünü gör"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "Neyin açık olduğunu göster"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "Bu yardımı göster"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "Sürümü göster"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "Komut verilmezse etkileşimli bir menü gösterilir."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "Bunu root olarak değil, kendi kullanıcınızla çalıştırın. Gerektiğinde parolanızı sorar."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "Bilinmeyen komut: %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "Baloncuğun animasyonlarını bir kez oynat."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "Demo için baloncuk stili: full ya da minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "Kilidi açmak için kameraya bakın."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "Göz kırpın ya da başınızı biraz çevirin."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "Çok fazla denemeden sonra yüzle kilit açma duraklatıldı. Parolanızı kullanın."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "Yüz tanınmadı."
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Ukrainian translation for plasma-face-unlock.
|
||||
# Ukrainian translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:46+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "Службу розблокування обличчям треба один раз увімкнути на цьому комп'ютері. Для цього потрібен ваш пароль."
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "Перевірте командою: systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "Для налаштування обличчя зображення з камери має бути видно на екрані. Запустіть це у своєму сеансі Plasma."
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "Вікно налаштування відкрито. Виконайте кроки в ньому."
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "Обличчя налаштовано."
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "Розблокування обличчям досі вимкнено. Увімкніть його через [1] або `%s enable`."
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "Обличчя не додано."
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "Спершу налаштуйте своє обличчя."
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "Не вдалося зберегти налаштування."
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "Не вдалося запустити агент екрана блокування."
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "Немає користувацького сеансу systemd, тому агент екрана блокування не запущено."
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "Розблокування обличчям увімкнено. Заблокуйте екран і подивіться на нього, щоб спробувати."
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "Воно працює і для sudo, і для запитів адміністратора. Див. Налаштування."
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "Розблокування обличчям вимкнено. Ваші обличчя збережено; видалити їх можна в розділі Обличчя."
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "Ще не налаштовано жодного обличчя."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "увімк."
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "вимк."
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "зразків: %s, вивчено: %s"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "Яке обличчя? Номери показує `%s faces`."
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "Видалено."
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "Використання: plasma-face-unlock [команда]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "Використання: face-unlock [команда]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "Команди:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "Увімкнути розблокування обличчям"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "Вимкнути його (обличчя зберігаються)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "Додати обличчя"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "Показати список облич"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "Видалити обличчя"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "Подивитися в камеру і побачити, що вона бачить"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "Показати, що увімкнено"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "Показати цю довідку"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "Показати версію"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "Без команди відкривається інтерактивне меню."
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "Запускайте це від свого користувача, не від root. Пароль буде запитано, коли він знадобиться."
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "Невідома команда: %s"
|
||||
@@ -795,19 +795,19 @@ msgstr "Один раз програти анімації бульбашки."
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "Стиль бульбашки для демо: full або minimal."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "Подивіться в камеру, щоб розблокувати."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "Кліпніть або трохи поверніть голову."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "Розблокування обличчям призупинено після надто багатьох спроб. Введіть пароль."
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "Обличчя не розпізнано."
|
||||
|
||||
|
||||
+13
-13
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Collects every translatable string into po/plasma-face-unlock.pot and brings
|
||||
# Collects every translatable string into po/face-unlock.pot and brings
|
||||
# the translations up to date with it. One catalog serves all four parts:
|
||||
# the shell code (pfu_msg), the agent (i18n in C++ and QML) and the PAM module
|
||||
# the shell code (fu_msg), the agent (i18n in C++ and QML) and the PAM module
|
||||
# (dgettext), so a word is translated once wherever it shows up.
|
||||
#
|
||||
# The settings labels and headings live in an array in menu.sh and reach
|
||||
@@ -18,23 +18,23 @@ trap 'rm -rf -- "$tmp"' EXIT
|
||||
version="$(make -s version)"
|
||||
|
||||
# The labels, as calls xgettext understands, pointing back at menu.sh.
|
||||
awk -F'|' '/^\t"(user|sys|pam)\|/ { sub(/"$/, "", $5); print "pfu_msg \"" $5 "\"" }
|
||||
/^\t"group\|/ { sub(/"$/, "", $2); print "pfu_msg \"" $2 "\"" }' src/lib/menu.sh > "$tmp/settings.sh"
|
||||
awk -F'|' '/^\t"(user|sys|pam)\|/ { sub(/"$/, "", $5); print "fu_msg \"" $5 "\"" }
|
||||
/^\t"group\|/ { sub(/"$/, "", $2); print "fu_msg \"" $2 "\"" }' src/lib/menu.sh > "$tmp/settings.sh"
|
||||
|
||||
common=(--from-code=UTF-8 --add-comments=TRANSLATORS --package-name=plasma-face-unlock --package-version="$version"
|
||||
--msgid-bugs-address=https://github.com/LoonixTools/plasma-face-unlock/issues)
|
||||
common=(--from-code=UTF-8 --add-comments=TRANSLATORS --package-name=face-unlock --package-version="$version"
|
||||
--msgid-bugs-address=https://github.com/LoonixTools/face-unlock/issues)
|
||||
|
||||
xgettext "${common[@]}" -L Shell -k --keyword=pfu_msg --keyword=pfu_msg_into:2 --keyword=pfu_msg_in:2 \
|
||||
-o "$tmp/shell.pot" src/plasma-face-unlock src/lib/*.sh "$tmp/settings.sh"
|
||||
xgettext "${common[@]}" -L Shell -k --keyword=fu_msg --keyword=fu_msg_into:2 --keyword=fu_msg_in:2 \
|
||||
-o "$tmp/shell.pot" src/face-unlock src/lib/*.sh "$tmp/settings.sh"
|
||||
sed -i "s|$tmp/settings.sh:[0-9]*|src/lib/menu.sh|g" "$tmp/shell.pot"
|
||||
xgettext "${common[@]}" -L C++ --keyword=i18n --keyword=_ -o "$tmp/native.pot" src/agent/*.cpp src/pam/*.c
|
||||
xgettext "${common[@]}" -L JavaScript --keyword=i18n -o "$tmp/qml.pot" src/agent/qml/*.qml
|
||||
|
||||
msgcat --use-first -o po/plasma-face-unlock.pot "$tmp/shell.pot" "$tmp/native.pot" "$tmp/qml.pot"
|
||||
sed -i -e '1i # Translation template for plasma-face-unlock.\n# Copyright (C) 2026 Felitendo\n# This file is distributed under the same license as plasma-face-unlock.' -e '1,4d' \
|
||||
po/plasma-face-unlock.pot
|
||||
msgcat --use-first -o po/face-unlock.pot "$tmp/shell.pot" "$tmp/native.pot" "$tmp/qml.pot"
|
||||
sed -i -e '1i # Translation template for face-unlock.\n# Copyright (C) 2026 Felitendo\n# This file is distributed under the same license as face-unlock.' -e '1,4d' \
|
||||
po/face-unlock.pot
|
||||
|
||||
for po in po/*.po; do
|
||||
msgmerge --quiet --update --backup=none --no-fuzzy-matching "$po" po/plasma-face-unlock.pot
|
||||
msgmerge --quiet --update --backup=none --no-fuzzy-matching "$po" po/face-unlock.pot
|
||||
done
|
||||
echo "po/plasma-face-unlock.pot: $(grep -c '^msgid' po/plasma-face-unlock.pot) strings"
|
||||
echo "po/face-unlock.pot: $(grep -c '^msgid' po/face-unlock.pot) strings"
|
||||
+44
-44
@@ -1,11 +1,11 @@
|
||||
# Chinese (simplified) translation for plasma-face-unlock.
|
||||
# Chinese (simplified) translation for face-unlock.
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# This file is distributed under the same license as plasma-face-unlock.
|
||||
# This file is distributed under the same license as face-unlock.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: plasma-face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/issues\n"
|
||||
"Project-Id-Version: face-unlock 1.0.1\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/face-unlock/issues\n"
|
||||
"POT-Creation-Date: 2026-09-24 10:46+0200\n"
|
||||
"PO-Revision-Date: 2026-09-24 12:00+0200\n"
|
||||
"Last-Translator: Felitendo\n"
|
||||
@@ -15,145 +15,145 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/plasma-face-unlock:50
|
||||
#: src/face-unlock:50
|
||||
msgid "Face unlock's service has to be switched on once for this computer. That needs your password."
|
||||
msgstr "人脸解锁服务需要在这台电脑上开启一次。这需要你的密码。"
|
||||
|
||||
#: src/plasma-face-unlock:57
|
||||
#: src/face-unlock:57
|
||||
#, sh-printf-format
|
||||
msgid "Check it with: systemctl status %s"
|
||||
msgstr "用以下命令检查:systemctl status %s"
|
||||
|
||||
#: src/plasma-face-unlock:67
|
||||
#: src/face-unlock:67
|
||||
msgid "Setting up a face needs the camera picture on screen. Run this inside your Plasma session."
|
||||
msgstr "设置人脸需要在屏幕上显示摄像头画面。请在你的 Plasma 会话中运行。"
|
||||
|
||||
#: src/plasma-face-unlock:71
|
||||
#: src/face-unlock:71
|
||||
msgid "The setup window is open. Follow it there."
|
||||
msgstr "设置窗口已打开。请按窗口中的步骤操作。"
|
||||
|
||||
#: src/plasma-face-unlock:80
|
||||
#: src/face-unlock:80
|
||||
msgid "The face is set up."
|
||||
msgstr "人脸已设置。"
|
||||
|
||||
#: src/plasma-face-unlock:83
|
||||
#: src/face-unlock:83
|
||||
#, sh-printf-format
|
||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||
msgstr "人脸解锁仍处于关闭状态。用 [1] 或 `%s enable` 开启。"
|
||||
|
||||
#: src/plasma-face-unlock:87
|
||||
#: src/face-unlock:87
|
||||
msgid "No face was added."
|
||||
msgstr "没有添加人脸。"
|
||||
|
||||
#: src/plasma-face-unlock:96
|
||||
#: src/face-unlock:96
|
||||
msgid "First, set up your face."
|
||||
msgstr "请先设置你的人脸。"
|
||||
|
||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/face-unlock:100 src/face-unlock:120 src/lib/menu.sh:434
|
||||
#: src/lib/menu.sh:438 src/lib/menu.sh:444 src/lib/menu.sh:446
|
||||
msgid "Could not save the setting."
|
||||
msgstr "无法保存设置。"
|
||||
|
||||
#: src/plasma-face-unlock:104
|
||||
#: src/face-unlock:104
|
||||
msgid "Could not start the lock screen agent."
|
||||
msgstr "无法启动锁屏代理。"
|
||||
|
||||
#: src/plasma-face-unlock:106
|
||||
#: src/face-unlock:106
|
||||
msgid "No systemd user session, so the lock screen agent was not started."
|
||||
msgstr "没有 systemd 用户会话,因此未启动锁屏代理。"
|
||||
|
||||
#: src/plasma-face-unlock:113
|
||||
#: src/face-unlock:113
|
||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||
msgstr "人脸解锁已开启。锁定屏幕并看着它来试试。"
|
||||
|
||||
#: src/plasma-face-unlock:115
|
||||
#: src/face-unlock:115
|
||||
msgid "It can do sudo and admin prompts too. See Settings."
|
||||
msgstr "它也可以用于 sudo 和管理员授权。见“设置”。"
|
||||
|
||||
#: src/plasma-face-unlock:130
|
||||
#: src/face-unlock:130
|
||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||
msgstr "人脸解锁已关闭。你的人脸会保留;可在“人脸”中删除。"
|
||||
|
||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||
#: src/face-unlock:144 src/lib/daemon.sh:109
|
||||
msgid "No face is set up yet."
|
||||
msgstr "尚未设置任何人脸。"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
#: src/face-unlock:148 src/lib/menu.sh:180 src/lib/menu.sh:594
|
||||
msgid "on"
|
||||
msgstr "开"
|
||||
|
||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/face-unlock:148 src/lib/menu.sh:182 src/lib/menu.sh:192
|
||||
#: src/lib/menu.sh:595
|
||||
msgid "off"
|
||||
msgstr "关"
|
||||
|
||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:612
|
||||
#: src/face-unlock:150 src/lib/menu.sh:612
|
||||
#, sh-printf-format
|
||||
msgid "%s samples, %s learned"
|
||||
msgstr "%s 个样本,已学习 %s 个"
|
||||
|
||||
#: src/plasma-face-unlock:156
|
||||
#: src/face-unlock:156
|
||||
#, sh-printf-format
|
||||
msgid "Which face? See `%s faces` for the ids."
|
||||
msgstr "哪张人脸?用 `%s faces` 查看 ID。"
|
||||
|
||||
#: src/plasma-face-unlock:160
|
||||
#: src/face-unlock:160
|
||||
msgid "Deleted."
|
||||
msgstr "已删除。"
|
||||
|
||||
#: src/plasma-face-unlock:171
|
||||
msgid "Usage: plasma-face-unlock [command]"
|
||||
msgstr "用法:plasma-face-unlock [命令]"
|
||||
#: src/face-unlock:171
|
||||
msgid "Usage: face-unlock [command]"
|
||||
msgstr "用法:face-unlock [命令]"
|
||||
|
||||
#: src/plasma-face-unlock:173
|
||||
#: src/face-unlock:173
|
||||
msgid "Commands:"
|
||||
msgstr "命令:"
|
||||
|
||||
#: src/plasma-face-unlock:174
|
||||
#: src/face-unlock:174
|
||||
msgid "Turn face unlock on"
|
||||
msgstr "开启人脸解锁"
|
||||
|
||||
#: src/plasma-face-unlock:175
|
||||
#: src/face-unlock:175
|
||||
msgid "Turn it off (faces are kept)"
|
||||
msgstr "关闭(保留人脸)"
|
||||
|
||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:678
|
||||
#: src/face-unlock:176 src/lib/menu.sh:678
|
||||
msgid "Add a face"
|
||||
msgstr "添加人脸"
|
||||
|
||||
#: src/plasma-face-unlock:177
|
||||
#: src/face-unlock:177
|
||||
msgid "List the faces"
|
||||
msgstr "列出人脸"
|
||||
|
||||
#: src/plasma-face-unlock:178
|
||||
#: src/face-unlock:178
|
||||
msgid "Delete a face"
|
||||
msgstr "删除人脸"
|
||||
|
||||
#: src/plasma-face-unlock:179
|
||||
#: src/face-unlock:179
|
||||
msgid "Look at the camera and see what it sees"
|
||||
msgstr "看着摄像头,查看它看到的画面"
|
||||
|
||||
#: src/plasma-face-unlock:180
|
||||
#: src/face-unlock:180
|
||||
msgid "Show what is on"
|
||||
msgstr "显示已开启的功能"
|
||||
|
||||
#: src/plasma-face-unlock:181
|
||||
#: src/face-unlock:181
|
||||
msgid "Show this help"
|
||||
msgstr "显示此帮助"
|
||||
|
||||
#: src/plasma-face-unlock:182
|
||||
#: src/face-unlock:182
|
||||
msgid "Show the version"
|
||||
msgstr "显示版本"
|
||||
|
||||
#: src/plasma-face-unlock:184
|
||||
#: src/face-unlock:184
|
||||
msgid "Without a command an interactive menu is shown."
|
||||
msgstr "不带命令时显示交互式菜单。"
|
||||
|
||||
#: src/plasma-face-unlock:203
|
||||
#: src/face-unlock:203
|
||||
msgid "Run this as your own user, not as root. It asks for your password when it needs to."
|
||||
msgstr "请以你自己的用户运行,不要用 root。需要时会询问你的密码。"
|
||||
|
||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||
#: src/face-unlock:221 src/lib/system.sh:89
|
||||
#, sh-printf-format
|
||||
msgid "Unknown command: %s"
|
||||
msgstr "未知命令:%s"
|
||||
@@ -795,19 +795,19 @@ msgstr "播放一次气泡动画。"
|
||||
msgid "Bubble style for the demo: full or minimal."
|
||||
msgstr "演示用的气泡样式:full 或 minimal。"
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:311
|
||||
#: src/pam/pam_face_unlock.c:311
|
||||
msgid "Look at the camera to unlock."
|
||||
msgstr "看着摄像头来解锁。"
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:314
|
||||
#: src/pam/pam_face_unlock.c:314
|
||||
msgid "Blink, or turn your head a little."
|
||||
msgstr "眨眼,或稍微转一下头。"
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:330
|
||||
#: src/pam/pam_face_unlock.c:330
|
||||
msgid "Face unlock is paused after too many tries. Use your password."
|
||||
msgstr "尝试次数过多,人脸解锁已暂停。请使用密码。"
|
||||
|
||||
#: src/pam/pam_plasma_face_unlock.c:334
|
||||
#: src/pam/pam_face_unlock.c:334
|
||||
msgid "Face not recognised."
|
||||
msgstr "未识别出人脸。"
|
||||
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Plasma Face Unlock
|
||||
Name=Face Unlock
|
||||
Name[de]=Plasma-Gesichtsentsperrung
|
||||
Name[fr]=Déverrouillage facial Plasma
|
||||
Name[es]=Desbloqueo facial de Plasma
|
||||
@@ -28,8 +28,8 @@ Comment[tr]=Kilit ekranını, sudo'yu ve yönetici istemlerini yüzünüzle aça
|
||||
Comment[zh_CN]=用你的脸解锁锁屏、sudo 和管理员授权
|
||||
Comment[ja]=顔でロック画面、sudo、管理者の認証を解除します
|
||||
Comment[ko]=얼굴로 잠금 화면, sudo, 관리자 인증 창의 잠금을 해제합니다
|
||||
Exec=@LIBEXECDIR@/plasma-face-unlock-agent
|
||||
Icon=plasma-face-unlock
|
||||
Exec=@LIBEXECDIR@/face-unlock-agent
|
||||
Icon=face-unlock
|
||||
NoDisplay=true
|
||||
OnlyShowIn=KDE;
|
||||
# KWin only lets a program show above the lock screen when its desktop file
|
||||
File renamed without changes.
+3
-3
@@ -4,13 +4,13 @@
|
||||
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
|
||||
<policyconfig>
|
||||
<vendor>LoonixTools</vendor>
|
||||
<vendor_url>https://github.com/LoonixTools/plasma-face-unlock</vendor_url>
|
||||
<icon_name>plasma-face-unlock</icon_name>
|
||||
<vendor_url>https://github.com/LoonixTools/face-unlock</vendor_url>
|
||||
<icon_name>face-unlock</icon_name>
|
||||
|
||||
<!-- A face is a way in, so adding, changing or deleting one takes the
|
||||
password, the way a phone asks for its code before it sets up a face.
|
||||
The daemon refuses to let a face answer this particular question. -->
|
||||
<action id="io.github.loonixtools.plasma-face-unlock.manage">
|
||||
<action id="io.github.loonixtools.face-unlock.manage">
|
||||
<description>Change the faces that can unlock your account</description>
|
||||
<description xml:lang="de">Gesichter ändern, die dein Konto entsperren können</description>
|
||||
<description xml:lang="fr">Modifier les visages qui peuvent déverrouiller votre compte</description>
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Face unlock for KDE Plasma (lock screen and bubble)
|
||||
Documentation=man:plasma-face-unlock(1)
|
||||
Documentation=man:face-unlock(1)
|
||||
PartOf=graphical-session.target
|
||||
After=graphical-session.target
|
||||
# Plasma on Wayland. The bubble is a layer-shell surface, and there is no such
|
||||
@@ -8,7 +8,7 @@ After=graphical-session.target
|
||||
ConditionEnvironment=WAYLAND_DISPLAY
|
||||
|
||||
[Service]
|
||||
ExecStart=@LIBEXECDIR@/plasma-face-unlock-agent
|
||||
ExecStart=@LIBEXECDIR@/face-unlock-agent
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
Slice=session.slice
|
||||
@@ -1,14 +1,14 @@
|
||||
[Unit]
|
||||
Description=Face unlock for KDE Plasma
|
||||
Documentation=man:plasma-face-unlock(1)
|
||||
Requires=plasma-face-unlockd.socket
|
||||
After=plasma-face-unlockd.socket
|
||||
Documentation=man:face-unlock(1)
|
||||
Requires=face-unlockd.socket
|
||||
After=face-unlockd.socket
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
# Started by the socket, and gone again after a minute with nothing to do.
|
||||
ExecStart=@LIBEXECDIR@/plasma-face-unlockd
|
||||
StateDirectory=plasma-face-unlock
|
||||
ExecStart=@LIBEXECDIR@/face-unlockd
|
||||
StateDirectory=face-unlock
|
||||
StateDirectoryMode=0700
|
||||
UMask=0077
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[Unit]
|
||||
Description=Face unlock for KDE Plasma (socket)
|
||||
Documentation=man:plasma-face-unlock(1)
|
||||
Documentation=man:face-unlock(1)
|
||||
|
||||
[Socket]
|
||||
# Everybody may connect. Who may ask for what is decided per request, by the
|
||||
# daemon, from the credentials the kernel reports for the other end.
|
||||
ListenStream=/run/plasma-face-unlock/socket
|
||||
ListenStream=/run/face-unlock/socket
|
||||
SocketMode=0666
|
||||
DirectoryMode=0755
|
||||
RemoveOnStop=yes
|
||||
@@ -48,7 +48,7 @@ AgentSocket::AgentSocket(QObject *parent)
|
||||
|
||||
QString AgentSocket::path()
|
||||
{
|
||||
return QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + QStringLiteral("/plasma-face-unlock/agent.socket");
|
||||
return QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + QStringLiteral("/face-unlock/agent.socket");
|
||||
}
|
||||
|
||||
bool AgentSocket::listen()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Where the daemon tells this session about scans it did not ask for: sudo in
|
||||
// a terminal, an admin prompt, a test from the menu. The daemon connects to
|
||||
// $XDG_RUNTIME_DIR/plasma-face-unlock/agent.socket when such a scan starts,
|
||||
// $XDG_RUNTIME_DIR/face-unlock/agent.socket when such a scan starts,
|
||||
// so neither side has to keep a connection open (and the daemon can exit when
|
||||
// it is idle).
|
||||
//
|
||||
|
||||
@@ -74,13 +74,13 @@ void BubbleWindow::create()
|
||||
// faint box with sharp corners around the bubble. An on-screen
|
||||
// display only fades, which a clear window does not show.
|
||||
layer->setScope(QStringLiteral("on-screen-display"));
|
||||
#ifdef PFU_LAYERSHELL_HAS_SCREEN
|
||||
#ifdef FU_LAYERSHELL_HAS_SCREEN
|
||||
layer->setScreen(QGuiApplication::primaryScreen());
|
||||
#endif
|
||||
}
|
||||
|
||||
m_view->setInitialProperties({{QStringLiteral("bubble"), QVariant::fromValue(m_controller)}});
|
||||
m_view->loadFromModule(QStringLiteral("PlasmaFaceUnlock"), QStringLiteral("Bubble"));
|
||||
m_view->loadFromModule(QStringLiteral("FaceUnlock"), QStringLiteral("Bubble"));
|
||||
if (m_view->status() == QQuickView::Error) {
|
||||
for (const QQmlError &e : m_view->errors()) {
|
||||
qWarning("%s", qPrintable(e.toString()));
|
||||
|
||||
@@ -38,8 +38,8 @@ DaemonRequest::~DaemonRequest()
|
||||
|
||||
QString DaemonRequest::socketPath()
|
||||
{
|
||||
const QByteArray env = qgetenv("PFU_SOCKET");
|
||||
return env.isEmpty() ? QStringLiteral(PFU_SOCKET) : QString::fromLocal8Bit(env);
|
||||
const QByteArray env = qgetenv("FU_SOCKET");
|
||||
return env.isEmpty() ? QStringLiteral(FU_SOCKET) : QString::fromLocal8Bit(env);
|
||||
}
|
||||
|
||||
void DaemonRequest::send(const QJsonObject &message)
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
//
|
||||
// plasma-face-unlock-agent: the part in the user's session.
|
||||
// face-unlock-agent: the part in the user's session.
|
||||
//
|
||||
// (no arguments) stay in the background: unlock the lock screen by face,
|
||||
// and show the bubble for every scan
|
||||
@@ -39,7 +39,7 @@ int runEnroll(QGuiApplication &app, const QString &name)
|
||||
QQmlApplicationEngine engine;
|
||||
KLocalization::setupLocalizedContext(&engine);
|
||||
engine.setInitialProperties({{QStringLiteral("controller"), QVariant::fromValue(&controller)}});
|
||||
engine.loadFromModule(QStringLiteral("PlasmaFaceUnlock"), QStringLiteral("Enroll"));
|
||||
engine.loadFromModule(QStringLiteral("FaceUnlock"), QStringLiteral("Enroll"));
|
||||
if (engine.rootObjects().isEmpty()) {
|
||||
return 2;
|
||||
}
|
||||
@@ -76,10 +76,10 @@ void scheduleDemo(BubbleController *bubble)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
app.setApplicationName(QStringLiteral("plasma-face-unlock-agent"));
|
||||
app.setApplicationVersion(QStringLiteral(PFU_VERSION));
|
||||
app.setDesktopFileName(QStringLiteral("io.github.loonixtools.plasma-face-unlock-agent"));
|
||||
KLocalizedString::setApplicationDomain(PFU_NAME);
|
||||
app.setApplicationName(QStringLiteral("face-unlock-agent"));
|
||||
app.setApplicationVersion(QStringLiteral(FU_VERSION));
|
||||
app.setDesktopFileName(QStringLiteral("io.github.loonixtools.face-unlock-agent"));
|
||||
KLocalizedString::setApplicationDomain(FU_NAME);
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(i18n("Face unlock for KDE Plasma"));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Window
|
||||
import PlasmaFaceUnlock
|
||||
import FaceUnlock
|
||||
|
||||
Window {
|
||||
id: window
|
||||
|
||||
@@ -23,7 +23,7 @@ UserConfig::UserConfig(QObject *parent)
|
||||
|
||||
QString UserConfig::path()
|
||||
{
|
||||
return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/plasma-face-unlock/config");
|
||||
return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/face-unlock/config");
|
||||
}
|
||||
|
||||
void UserConfig::load()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
//
|
||||
// ~/.config/plasma-face-unlock/config: what this user wants from the agent.
|
||||
// ~/.config/face-unlock/config: what this user wants from the agent.
|
||||
// Written by the menu, read here, and read again whenever it changes.
|
||||
|
||||
#pragma once
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
//
|
||||
// The system settings, /etc/plasma-face-unlock/config.
|
||||
// The system settings, /etc/face-unlock/config.
|
||||
//
|
||||
// These are the ones that decide how hard it is to get in: which camera, how
|
||||
// strict the match is, whether a photo is checked for. They belong to root
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// The face data.
|
||||
//
|
||||
// One file per user under /var/lib/plasma-face-unlock/users, named after the
|
||||
// One file per user under /var/lib/face-unlock/users, named after the
|
||||
// numeric user id so a rename cannot hand one person's faces to another. Only
|
||||
// root can read or write the directory. There are no pictures in it: every
|
||||
// sample is the 128 numbers the recognizer made of one frame, and the frame
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
//
|
||||
// plasma-face-unlock-ctl: the shell code's way to the daemon.
|
||||
// face-unlock-ctl: the shell code's way to the daemon.
|
||||
//
|
||||
// bash has no Unix sockets, so this sends one request and prints every
|
||||
// message that comes back as one line of tab separated key=value pairs:
|
||||
@@ -68,7 +68,7 @@ void printObject(const QJsonObject &o, const QString &event)
|
||||
int usage()
|
||||
{
|
||||
std::fprintf(stderr,
|
||||
"usage: plasma-face-unlock-ctl [--socket PATH] COMMAND\n"
|
||||
"usage: face-unlock-ctl [--socket PATH] COMMAND\n"
|
||||
" hello | status | cameras | list | watch | unlocked\n"
|
||||
" verify [USER] [PURPOSE] | test\n"
|
||||
" remove ID | rename ID NAME | enable ID | disable ID | clear\n");
|
||||
@@ -81,12 +81,12 @@ int main(int argc, char **argv)
|
||||
QCoreApplication app(argc, argv);
|
||||
QStringList args = app.arguments().mid(1);
|
||||
|
||||
QString socketPath = QStringLiteral(PFU_SOCKET);
|
||||
QString socketPath = QStringLiteral(FU_SOCKET);
|
||||
if (args.size() >= 2 && args.first() == u"--socket") {
|
||||
socketPath = args.at(1);
|
||||
args = args.mid(2);
|
||||
}
|
||||
if (const QByteArray env = qgetenv("PFU_SOCKET"); !env.isEmpty()) {
|
||||
if (const QByteArray env = qgetenv("FU_SOCKET"); !env.isEmpty()) {
|
||||
socketPath = QString::fromLocal8Bit(env);
|
||||
}
|
||||
if (args.isEmpty()) {
|
||||
|
||||
@@ -25,7 +25,7 @@ AgentLink::AgentLink(uid_t uid, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_uid(uid)
|
||||
{
|
||||
const QString dir = QStringLiteral("/run/user/%1/plasma-face-unlock").arg(uid);
|
||||
const QString dir = QStringLiteral("/run/user/%1/face-unlock").arg(uid);
|
||||
const QString path = dir + QStringLiteral("/agent.socket");
|
||||
if (!ownedBy(dir, uid, false) || !ownedBy(path, uid, true)) {
|
||||
// No agent in that session, or not one of this user's making.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Telling a user's session about a scan it did not start itself (sudo, an
|
||||
// admin prompt, a test from the menu), so the bubble can show it.
|
||||
//
|
||||
// The agent listens on /run/user/UID/plasma-face-unlock/agent.socket. That is
|
||||
// The agent listens on /run/user/UID/face-unlock/agent.socket. That is
|
||||
// a place the user controls, so nothing is taken for granted: the socket has
|
||||
// to belong to the user, and so does the process that answers on it, checked
|
||||
// by the kernel before a single byte is written. What is written is only
|
||||
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
//
|
||||
// plasma-face-unlockd: the part that runs as root.
|
||||
// face-unlockd: the part that runs as root.
|
||||
//
|
||||
// It owns the camera and the face data, and it is the only thing that does.
|
||||
// Everything else (the lock screen agent, sudo, the setup window, the menu)
|
||||
@@ -66,8 +66,8 @@ int main(int argc, char **argv)
|
||||
umask(077);
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
app.setApplicationName(QStringLiteral("plasma-face-unlockd"));
|
||||
app.setApplicationVersion(QStringLiteral(PFU_VERSION));
|
||||
app.setApplicationName(QStringLiteral("face-unlockd"));
|
||||
app.setApplicationVersion(QStringLiteral(FU_VERSION));
|
||||
qSetMessagePattern(QStringLiteral("%{if-warning}warning: %{endif}%{if-critical}error: %{endif}%{message}"));
|
||||
|
||||
QCommandLineParser parser;
|
||||
@@ -75,12 +75,12 @@ int main(int argc, char **argv)
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
const QCommandLineOption socketOpt(QStringLiteral("socket"), QStringLiteral("Listen here instead of the system socket."), QStringLiteral("path"),
|
||||
QStringLiteral(PFU_SOCKET));
|
||||
QStringLiteral(FU_SOCKET));
|
||||
const QCommandLineOption stateOpt(QStringLiteral("state-dir"), QStringLiteral("Where face data is kept."), QStringLiteral("dir"),
|
||||
QStringLiteral(PFU_STATEDIR));
|
||||
const QCommandLineOption configOpt(QStringLiteral("config"), QStringLiteral("The settings file."), QStringLiteral("file"), QStringLiteral(PFU_CONFIG));
|
||||
QStringLiteral(FU_STATEDIR));
|
||||
const QCommandLineOption configOpt(QStringLiteral("config"), QStringLiteral("The settings file."), QStringLiteral("file"), QStringLiteral(FU_CONFIG));
|
||||
const QCommandLineOption modelOpt(QStringLiteral("models"), QStringLiteral("Where the networks are."), QStringLiteral("dir"),
|
||||
QStringLiteral(PFU_MODELDIR));
|
||||
QStringLiteral(FU_MODELDIR));
|
||||
const QCommandLineOption idleOpt(QStringLiteral("idle-exit"), QStringLiteral("Exit after this many idle seconds (0: never)."), QStringLiteral("seconds"));
|
||||
parser.addOptions({socketOpt, stateOpt, configOpt, modelOpt, idleOpt});
|
||||
parser.process(app);
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
namespace Polkit
|
||||
{
|
||||
inline constexpr char ManageAction[] = "io.github.loonixtools.plasma-face-unlock.manage";
|
||||
inline constexpr char ManageAction[] = "io.github.loonixtools.face-unlock.manage";
|
||||
|
||||
// Calls done(true) when the process may go ahead. Interactive: this can take
|
||||
// as long as it takes somebody to type a password.
|
||||
|
||||
@@ -282,7 +282,7 @@ void Server::onRequest(Client *client, const QJsonObject &request)
|
||||
client->role = cmd;
|
||||
|
||||
if (cmd == u"hello") {
|
||||
reply(client, {{QStringLiteral("event"), QStringLiteral("result")}, {QStringLiteral("ok"), true}, {QStringLiteral("version"), QStringLiteral(PFU_VERSION)}});
|
||||
reply(client, {{QStringLiteral("event"), QStringLiteral("result")}, {QStringLiteral("ok"), true}, {QStringLiteral("version"), QStringLiteral(FU_VERSION)}});
|
||||
} else if (cmd == u"status") {
|
||||
handleStatus(client);
|
||||
} else if (cmd == u"cameras") {
|
||||
@@ -344,7 +344,7 @@ void Server::handleStatus(Client *client)
|
||||
reply(client,
|
||||
{{QStringLiteral("event"), QStringLiteral("result")},
|
||||
{QStringLiteral("ok"), true},
|
||||
{QStringLiteral("version"), QStringLiteral(PFU_VERSION)},
|
||||
{QStringLiteral("version"), QStringLiteral(FU_VERSION)},
|
||||
{QStringLiteral("user"), System::nameOf(uid)},
|
||||
{QStringLiteral("faces"), enabled},
|
||||
{QStringLiteral("identities"), int(faces.size())},
|
||||
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# face-unlock: face unlock for KDE Plasma
|
||||
#
|
||||
# Look at the screen and it unlocks, the way a phone does. The lock screen,
|
||||
# sudo in a terminal and the admin password prompts can all take a face
|
||||
# instead of a password, with a check that it is a face and not a photo of one.
|
||||
#
|
||||
# This is the front end: the menu and the commands. The camera, the face data
|
||||
# and the decision are the daemon's (face-unlockd, running as root),
|
||||
# the lock screen and the bubble at the top of the screen are the agent's
|
||||
# (face-unlock-agent, in the session), and sudo and polkit reach the
|
||||
# daemon through a PAM module. See the man page for how the pieces fit.
|
||||
#
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
FU_SELF="$(readlink -f "${BASH_SOURCE[0]}")"
|
||||
|
||||
# Run as root (through sudo from the menu), only what was installed counts.
|
||||
# An environment that points the libraries somewhere else is ignored then.
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
unset FU_LIBDIR FU_LIBEXECDIR FU_LOCALEDIR FU_PAMDIR FU_CTL FU_AGENT FU_PAM_MODULE FU_SYSCONFIG \
|
||||
FU_PAM_ETC_DIR FU_PAM_VENDOR_DIRS
|
||||
fi
|
||||
|
||||
FU_LIBDIR="${FU_LIBDIR:-@LIBDIR@}"
|
||||
|
||||
for _mod in common config daemon pam system menu; do
|
||||
# shellcheck source=/dev/null
|
||||
if ! source "$FU_LIBDIR/$_mod.sh"; then
|
||||
printf 'face-unlock: cannot load %s/%s.sh\n' "$FU_LIBDIR" "$_mod" >&2
|
||||
exit 14
|
||||
fi
|
||||
done
|
||||
unset _mod
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Commands
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# The daemon is started by its socket. Enabling the socket is the one thing
|
||||
# that needs root once per machine.
|
||||
fu_ensure_service() {
|
||||
fu_status_load && return 0
|
||||
|
||||
if ! fu_socket_enabled; then
|
||||
fu_say " $(fu_msg "Face unlock's service has to be switched on once for this computer. That needs your password.")"
|
||||
fu_root socket-enable || return 1
|
||||
sleep 0.3
|
||||
fi
|
||||
fu_status_load && return 0
|
||||
|
||||
fu_bad "$(fu_reason_text unreachable)"
|
||||
fu_note "$(fu_msg "Check it with: systemctl status %s" "$FU_UNIT_SOCKET")"
|
||||
return 1
|
||||
}
|
||||
|
||||
fu_do_setup() {
|
||||
local name="${1:-}" rc
|
||||
|
||||
fu_ensure_service || return 1
|
||||
|
||||
if [[ -z ${WAYLAND_DISPLAY:-} && -z ${DISPLAY:-} ]]; then
|
||||
fu_bad "$(fu_msg "Setting up a face needs the camera picture on screen. Run this inside your Plasma session.")"
|
||||
return 1
|
||||
fi
|
||||
|
||||
fu_say " $(fu_msg "The setup window is open. Follow it there.")"
|
||||
if [[ -n $name ]]; then
|
||||
"$FU_AGENT" --enroll --name "$name" > /dev/null 2>&1
|
||||
else
|
||||
"$FU_AGENT" --enroll > /dev/null 2>&1
|
||||
fi
|
||||
rc=$?
|
||||
|
||||
if (( rc == 0 )); then
|
||||
fu_ok "$(fu_msg "The face is set up.")"
|
||||
fu_config_load
|
||||
if [[ $CFG_ENABLED != yes ]]; then
|
||||
fu_note "$(fu_msg "Face unlock is still off. Turn it on with [1] or \`%s enable\`." "$FU_NAME")"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
fu_note "$(fu_msg "No face was added.")"
|
||||
return 1
|
||||
}
|
||||
|
||||
fu_do_enable() {
|
||||
fu_ensure_service || return 1
|
||||
|
||||
fu_faces_load
|
||||
if (( ${#FU_FACE_IDS[@]} == 0 )); then
|
||||
fu_say " $(fu_msg "First, set up your face.")"
|
||||
fu_do_setup || return 1
|
||||
fi
|
||||
|
||||
fu_config_set Enabled yes || { fu_bad "$(fu_msg "Could not save the setting.")"; return 1; }
|
||||
fu_config_load
|
||||
|
||||
if fu_agent_available; then
|
||||
fu_agent_enable || fu_bad "$(fu_msg "Could not start the lock screen agent.")"
|
||||
else
|
||||
fu_note "$(fu_msg "No systemd user session, so the lock screen agent was not started.")"
|
||||
fi
|
||||
|
||||
# What was on the last time face unlock was on.
|
||||
[[ $CFG_SUDO == yes ]] && ! fu_pam_enabled sudo && fu_root pam-enable sudo
|
||||
[[ $CFG_POLKIT == yes ]] && ! fu_pam_enabled polkit-1 && fu_root pam-enable polkit-1
|
||||
|
||||
fu_ok "$(fu_msg "Face unlock is on. Lock the screen and look at it to try.")"
|
||||
if [[ $CFG_SUDO != yes && $CFG_POLKIT != yes ]]; then
|
||||
fu_note "$(fu_msg "It can do sudo and admin prompts too. See Settings.")"
|
||||
fi
|
||||
}
|
||||
|
||||
fu_do_disable() {
|
||||
fu_config_set Enabled no || { fu_bad "$(fu_msg "Could not save the setting.")"; return 1; }
|
||||
fu_agent_available && fu_agent_disable
|
||||
|
||||
local service
|
||||
for service in "${FU_PAM_SERVICES[@]}"; do
|
||||
if fu_pam_enabled "$service"; then
|
||||
fu_root pam-disable "$service" || true
|
||||
fi
|
||||
done
|
||||
|
||||
fu_ok "$(fu_msg "Face unlock is off. Your faces are kept; delete them under Faces.")"
|
||||
}
|
||||
|
||||
fu_do_status() {
|
||||
fu_head " $FU_PRETTY"
|
||||
fu_ui_status
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
fu_do_faces() {
|
||||
local i state
|
||||
fu_status_load || { fu_bad "$(fu_reason_text unreachable)"; return 1; }
|
||||
fu_faces_load
|
||||
if (( ${#FU_FACE_IDS[@]} == 0 )); then
|
||||
fu_note "$(fu_msg "No face is set up yet.")"
|
||||
return 0
|
||||
fi
|
||||
for i in "${!FU_FACE_IDS[@]}"; do
|
||||
if [[ ${FU_FACE_ON[i]} == true ]]; then state="$(fu_msg "on")"; else state="$(fu_msg "off")"; fi
|
||||
printf ' %s %-24s %-4s %s\n' "${FU_FACE_IDS[i]}" "${FU_FACE_NAMES[i]}" "$state" \
|
||||
"$(fu_msg "%s samples, %s learned" "${FU_FACE_SAMPLES[i]}" "${FU_FACE_LEARNED[i]}")"
|
||||
done
|
||||
}
|
||||
|
||||
fu_do_remove() {
|
||||
local id="${1:-}" line
|
||||
[[ -n $id ]] || { fu_bad "$(fu_msg "Which face? See \`%s faces\` for the ids." "$FU_NAME")"; return 1; }
|
||||
line="$(fu_ctl remove "$id" | tail -n1)"
|
||||
_fu_fields "$line"
|
||||
if [[ ${FU_F[ok]:-} == true ]]; then
|
||||
fu_ok "$(fu_msg "Deleted.")"
|
||||
else
|
||||
fu_bad "$(fu_reason_text "${FU_F[reason]:-unreachable}")"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
fu_do_help() {
|
||||
cat <<- EOF
|
||||
$FU_PRETTY $FU_VERSION
|
||||
|
||||
$(fu_msg "Usage: face-unlock [command]")
|
||||
|
||||
$(fu_msg "Commands:")
|
||||
enable $(fu_msg "Turn face unlock on")
|
||||
disable $(fu_msg "Turn it off (faces are kept)")
|
||||
setup [NAME] $(fu_msg "Add a face")
|
||||
faces $(fu_msg "List the faces")
|
||||
remove ID $(fu_msg "Delete a face")
|
||||
test $(fu_msg "Look at the camera and see what it sees")
|
||||
status $(fu_msg "Show what is on")
|
||||
-h, --help $(fu_msg "Show this help")
|
||||
-V, --version $(fu_msg "Show the version")
|
||||
|
||||
$(fu_msg "Without a command an interactive menu is shown.")
|
||||
EOF
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Dispatch
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
main() {
|
||||
local cmd="${1:-}"
|
||||
[[ $# -gt 0 ]] && shift
|
||||
|
||||
case "$cmd" in
|
||||
--root) fu_root_verb "$@"; return ;;
|
||||
esac
|
||||
|
||||
# Face data and settings are per user; root has neither a lock screen
|
||||
# nor a face of its own to set up.
|
||||
if [[ $EUID -eq 0 && -z ${FU_ALLOW_ROOT:-} ]]; then
|
||||
fu_bad "$(fu_msg "Run this as your own user, not as root. It asks for your password when it needs to.")"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
case "$cmd" in
|
||||
enable) fu_do_enable ;;
|
||||
disable) fu_do_disable ;;
|
||||
setup|add|enroll) fu_do_setup "$@" ;;
|
||||
faces|list) fu_do_faces ;;
|
||||
remove|delete) fu_do_remove "$@" ;;
|
||||
test|try) fu_ensure_service && fu_test ;;
|
||||
status) fu_do_status ;;
|
||||
|
||||
-h|--help|help) fu_do_help ;;
|
||||
-V|--version) printf '%s %s\n' "$FU_NAME" "$FU_VERSION" ;;
|
||||
|
||||
'') fu_ui_menu ;;
|
||||
*)
|
||||
fu_bad "$(fu_msg "Unknown command: %s" "$cmd")"
|
||||
printf '\n'
|
||||
fu_do_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
+70
-70
@@ -4,42 +4,42 @@
|
||||
#
|
||||
# The shell side never touches the camera or the face data. Those belong to
|
||||
# the daemon, and everything here that needs them asks it through
|
||||
# plasma-face-unlock-ctl. What this side does write is the user's own settings
|
||||
# face-unlock-ctl. What this side does write is the user's own settings
|
||||
# file, and (through sudo, and only when asked) the system settings and the
|
||||
# PAM files of sudo and polkit.
|
||||
|
||||
PFU_VERSION="@VERSION@"
|
||||
PFU_NAME="plasma-face-unlock"
|
||||
PFU_PRETTY="Plasma Face Unlock"
|
||||
FU_VERSION="@VERSION@"
|
||||
FU_NAME="face-unlock"
|
||||
FU_PRETTY="Face Unlock"
|
||||
|
||||
PFU_LIBDIR="${PFU_LIBDIR:-@LIBDIR@}"
|
||||
PFU_LIBEXECDIR="${PFU_LIBEXECDIR:-@LIBEXECDIR@}"
|
||||
PFU_LOCALEDIR="${PFU_LOCALEDIR:-@LOCALEDIR@}"
|
||||
PFU_PAMDIR="${PFU_PAMDIR:-@PAMDIR@}"
|
||||
FU_LIBDIR="${FU_LIBDIR:-@LIBDIR@}"
|
||||
FU_LIBEXECDIR="${FU_LIBEXECDIR:-@LIBEXECDIR@}"
|
||||
FU_LOCALEDIR="${FU_LOCALEDIR:-@LOCALEDIR@}"
|
||||
FU_PAMDIR="${FU_PAMDIR:-@PAMDIR@}"
|
||||
|
||||
PFU_CTL="${PFU_CTL:-$PFU_LIBEXECDIR/plasma-face-unlock-ctl}"
|
||||
PFU_AGENT="${PFU_AGENT:-$PFU_LIBEXECDIR/plasma-face-unlock-agent}"
|
||||
PFU_PAM_MODULE="${PFU_PAM_MODULE:-$PFU_PAMDIR/pam_plasma_face_unlock.so}"
|
||||
FU_CTL="${FU_CTL:-$FU_LIBEXECDIR/face-unlock-ctl}"
|
||||
FU_AGENT="${FU_AGENT:-$FU_LIBEXECDIR/face-unlock-agent}"
|
||||
FU_PAM_MODULE="${FU_PAM_MODULE:-$FU_PAMDIR/pam_face_unlock.so}"
|
||||
|
||||
PFU_XDG_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
PFU_CONFDIR="${PFU_CONFDIR:-${PFU_XDG_CONFIG}/${PFU_NAME}}"
|
||||
PFU_CONFIG="${PFU_CONFIG:-${PFU_CONFDIR}/config}"
|
||||
FU_XDG_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
FU_CONFDIR="${FU_CONFDIR:-${FU_XDG_CONFIG}/${FU_NAME}}"
|
||||
FU_CONFIG="${FU_CONFIG:-${FU_CONFDIR}/config}"
|
||||
|
||||
# The system settings. Only root writes them; see system.sh.
|
||||
PFU_SYSCONFIG="${PFU_SYSCONFIG:-/etc/${PFU_NAME}/config}"
|
||||
FU_SYSCONFIG="${FU_SYSCONFIG:-/etc/${FU_NAME}/config}"
|
||||
|
||||
PFU_UNIT_SOCKET="plasma-face-unlockd.socket"
|
||||
PFU_UNIT_AGENT="plasma-face-unlock-agent.service"
|
||||
FU_UNIT_SOCKET="face-unlockd.socket"
|
||||
FU_UNIT_AGENT="face-unlock-agent.service"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Translations
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
export TEXTDOMAIN="plasma-face-unlock"
|
||||
export TEXTDOMAINDIR="${PFU_LOCALEDIR}"
|
||||
export TEXTDOMAIN="face-unlock"
|
||||
export TEXTDOMAINDIR="${FU_LOCALEDIR}"
|
||||
|
||||
pfu_ui_locale() {
|
||||
local l="${PFU_UI_LOCALE:-}"
|
||||
fu_ui_locale() {
|
||||
local l="${FU_UI_LOCALE:-}"
|
||||
|
||||
if [[ -z $l ]]; then
|
||||
l="${LC_ALL:-}"
|
||||
@@ -63,53 +63,53 @@ pfu_ui_locale() {
|
||||
|
||||
# Every gettext lookup is a fork and the settings screen redraws a screenful of
|
||||
# labels per keypress, so results are memoized.
|
||||
declare -A PFU_MSG_CACHE=()
|
||||
declare -A FU_MSG_CACHE=()
|
||||
|
||||
PFU_MSG_RESULT=''
|
||||
FU_MSG_RESULT=''
|
||||
|
||||
# pfu_msg_into <locale> <msgid>
|
||||
# Plain lookup with the result in PFU_MSG_RESULT and no printf formatting, for
|
||||
# fu_msg_into <locale> <msgid>
|
||||
# Plain lookup with the result in FU_MSG_RESULT and no printf formatting, for
|
||||
# callers that would otherwise pay a fork per label per frame.
|
||||
pfu_msg_into() {
|
||||
fu_msg_into() {
|
||||
local locale="$1" msgid="$2" cachekey
|
||||
cachekey="${locale}"$'\x1f'"${msgid}"
|
||||
|
||||
if [[ -n ${PFU_MSG_CACHE[$cachekey]+set} ]]; then
|
||||
PFU_MSG_RESULT="${PFU_MSG_CACHE[$cachekey]}"
|
||||
if [[ -n ${FU_MSG_CACHE[$cachekey]+set} ]]; then
|
||||
FU_MSG_RESULT="${FU_MSG_CACHE[$cachekey]}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
PFU_MSG_RESULT="$(LC_ALL="$locale" LANGUAGE="${locale%%.*}" gettext -- "$msgid" 2>/dev/null)"
|
||||
[[ -n $PFU_MSG_RESULT ]] || PFU_MSG_RESULT="$msgid"
|
||||
PFU_MSG_CACHE[$cachekey]="$PFU_MSG_RESULT"
|
||||
FU_MSG_RESULT="$(LC_ALL="$locale" LANGUAGE="${locale%%.*}" gettext -- "$msgid" 2>/dev/null)"
|
||||
[[ -n $FU_MSG_RESULT ]] || FU_MSG_RESULT="$msgid"
|
||||
FU_MSG_CACHE[$cachekey]="$FU_MSG_RESULT"
|
||||
return 0
|
||||
}
|
||||
|
||||
# pfu_msg_in <locale> <msgid> [printf args...]
|
||||
pfu_msg_in() {
|
||||
# fu_msg_in <locale> <msgid> [printf args...]
|
||||
fu_msg_in() {
|
||||
local locale="$1" msgid="$2"
|
||||
shift 2
|
||||
|
||||
pfu_msg_into "$locale" "$msgid"
|
||||
fu_msg_into "$locale" "$msgid"
|
||||
|
||||
# With no arguments the message is plain text, not a format string. Feeding
|
||||
# it to printf anyway would turn a literal percent sign in a translation
|
||||
# into an invalid conversion.
|
||||
if (( $# == 0 )); then
|
||||
printf '%s' "$PFU_MSG_RESULT"
|
||||
printf '%s' "$FU_MSG_RESULT"
|
||||
return
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2059 # the format string is the translated message
|
||||
printf -- "$PFU_MSG_RESULT" "$@"
|
||||
printf -- "$FU_MSG_RESULT" "$@"
|
||||
}
|
||||
|
||||
PFU_LOCALE_CACHED=''
|
||||
FU_LOCALE_CACHED=''
|
||||
|
||||
# pfu_msg <msgid> [printf args...]
|
||||
pfu_msg() {
|
||||
[[ -n $PFU_LOCALE_CACHED ]] || PFU_LOCALE_CACHED="$(pfu_ui_locale)"
|
||||
pfu_msg_in "$PFU_LOCALE_CACHED" "$@"
|
||||
# fu_msg <msgid> [printf args...]
|
||||
fu_msg() {
|
||||
[[ -n $FU_LOCALE_CACHED ]] || FU_LOCALE_CACHED="$(fu_ui_locale)"
|
||||
fu_msg_in "$FU_LOCALE_CACHED" "$@"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -119,45 +119,45 @@ pfu_msg() {
|
||||
# Decided once, while stdout is still whatever the process was started with:
|
||||
# testing -t 1 at the point of use is wrong for anything called through $(...),
|
||||
# which sees a pipe and would conclude nobody is watching.
|
||||
PFU_INTERACTIVE=''
|
||||
[[ -t 1 ]] && PFU_INTERACTIVE=1
|
||||
FU_INTERACTIVE=''
|
||||
[[ -t 1 ]] && FU_INTERACTIVE=1
|
||||
|
||||
if [[ -n $PFU_INTERACTIVE && -z ${NO_COLOR:-} ]]; then
|
||||
PFU_C_RESET=$'\033[0m'
|
||||
PFU_C_BOLD=$'\033[1m'
|
||||
PFU_C_DIM=$'\033[2m'
|
||||
PFU_C_BLUE=$'\033[38;2;52;153;255m'
|
||||
PFU_C_GREEN=$'\033[32m'
|
||||
PFU_C_YELLOW=$'\033[33m'
|
||||
PFU_C_RED=$'\033[31m'
|
||||
if [[ -n $FU_INTERACTIVE && -z ${NO_COLOR:-} ]]; then
|
||||
FU_C_RESET=$'\033[0m'
|
||||
FU_C_BOLD=$'\033[1m'
|
||||
FU_C_DIM=$'\033[2m'
|
||||
FU_C_BLUE=$'\033[38;2;52;153;255m'
|
||||
FU_C_GREEN=$'\033[32m'
|
||||
FU_C_YELLOW=$'\033[33m'
|
||||
FU_C_RED=$'\033[31m'
|
||||
else
|
||||
PFU_C_RESET='' PFU_C_BOLD='' PFU_C_DIM='' PFU_C_BLUE=''
|
||||
PFU_C_GREEN='' PFU_C_YELLOW='' PFU_C_RED=''
|
||||
FU_C_RESET='' FU_C_BOLD='' FU_C_DIM='' FU_C_BLUE=''
|
||||
FU_C_GREEN='' FU_C_YELLOW='' FU_C_RED=''
|
||||
fi
|
||||
|
||||
# What pfu_ok, pfu_bad and pfu_note printed. The menu redraws straight after an
|
||||
# What fu_ok, fu_bad and fu_note printed. The menu redraws straight after an
|
||||
# action, which wipes the screen, so it shows these again under the new frame
|
||||
# rather than holding everything up for a key press.
|
||||
PFU_UI_NOTICES=()
|
||||
FU_UI_NOTICES=()
|
||||
|
||||
pfu_say() { printf '%s\n' "$*"; }
|
||||
pfu_head() { printf '\n%s%s%s\n\n' "$PFU_C_BOLD$PFU_C_BLUE" "$*" "$PFU_C_RESET"; }
|
||||
pfu_ok() { PFU_UI_NOTICES+=("$PFU_C_GREEN✔$PFU_C_RESET $*"); printf '%s✔%s %s\n' "$PFU_C_GREEN" "$PFU_C_RESET" "$*"; }
|
||||
pfu_bad() { PFU_UI_NOTICES+=("$PFU_C_RED✘$PFU_C_RESET $*"); printf '%s✘%s %s\n' "$PFU_C_RED" "$PFU_C_RESET" "$*" >&2; }
|
||||
pfu_note() { PFU_UI_NOTICES+=("$PFU_C_DIM•$PFU_C_RESET $*"); printf '%s•%s %s\n' "$PFU_C_DIM" "$PFU_C_RESET" "$*"; }
|
||||
fu_say() { printf '%s\n' "$*"; }
|
||||
fu_head() { printf '\n%s%s%s\n\n' "$FU_C_BOLD$FU_C_BLUE" "$*" "$FU_C_RESET"; }
|
||||
fu_ok() { FU_UI_NOTICES+=("$FU_C_GREEN✔$FU_C_RESET $*"); printf '%s✔%s %s\n' "$FU_C_GREEN" "$FU_C_RESET" "$*"; }
|
||||
fu_bad() { FU_UI_NOTICES+=("$FU_C_RED✘$FU_C_RESET $*"); printf '%s✘%s %s\n' "$FU_C_RED" "$FU_C_RESET" "$*" >&2; }
|
||||
fu_note() { FU_UI_NOTICES+=("$FU_C_DIM•$FU_C_RESET $*"); printf '%s•%s %s\n' "$FU_C_DIM" "$FU_C_RESET" "$*"; }
|
||||
|
||||
pfu_have() { command -v "$1" > /dev/null 2>&1; }
|
||||
fu_have() { command -v "$1" > /dev/null 2>&1; }
|
||||
|
||||
# Human-readable "x minutes ago" for a unix timestamp. 0 or empty yields the
|
||||
# translated "never".
|
||||
#
|
||||
# Written with [[ ]] and a variable for each number on purpose: xgettext reads
|
||||
# the < of an (( )) as a redirection and loses every string after it.
|
||||
pfu_time_ago() {
|
||||
fu_time_ago() {
|
||||
local ts="$1" now delta n
|
||||
|
||||
if [[ ! $ts =~ ^[0-9]+$ || $ts -eq 0 ]]; then
|
||||
pfu_msg "never"
|
||||
fu_msg "never"
|
||||
printf '\n'
|
||||
return
|
||||
fi
|
||||
@@ -167,22 +167,22 @@ pfu_time_ago() {
|
||||
[[ $delta -lt 0 ]] && delta=0
|
||||
|
||||
if [[ $delta -lt 60 ]]; then
|
||||
pfu_msg "just now"
|
||||
fu_msg "just now"
|
||||
elif [[ $delta -lt 120 ]]; then
|
||||
pfu_msg "1 minute ago"
|
||||
fu_msg "1 minute ago"
|
||||
elif [[ $delta -lt 3600 ]]; then
|
||||
n=$(( delta / 60 ))
|
||||
pfu_msg "%d minutes ago" "$n"
|
||||
fu_msg "%d minutes ago" "$n"
|
||||
elif [[ $delta -lt 7200 ]]; then
|
||||
pfu_msg "1 hour ago"
|
||||
fu_msg "1 hour ago"
|
||||
elif [[ $delta -lt 86400 ]]; then
|
||||
n=$(( delta / 3600 ))
|
||||
pfu_msg "%d hours ago" "$n"
|
||||
fu_msg "%d hours ago" "$n"
|
||||
elif [[ $delta -lt 172800 ]]; then
|
||||
pfu_msg "1 day ago"
|
||||
fu_msg "1 day ago"
|
||||
else
|
||||
n=$(( delta / 86400 ))
|
||||
pfu_msg "%d days ago" "$n"
|
||||
fu_msg "%d days ago" "$n"
|
||||
fi
|
||||
printf '\n'
|
||||
}
|
||||
+34
-34
@@ -2,9 +2,9 @@
|
||||
#
|
||||
# Reading and writing the settings files.
|
||||
#
|
||||
# Two of them, in the same format: ~/.config/plasma-face-unlock/config for
|
||||
# Two of them, in the same format: ~/.config/face-unlock/config for
|
||||
# what this user wants from the lock screen and the bubble, and
|
||||
# /etc/plasma-face-unlock/config for what the daemon does (which camera, how
|
||||
# /etc/face-unlock/config for what the daemon does (which camera, how
|
||||
# strict), which only root writes. Neither is meant to be edited by hand:
|
||||
# every option is in the menu.
|
||||
#
|
||||
@@ -12,25 +12,25 @@
|
||||
# comments. The daemon and the agent read them with the same rules (see
|
||||
# src/core/keyvalue.cpp).
|
||||
|
||||
declare -A PFU_KV_CACHE=()
|
||||
declare -A FU_KV_CACHE=()
|
||||
|
||||
# _pfu_kv_lookup <file> <Key> [default]
|
||||
# Result in PFU_KV_VALUE. Assigning rather than printing matters on the
|
||||
# _fu_kv_lookup <file> <Key> [default]
|
||||
# Result in FU_KV_VALUE. Assigning rather than printing matters on the
|
||||
# settings screen, which reads every key on every frame: a command
|
||||
# substitution there is a fork, and forks are the whole cost of a redraw.
|
||||
PFU_KV_VALUE=''
|
||||
FU_KV_VALUE=''
|
||||
|
||||
_pfu_kv_lookup() {
|
||||
_fu_kv_lookup() {
|
||||
local file="$1" key="$2" default="${3:-}" val='' line content
|
||||
|
||||
PFU_KV_VALUE="$default"
|
||||
FU_KV_VALUE="$default"
|
||||
[[ -r $file ]] || return 0
|
||||
|
||||
if [[ -n ${PFU_KV_CACHE[$file]+set} ]]; then
|
||||
content="${PFU_KV_CACHE[$file]}"
|
||||
if [[ -n ${FU_KV_CACHE[$file]+set} ]]; then
|
||||
content="${FU_KV_CACHE[$file]}"
|
||||
else
|
||||
content="$(< "$file")"
|
||||
PFU_KV_CACHE[$file]="$content"
|
||||
FU_KV_CACHE[$file]="$content"
|
||||
fi
|
||||
|
||||
while IFS= read -r line; do
|
||||
@@ -45,19 +45,19 @@ _pfu_kv_lookup() {
|
||||
val="${val%\"}"
|
||||
val="${val#\"}"
|
||||
|
||||
[[ -n $val ]] && PFU_KV_VALUE="$val"
|
||||
[[ -n $val ]] && FU_KV_VALUE="$val"
|
||||
return 0
|
||||
}
|
||||
|
||||
pfu_is_true() {
|
||||
fu_is_true() {
|
||||
case "${1,,}" in
|
||||
yes|y|true|1|on|enabled) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# pfu_kv_set <file> <Key> <Value> <header line>
|
||||
pfu_kv_set() {
|
||||
# fu_kv_set <file> <Key> <Value> <header line>
|
||||
fu_kv_set() {
|
||||
local file="$1" key="$2" value="$3" header="$4" tmp
|
||||
|
||||
if [[ ! -e $file ]]; then
|
||||
@@ -65,7 +65,7 @@ pfu_kv_set() {
|
||||
{
|
||||
printf '# %s\n' "$header"
|
||||
printf '#\n'
|
||||
printf '# Written by `%s`. Nothing here needs editing by hand:\n' "$PFU_NAME"
|
||||
printf '# Written by `%s`. Nothing here needs editing by hand:\n' "$FU_NAME"
|
||||
printf '# every option is in the menu.\n'
|
||||
} > "$file" || return 1
|
||||
fi
|
||||
@@ -91,42 +91,42 @@ pfu_kv_set() {
|
||||
# Replaced, not rewritten in place: the agent watches the directory and
|
||||
# picks up the new file the moment it lands.
|
||||
mv -f "$tmp" "$file"
|
||||
unset 'PFU_KV_CACHE[$file]'
|
||||
unset 'FU_KV_CACHE[$file]'
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# This user's settings
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
pfu_config_get() {
|
||||
_pfu_kv_lookup "$PFU_CONFIG" "$@"
|
||||
printf '%s\n' "$PFU_KV_VALUE"
|
||||
fu_config_get() {
|
||||
_fu_kv_lookup "$FU_CONFIG" "$@"
|
||||
printf '%s\n' "$FU_KV_VALUE"
|
||||
}
|
||||
|
||||
pfu_config_set() {
|
||||
pfu_kv_set "$PFU_CONFIG" "$1" "$2" "$PFU_PRETTY"
|
||||
fu_config_set() {
|
||||
fu_kv_set "$FU_CONFIG" "$1" "$2" "$FU_PRETTY"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# The system settings (read by anybody, written by root)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
pfu_sys_get() {
|
||||
_pfu_kv_lookup "$PFU_SYSCONFIG" "$@"
|
||||
printf '%s\n' "$PFU_KV_VALUE"
|
||||
fu_sys_get() {
|
||||
_fu_kv_lookup "$FU_SYSCONFIG" "$@"
|
||||
printf '%s\n' "$FU_KV_VALUE"
|
||||
}
|
||||
|
||||
# pfu_config_load
|
||||
# fu_config_load
|
||||
# Everything the menu shows, resolved once per screen.
|
||||
pfu_config_load() {
|
||||
PFU_KV_CACHE=()
|
||||
fu_config_load() {
|
||||
FU_KV_CACHE=()
|
||||
|
||||
_pfu_kv_lookup "$PFU_CONFIG" Enabled no; CFG_ENABLED=no; pfu_is_true "$PFU_KV_VALUE" && CFG_ENABLED=yes
|
||||
_pfu_kv_lookup "$PFU_CONFIG" LockScreen yes; CFG_LOCK=no; pfu_is_true "$PFU_KV_VALUE" && CFG_LOCK=yes
|
||||
_pfu_kv_lookup "$PFU_CONFIG" Sudo no; CFG_SUDO=no; pfu_is_true "$PFU_KV_VALUE" && CFG_SUDO=yes
|
||||
_pfu_kv_lookup "$PFU_CONFIG" Polkit no; CFG_POLKIT=no; pfu_is_true "$PFU_KV_VALUE" && CFG_POLKIT=yes
|
||||
_fu_kv_lookup "$FU_CONFIG" Enabled no; CFG_ENABLED=no; fu_is_true "$FU_KV_VALUE" && CFG_ENABLED=yes
|
||||
_fu_kv_lookup "$FU_CONFIG" LockScreen yes; CFG_LOCK=no; fu_is_true "$FU_KV_VALUE" && CFG_LOCK=yes
|
||||
_fu_kv_lookup "$FU_CONFIG" Sudo no; CFG_SUDO=no; fu_is_true "$FU_KV_VALUE" && CFG_SUDO=yes
|
||||
_fu_kv_lookup "$FU_CONFIG" Polkit no; CFG_POLKIT=no; fu_is_true "$FU_KV_VALUE" && CFG_POLKIT=yes
|
||||
|
||||
_pfu_kv_lookup "$PFU_SYSCONFIG" Liveness light; CFG_LIVENESS="$PFU_KV_VALUE"
|
||||
_pfu_kv_lookup "$PFU_SYSCONFIG" Camera auto; CFG_CAMERA="$PFU_KV_VALUE"
|
||||
_fu_kv_lookup "$FU_SYSCONFIG" Liveness light; CFG_LIVENESS="$FU_KV_VALUE"
|
||||
_fu_kv_lookup "$FU_SYSCONFIG" Camera auto; CFG_CAMERA="$FU_KV_VALUE"
|
||||
return 0
|
||||
}
|
||||
+103
-103
@@ -2,184 +2,184 @@
|
||||
#
|
||||
# Asking the daemon.
|
||||
#
|
||||
# Through plasma-face-unlock-ctl, which prints every message as a line of tab
|
||||
# Through face-unlock-ctl, which prints every message as a line of tab
|
||||
# separated key=value pairs (see src/ctl/main.cpp). What comes back is parsed
|
||||
# into plain variables and arrays here, so the rest of the shell code never
|
||||
# sees the wire format.
|
||||
|
||||
# _pfu_fields <line>
|
||||
# Splits one line of ctl output into the associative array PFU_F.
|
||||
declare -A PFU_F=()
|
||||
# _fu_fields <line>
|
||||
# Splits one line of ctl output into the associative array FU_F.
|
||||
declare -A FU_F=()
|
||||
|
||||
_pfu_fields() {
|
||||
_fu_fields() {
|
||||
local line="$1" field
|
||||
local -a parts
|
||||
PFU_F=()
|
||||
FU_F=()
|
||||
IFS=$'\t' read -r -a parts <<< "$line"
|
||||
for field in "${parts[@]}"; do
|
||||
PFU_F["${field%%=*}"]="${field#*=}"
|
||||
FU_F["${field%%=*}"]="${field#*=}"
|
||||
done
|
||||
}
|
||||
|
||||
pfu_ctl() {
|
||||
"$PFU_CTL" "$@"
|
||||
fu_ctl() {
|
||||
"$FU_CTL" "$@"
|
||||
}
|
||||
|
||||
# pfu_status_load
|
||||
# PFU_ST_REACHABLE is yes when the daemon answered at all. Everything else
|
||||
# fu_status_load
|
||||
# FU_ST_REACHABLE is yes when the daemon answered at all. Everything else
|
||||
# is only filled in then.
|
||||
pfu_status_load() {
|
||||
fu_status_load() {
|
||||
local out
|
||||
PFU_ST_REACHABLE=no
|
||||
PFU_ST_FACES=0
|
||||
PFU_ST_LOCKOUT=0
|
||||
PFU_ST_LAST=0
|
||||
PFU_ST_PURPOSE=''
|
||||
PFU_ST_CAMERA=''
|
||||
PFU_ST_CAMERA_NAME=''
|
||||
PFU_ST_CAMERA_PRESENT=no
|
||||
PFU_ST_MODELS=no
|
||||
FU_ST_REACHABLE=no
|
||||
FU_ST_FACES=0
|
||||
FU_ST_LOCKOUT=0
|
||||
FU_ST_LAST=0
|
||||
FU_ST_PURPOSE=''
|
||||
FU_ST_CAMERA=''
|
||||
FU_ST_CAMERA_NAME=''
|
||||
FU_ST_CAMERA_PRESENT=no
|
||||
FU_ST_MODELS=no
|
||||
|
||||
out="$(pfu_ctl status 2>/dev/null | tail -n1)"
|
||||
_pfu_fields "$out"
|
||||
[[ ${PFU_F[ok]:-} == true ]] || return 1
|
||||
out="$(fu_ctl status 2>/dev/null | tail -n1)"
|
||||
_fu_fields "$out"
|
||||
[[ ${FU_F[ok]:-} == true ]] || return 1
|
||||
|
||||
PFU_ST_REACHABLE=yes
|
||||
PFU_ST_FACES="${PFU_F[faces]:-0}"
|
||||
PFU_ST_LOCKOUT="${PFU_F[lockout]:-0}"
|
||||
PFU_ST_LAST="${PFU_F[lastUnlock]:-0}"
|
||||
PFU_ST_PURPOSE="${PFU_F[lastPurpose]:-}"
|
||||
PFU_ST_CAMERA="${PFU_F[cameraPath]:-}"
|
||||
PFU_ST_CAMERA_NAME="${PFU_F[cameraName]:-}"
|
||||
PFU_ST_CAMERA_PRESENT="${PFU_F[cameraPresent]:-false}"
|
||||
PFU_ST_MODELS="${PFU_F[models]:-false}"
|
||||
FU_ST_REACHABLE=yes
|
||||
FU_ST_FACES="${FU_F[faces]:-0}"
|
||||
FU_ST_LOCKOUT="${FU_F[lockout]:-0}"
|
||||
FU_ST_LAST="${FU_F[lastUnlock]:-0}"
|
||||
FU_ST_PURPOSE="${FU_F[lastPurpose]:-}"
|
||||
FU_ST_CAMERA="${FU_F[cameraPath]:-}"
|
||||
FU_ST_CAMERA_NAME="${FU_F[cameraName]:-}"
|
||||
FU_ST_CAMERA_PRESENT="${FU_F[cameraPresent]:-false}"
|
||||
FU_ST_MODELS="${FU_F[models]:-false}"
|
||||
return 0
|
||||
}
|
||||
|
||||
# pfu_faces_load
|
||||
# fu_faces_load
|
||||
# The caller's faces, into parallel arrays.
|
||||
pfu_faces_load() {
|
||||
fu_faces_load() {
|
||||
local line
|
||||
PFU_FACE_IDS=() PFU_FACE_NAMES=() PFU_FACE_ON=() PFU_FACE_SAMPLES=() PFU_FACE_LEARNED=() PFU_FACE_CREATED=()
|
||||
FU_FACE_IDS=() FU_FACE_NAMES=() FU_FACE_ON=() FU_FACE_SAMPLES=() FU_FACE_LEARNED=() FU_FACE_CREATED=()
|
||||
|
||||
while IFS= read -r line; do
|
||||
_pfu_fields "$line"
|
||||
[[ ${PFU_F[event]:-} == item ]] || continue
|
||||
PFU_FACE_IDS+=("${PFU_F[id]}")
|
||||
PFU_FACE_NAMES+=("${PFU_F[name]}")
|
||||
PFU_FACE_ON+=("${PFU_F[enabled]}")
|
||||
PFU_FACE_SAMPLES+=("${PFU_F[samples]:-0}")
|
||||
PFU_FACE_LEARNED+=("${PFU_F[adaptive]:-0}")
|
||||
PFU_FACE_CREATED+=("${PFU_F[created]:-0}")
|
||||
done < <(pfu_ctl list 2>/dev/null)
|
||||
_fu_fields "$line"
|
||||
[[ ${FU_F[event]:-} == item ]] || continue
|
||||
FU_FACE_IDS+=("${FU_F[id]}")
|
||||
FU_FACE_NAMES+=("${FU_F[name]}")
|
||||
FU_FACE_ON+=("${FU_F[enabled]}")
|
||||
FU_FACE_SAMPLES+=("${FU_F[samples]:-0}")
|
||||
FU_FACE_LEARNED+=("${FU_F[adaptive]:-0}")
|
||||
FU_FACE_CREATED+=("${FU_F[created]:-0}")
|
||||
done < <(fu_ctl list 2>/dev/null)
|
||||
}
|
||||
|
||||
# pfu_cameras_load
|
||||
pfu_cameras_load() {
|
||||
# fu_cameras_load
|
||||
fu_cameras_load() {
|
||||
local line
|
||||
PFU_CAM_PATHS=() PFU_CAM_NAMES=() PFU_CAM_IR=()
|
||||
PFU_CAM_AUTO=''
|
||||
FU_CAM_PATHS=() FU_CAM_NAMES=() FU_CAM_IR=()
|
||||
FU_CAM_AUTO=''
|
||||
|
||||
while IFS= read -r line; do
|
||||
_pfu_fields "$line"
|
||||
case "${PFU_F[event]:-}" in
|
||||
_fu_fields "$line"
|
||||
case "${FU_F[event]:-}" in
|
||||
item)
|
||||
PFU_CAM_PATHS+=("${PFU_F[path]}")
|
||||
PFU_CAM_NAMES+=("${PFU_F[name]}")
|
||||
PFU_CAM_IR+=("${PFU_F[infrared]}")
|
||||
FU_CAM_PATHS+=("${FU_F[path]}")
|
||||
FU_CAM_NAMES+=("${FU_F[name]}")
|
||||
FU_CAM_IR+=("${FU_F[infrared]}")
|
||||
;;
|
||||
result)
|
||||
PFU_CAM_AUTO="${PFU_F[auto]:-}"
|
||||
FU_CAM_AUTO="${FU_F[auto]:-}"
|
||||
;;
|
||||
esac
|
||||
done < <(pfu_ctl cameras 2>/dev/null)
|
||||
done < <(fu_ctl cameras 2>/dev/null)
|
||||
}
|
||||
|
||||
# pfu_reason_text <reason>
|
||||
# fu_reason_text <reason>
|
||||
# What a daemon answer means, for people.
|
||||
pfu_reason_text() {
|
||||
fu_reason_text() {
|
||||
case "$1" in
|
||||
mismatch) pfu_msg "The face did not match." ;;
|
||||
spoof) pfu_msg "That looked like a photo or a screen." ;;
|
||||
liveness) pfu_msg "The face matched, but did not blink or move." ;;
|
||||
attention) pfu_msg "The face was not looking at the screen." ;;
|
||||
quality) pfu_msg "The picture was too dark, too blurry or too far away." ;;
|
||||
no-face) pfu_msg "No face in view." ;;
|
||||
lockout) pfu_msg "Face unlock is paused after too many tries. Unlock once with your password." ;;
|
||||
not-enrolled) pfu_msg "No face is set up yet." ;;
|
||||
camera) pfu_msg "The camera could not be used." ;;
|
||||
models) pfu_msg "The recognition models are missing. Reinstall the package." ;;
|
||||
lid-closed) pfu_msg "The lid is closed." ;;
|
||||
busy) pfu_msg "The camera is busy with another scan." ;;
|
||||
unreachable) pfu_msg "The face unlock service is not running." ;;
|
||||
denied) pfu_msg "Not allowed." ;;
|
||||
*) pfu_msg "Something went wrong (%s)." "$1" ;;
|
||||
mismatch) fu_msg "The face did not match." ;;
|
||||
spoof) fu_msg "That looked like a photo or a screen." ;;
|
||||
liveness) fu_msg "The face matched, but did not blink or move." ;;
|
||||
attention) fu_msg "The face was not looking at the screen." ;;
|
||||
quality) fu_msg "The picture was too dark, too blurry or too far away." ;;
|
||||
no-face) fu_msg "No face in view." ;;
|
||||
lockout) fu_msg "Face unlock is paused after too many tries. Unlock once with your password." ;;
|
||||
not-enrolled) fu_msg "No face is set up yet." ;;
|
||||
camera) fu_msg "The camera could not be used." ;;
|
||||
models) fu_msg "The recognition models are missing. Reinstall the package." ;;
|
||||
lid-closed) fu_msg "The lid is closed." ;;
|
||||
busy) fu_msg "The camera is busy with another scan." ;;
|
||||
unreachable) fu_msg "The face unlock service is not running." ;;
|
||||
denied) fu_msg "Not allowed." ;;
|
||||
*) fu_msg "Something went wrong (%s)." "$1" ;;
|
||||
esac
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
# pfu_test
|
||||
# fu_test
|
||||
# One scan, with everything the checks see on one line that keeps updating.
|
||||
# The bubble shows it too, if the agent is running.
|
||||
pfu_test() {
|
||||
fu_test() {
|
||||
local line started=0 shown='' score='-' matched=0
|
||||
|
||||
pfu_say " $(pfu_msg "Look at the camera. Blink once, or turn your head a little.")"
|
||||
fu_say " $(fu_msg "Look at the camera. Blink once, or turn your head a little.")"
|
||||
printf '\n'
|
||||
|
||||
while IFS= read -r line; do
|
||||
_pfu_fields "$line"
|
||||
case "${PFU_F[event]:-}" in
|
||||
_fu_fields "$line"
|
||||
case "${FU_F[event]:-}" in
|
||||
started)
|
||||
started=1
|
||||
;;
|
||||
face)
|
||||
printf '\r\033[K %s\n' "$(pfu_msg "Face found.")"
|
||||
printf '\r\033[K %s\n' "$(fu_msg "Face found.")"
|
||||
;;
|
||||
hint)
|
||||
case "${PFU_F[hint]}" in
|
||||
blink) printf '\r\033[K %s\n' "$(pfu_msg "Recognised. Now blink once, or turn your head a little.")" ;;
|
||||
look) printf '\r\033[K %s\n' "$(pfu_msg "Look at the screen.")" ;;
|
||||
closer) printf '\r\033[K %s\n' "$(pfu_msg "Move closer to the camera.")" ;;
|
||||
light) printf '\r\033[K %s\n' "$(pfu_msg "It is too dark to see your face.")" ;;
|
||||
case "${FU_F[hint]}" in
|
||||
blink) printf '\r\033[K %s\n' "$(fu_msg "Recognised. Now blink once, or turn your head a little.")" ;;
|
||||
look) printf '\r\033[K %s\n' "$(fu_msg "Look at the screen.")" ;;
|
||||
closer) printf '\r\033[K %s\n' "$(fu_msg "Move closer to the camera.")" ;;
|
||||
light) printf '\r\033[K %s\n' "$(fu_msg "It is too dark to see your face.")" ;;
|
||||
esac
|
||||
;;
|
||||
frame)
|
||||
[[ -n ${PFU_F[score]:-} ]] && score="${PFU_F[score]}"
|
||||
matched="${PFU_F[matched]:-0}"
|
||||
[[ -n ${FU_F[score]:-} ]] && score="${FU_F[score]}"
|
||||
matched="${FU_F[matched]:-0}"
|
||||
# match, turn of the head, eyes, and how close each photo check is
|
||||
# to firing, as numbers for anybody tuning it.
|
||||
printf -v shown ' %s %-6s %s %5s° %s %-5s %s %-4s %s %-4s %s %-4s %s %-4s' \
|
||||
"$(pfu_msg "match")" "$score" "$(pfu_msg "turn")" "${PFU_F[yaw]:-0}" \
|
||||
"$(pfu_msg "eyes")" "${PFU_F[eyes]:-0}" \
|
||||
"$(pfu_msg "depth")" "${PFU_F[depth]:-0}" "$(pfu_msg "blink")" "${PFU_F[blink]:-0}" \
|
||||
"$(pfu_msg "glare")" "${PFU_F[glare]:-0}" "$(pfu_msg "edge")" "${PFU_F[device]:-0}"
|
||||
[[ -n $PFU_INTERACTIVE ]] && printf '\r\033[K%s%s%s' "$PFU_C_DIM" "$shown" "$PFU_C_RESET"
|
||||
"$(fu_msg "match")" "$score" "$(fu_msg "turn")" "${FU_F[yaw]:-0}" \
|
||||
"$(fu_msg "eyes")" "${FU_F[eyes]:-0}" \
|
||||
"$(fu_msg "depth")" "${FU_F[depth]:-0}" "$(fu_msg "blink")" "${FU_F[blink]:-0}" \
|
||||
"$(fu_msg "glare")" "${FU_F[glare]:-0}" "$(fu_msg "edge")" "${FU_F[device]:-0}"
|
||||
[[ -n $FU_INTERACTIVE ]] && printf '\r\033[K%s%s%s' "$FU_C_DIM" "$shown" "$FU_C_RESET"
|
||||
;;
|
||||
result)
|
||||
printf '\r\033[K'
|
||||
if [[ ${PFU_F[ok]} == true ]]; then
|
||||
if [[ ${FU_F[ok]} == true ]]; then
|
||||
local how=''
|
||||
case "${PFU_F[liveness]:-}" in
|
||||
blink) how="$(pfu_msg "blink")" ;;
|
||||
depth) how="$(pfu_msg "head turn")" ;;
|
||||
case "${FU_F[liveness]:-}" in
|
||||
blink) how="$(fu_msg "blink")" ;;
|
||||
depth) how="$(fu_msg "head turn")" ;;
|
||||
esac
|
||||
pfu_ok "$(pfu_msg "Recognised as %s (match %s) in %s ms." "${PFU_F[name]}" "${PFU_F[score]}" "${PFU_F[ms]}")"
|
||||
[[ -n $how ]] && pfu_say " $(pfu_msg "Sign of life: %s" "$how")"
|
||||
fu_ok "$(fu_msg "Recognised as %s (match %s) in %s ms." "${FU_F[name]}" "${FU_F[score]}" "${FU_F[ms]}")"
|
||||
[[ -n $how ]] && fu_say " $(fu_msg "Sign of life: %s" "$how")"
|
||||
else
|
||||
pfu_bad "$(pfu_reason_text "${PFU_F[reason]}")"
|
||||
[[ -n ${PFU_F[message]:-} ]] && pfu_say " ${PFU_F[message]}"
|
||||
if [[ -n ${PFU_F[lockout]:-} ]]; then
|
||||
pfu_note "$(pfu_msg "That was too many tries. Face unlock is paused until you unlock with your password.")"
|
||||
fu_bad "$(fu_reason_text "${FU_F[reason]}")"
|
||||
[[ -n ${FU_F[message]:-} ]] && fu_say " ${FU_F[message]}"
|
||||
if [[ -n ${FU_F[lockout]:-} ]]; then
|
||||
fu_note "$(fu_msg "That was too many tries. Face unlock is paused until you unlock with your password.")"
|
||||
fi
|
||||
fi
|
||||
(( started )) || true
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
done < <(pfu_ctl test 2>/dev/null)
|
||||
done < <(fu_ctl test 2>/dev/null)
|
||||
|
||||
printf '\n'
|
||||
pfu_bad "$(pfu_reason_text unreachable)"
|
||||
fu_bad "$(fu_reason_text unreachable)"
|
||||
return 1
|
||||
}
|
||||
+265
-265
@@ -14,39 +14,39 @@
|
||||
# character, so the line discipline eats it instead of delivering it, and a
|
||||
# backspace typed while the interface was between reads simply vanishes.
|
||||
# Holding non-canonical mode for the whole interface removes the gap.
|
||||
PFU_TERM_SAVED=''
|
||||
FU_TERM_SAVED=''
|
||||
|
||||
pfu_ui_term_raw() {
|
||||
pfu_have stty || return 0
|
||||
fu_ui_term_raw() {
|
||||
fu_have stty || return 0
|
||||
[[ -t 0 ]] || return 0
|
||||
[[ -n $PFU_TERM_SAVED ]] && return 0
|
||||
[[ -n $FU_TERM_SAVED ]] && return 0
|
||||
|
||||
PFU_TERM_SAVED="$(stty -g 2>/dev/null)" || { PFU_TERM_SAVED=''; return 0; }
|
||||
FU_TERM_SAVED="$(stty -g 2>/dev/null)" || { FU_TERM_SAVED=''; return 0; }
|
||||
stty -icanon -echo min 1 time 0 2>/dev/null || true
|
||||
}
|
||||
|
||||
pfu_ui_term_restore() {
|
||||
[[ -n $PFU_TERM_SAVED ]] || return 0
|
||||
stty "$PFU_TERM_SAVED" 2>/dev/null || true
|
||||
PFU_TERM_SAVED=''
|
||||
fu_ui_term_restore() {
|
||||
[[ -n $FU_TERM_SAVED ]] || return 0
|
||||
stty "$FU_TERM_SAVED" 2>/dev/null || true
|
||||
FU_TERM_SAVED=''
|
||||
}
|
||||
|
||||
# Runs an action with the terminal handed back to normal line mode, so anything
|
||||
# it prints or prompts for (sudo's password prompt, above all) behaves the way
|
||||
# a program expects.
|
||||
pfu_ui_cooked() {
|
||||
pfu_ui_term_restore
|
||||
fu_ui_cooked() {
|
||||
fu_ui_term_restore
|
||||
"$@"
|
||||
local rc=$?
|
||||
pfu_ui_term_raw
|
||||
fu_ui_term_raw
|
||||
return $rc
|
||||
}
|
||||
|
||||
# pfu_read_key
|
||||
# fu_read_key
|
||||
# One keypress, resolved to a symbolic name. Arrow keys arrive as ESC [ A, so
|
||||
# the tail of the sequence is consumed here rather than being mistaken for
|
||||
# three separate presses.
|
||||
pfu_read_key() {
|
||||
fu_read_key() {
|
||||
local k rest
|
||||
|
||||
IFS= read -rsn1 k || return 1
|
||||
@@ -72,26 +72,26 @@ pfu_read_key() {
|
||||
esac
|
||||
}
|
||||
|
||||
# pfu_ui_read_line <initial>
|
||||
# A minimal line editor built on pfu_read_key, with the result in
|
||||
# PFU_LINE_RESULT. This exists instead of bash's own `read -r` because mixing
|
||||
# fu_ui_read_line <initial>
|
||||
# A minimal line editor built on fu_read_key, with the result in
|
||||
# FU_LINE_RESULT. This exists instead of bash's own `read -r` because mixing
|
||||
# line mode into a single-key interface breaks it: after one cooked-mode read
|
||||
# the following `read -sn1` stops receiving keystrokes entirely.
|
||||
PFU_LINE_RESULT=''
|
||||
FU_LINE_RESULT=''
|
||||
|
||||
pfu_ui_read_line() {
|
||||
fu_ui_read_line() {
|
||||
local buf="${1:-}" key
|
||||
|
||||
PFU_LINE_RESULT=''
|
||||
FU_LINE_RESULT=''
|
||||
printf '%s' "$buf"
|
||||
|
||||
while true; do
|
||||
key="$(pfu_read_key)" || { printf '\n'; return 1; }
|
||||
key="$(fu_read_key)" || { printf '\n'; return 1; }
|
||||
|
||||
case "$key" in
|
||||
enter)
|
||||
printf '\n'
|
||||
PFU_LINE_RESULT="$buf"
|
||||
FU_LINE_RESULT="$buf"
|
||||
return 0
|
||||
;;
|
||||
escape)
|
||||
@@ -118,88 +118,88 @@ pfu_ui_read_line() {
|
||||
done
|
||||
}
|
||||
|
||||
# _pfu_ui_take_notices
|
||||
# _fu_ui_take_notices
|
||||
# The messages the last action left, as lines for under a frame, in
|
||||
# PFU_UI_NOTICE_TEXT. Each is shown once.
|
||||
PFU_UI_NOTICE_TEXT=''
|
||||
# FU_UI_NOTICE_TEXT. Each is shown once.
|
||||
FU_UI_NOTICE_TEXT=''
|
||||
|
||||
_pfu_ui_take_notices() {
|
||||
_fu_ui_take_notices() {
|
||||
local n
|
||||
PFU_UI_NOTICE_TEXT=''
|
||||
(( ${#PFU_UI_NOTICES[@]} )) || return 0
|
||||
PFU_UI_NOTICE_TEXT=$'\n'
|
||||
for n in "${PFU_UI_NOTICES[@]}"; do
|
||||
PFU_UI_NOTICE_TEXT+=" $n"$'\n'
|
||||
FU_UI_NOTICE_TEXT=''
|
||||
(( ${#FU_UI_NOTICES[@]} )) || return 0
|
||||
FU_UI_NOTICE_TEXT=$'\n'
|
||||
for n in "${FU_UI_NOTICES[@]}"; do
|
||||
FU_UI_NOTICE_TEXT+=" $n"$'\n'
|
||||
done
|
||||
PFU_UI_NOTICES=()
|
||||
FU_UI_NOTICES=()
|
||||
}
|
||||
|
||||
# pfu_ui_confirm <question>
|
||||
pfu_ui_confirm() {
|
||||
# fu_ui_confirm <question>
|
||||
fu_ui_confirm() {
|
||||
local key hint yes
|
||||
# TRANSLATORS: the letter after "[" is the key for yes. y works too.
|
||||
hint="$(pfu_msg "[y/N]")"
|
||||
hint="$(fu_msg "[y/N]")"
|
||||
yes="${hint:1:1}"
|
||||
printf '\n %s %s ' "$1" "$hint"
|
||||
key="$(pfu_read_key)" || return 1
|
||||
key="$(fu_read_key)" || return 1
|
||||
printf '%s\n' "$key"
|
||||
[[ ${key,,} == y || ${key,,} == "${yes,,}" ]]
|
||||
}
|
||||
|
||||
# _pfu_width <text>
|
||||
# The columns the text takes, into PFU_WIDTH. ${#s} counts characters, but
|
||||
# _fu_width <text>
|
||||
# The columns the text takes, into FU_WIDTH. ${#s} counts characters, but
|
||||
# Chinese, Japanese and Korean ones take two columns each.
|
||||
PFU_WIDTH=0
|
||||
FU_WIDTH=0
|
||||
|
||||
_pfu_width() {
|
||||
_fu_width() {
|
||||
local wide="${1//[^ -〿-ヿ㐀-䶿一-鿿가-豈--⦆]/}"
|
||||
PFU_WIDTH=$(( ${#1} + ${#wide} ))
|
||||
FU_WIDTH=$(( ${#1} + ${#wide} ))
|
||||
}
|
||||
|
||||
# _pfu_row <label> <value>
|
||||
# _fu_row <label> <value>
|
||||
# printf's %-28s pads by bytes, so a label containing "ü" comes out one column
|
||||
# short. The padding is computed here instead.
|
||||
_pfu_row() {
|
||||
_fu_row() {
|
||||
local label="$1" value="$2" pad
|
||||
_pfu_width "$label"
|
||||
pad=$(( 30 - PFU_WIDTH ))
|
||||
_fu_width "$label"
|
||||
pad=$(( 30 - FU_WIDTH ))
|
||||
(( pad < 0 )) && pad=0
|
||||
printf ' %s%*s %s\n' "$label" "$pad" '' "$value"
|
||||
}
|
||||
|
||||
_pfu_onoff() {
|
||||
_fu_onoff() {
|
||||
if [[ $1 == yes ]]; then
|
||||
printf '%s%s%s' "$PFU_C_GREEN" "$(pfu_msg "ON")" "$PFU_C_RESET"
|
||||
printf '%s%s%s' "$FU_C_GREEN" "$(fu_msg "ON")" "$FU_C_RESET"
|
||||
else
|
||||
printf '%s%s%s' "$PFU_C_DIM" "$(pfu_msg "OFF")" "$PFU_C_RESET"
|
||||
printf '%s%s%s' "$FU_C_DIM" "$(fu_msg "OFF")" "$FU_C_RESET"
|
||||
fi
|
||||
}
|
||||
|
||||
_pfu_small_onoff() {
|
||||
_fu_small_onoff() {
|
||||
if [[ $1 == yes ]]; then
|
||||
printf '%s%s%s' "$PFU_C_GREEN" "$(pfu_msg "on")" "$PFU_C_RESET"
|
||||
printf '%s%s%s' "$FU_C_GREEN" "$(fu_msg "on")" "$FU_C_RESET"
|
||||
else
|
||||
printf '%s%s%s' "$PFU_C_DIM" "$(pfu_msg "off")" "$PFU_C_RESET"
|
||||
printf '%s%s%s' "$FU_C_DIM" "$(fu_msg "off")" "$FU_C_RESET"
|
||||
fi
|
||||
}
|
||||
|
||||
# pfu_value_label <Key> <value>
|
||||
# fu_value_label <Key> <value>
|
||||
# How a setting's value reads in the menu.
|
||||
pfu_value_label() {
|
||||
fu_value_label() {
|
||||
case "$1:$2" in
|
||||
Liveness:heavy) pfu_msg "strict" ;;
|
||||
Liveness:light) pfu_msg "basic" ;;
|
||||
Liveness:off) pfu_msg "off" ;;
|
||||
Strictness:normal) pfu_msg "normal" ;;
|
||||
Strictness:strict) pfu_msg "strict" ;;
|
||||
Strictness:relaxed) pfu_msg "relaxed" ;;
|
||||
BubbleStyle:full) pfu_msg "island with the face" ;;
|
||||
BubbleStyle:minimal) pfu_msg "small pill with a lock" ;;
|
||||
AnimationSpeed:normal) pfu_msg "normal" ;;
|
||||
AnimationSpeed:fast) pfu_msg "fast" ;;
|
||||
AnimationSpeed:slow) pfu_msg "slow" ;;
|
||||
ScanSeconds:*) pfu_msg "%s seconds" "$2" ;;
|
||||
Camera:auto) pfu_msg "automatic" ;;
|
||||
Liveness:heavy) fu_msg "strict" ;;
|
||||
Liveness:light) fu_msg "basic" ;;
|
||||
Liveness:off) fu_msg "off" ;;
|
||||
Strictness:normal) fu_msg "normal" ;;
|
||||
Strictness:strict) fu_msg "strict" ;;
|
||||
Strictness:relaxed) fu_msg "relaxed" ;;
|
||||
BubbleStyle:full) fu_msg "island with the face" ;;
|
||||
BubbleStyle:minimal) fu_msg "small pill with a lock" ;;
|
||||
AnimationSpeed:normal) fu_msg "normal" ;;
|
||||
AnimationSpeed:fast) fu_msg "fast" ;;
|
||||
AnimationSpeed:slow) fu_msg "slow" ;;
|
||||
ScanSeconds:*) fu_msg "%s seconds" "$2" ;;
|
||||
Camera:auto) fu_msg "automatic" ;;
|
||||
*) printf '%s' "$2" ;;
|
||||
esac
|
||||
}
|
||||
@@ -208,55 +208,55 @@ pfu_value_label() {
|
||||
# Status
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# pfu_ui_status
|
||||
# fu_ui_status
|
||||
# Shared by the `status` subcommand and the menu header.
|
||||
pfu_ui_status() {
|
||||
fu_ui_status() {
|
||||
local names='' i camera
|
||||
|
||||
pfu_config_load
|
||||
pfu_status_load
|
||||
fu_config_load
|
||||
fu_status_load
|
||||
|
||||
_pfu_row "$(pfu_msg "Face unlock")" "$(_pfu_onoff "$CFG_ENABLED")"
|
||||
_fu_row "$(fu_msg "Face unlock")" "$(_fu_onoff "$CFG_ENABLED")"
|
||||
printf '\n'
|
||||
|
||||
if [[ $PFU_ST_REACHABLE != yes ]]; then
|
||||
_pfu_row "$(pfu_msg "Service")" "${PFU_C_YELLOW}$(pfu_msg "not running")${PFU_C_RESET}"
|
||||
if [[ $FU_ST_REACHABLE != yes ]]; then
|
||||
_fu_row "$(fu_msg "Service")" "${FU_C_YELLOW}$(fu_msg "not running")${FU_C_RESET}"
|
||||
if [[ $CFG_ENABLED == yes ]]; then
|
||||
printf '\n %s%s%s\n' "$PFU_C_DIM" "$(pfu_msg "Turning face unlock on again starts it.")" "$PFU_C_RESET"
|
||||
printf '\n %s%s%s\n' "$FU_C_DIM" "$(fu_msg "Turning face unlock on again starts it.")" "$FU_C_RESET"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
pfu_faces_load
|
||||
for i in "${!PFU_FACE_NAMES[@]}"; do
|
||||
[[ ${PFU_FACE_ON[i]} == true ]] || continue
|
||||
names="${names:+$names, }${PFU_FACE_NAMES[i]}"
|
||||
fu_faces_load
|
||||
for i in "${!FU_FACE_NAMES[@]}"; do
|
||||
[[ ${FU_FACE_ON[i]} == true ]] || continue
|
||||
names="${names:+$names, }${FU_FACE_NAMES[i]}"
|
||||
done
|
||||
if (( ${#PFU_FACE_IDS[@]} == 0 )); then
|
||||
_pfu_row "$(pfu_msg "Faces")" "${PFU_C_YELLOW}$(pfu_msg "none set up yet")${PFU_C_RESET}"
|
||||
if (( ${#FU_FACE_IDS[@]} == 0 )); then
|
||||
_fu_row "$(fu_msg "Faces")" "${FU_C_YELLOW}$(fu_msg "none set up yet")${FU_C_RESET}"
|
||||
else
|
||||
_pfu_row "$(pfu_msg "Faces")" "${PFU_ST_FACES} ${PFU_C_DIM}(${names:-$(pfu_msg "all turned off")})${PFU_C_RESET}"
|
||||
_fu_row "$(fu_msg "Faces")" "${FU_ST_FACES} ${FU_C_DIM}(${names:-$(fu_msg "all turned off")})${FU_C_RESET}"
|
||||
fi
|
||||
|
||||
if [[ $PFU_ST_CAMERA_PRESENT == true ]]; then
|
||||
camera="${PFU_ST_CAMERA_NAME:-$PFU_ST_CAMERA}"
|
||||
if [[ $FU_ST_CAMERA_PRESENT == true ]]; then
|
||||
camera="${FU_ST_CAMERA_NAME:-$FU_ST_CAMERA}"
|
||||
else
|
||||
camera="${PFU_C_YELLOW}$(pfu_msg "none found")${PFU_C_RESET}"
|
||||
camera="${FU_C_YELLOW}$(fu_msg "none found")${FU_C_RESET}"
|
||||
fi
|
||||
_pfu_row "$(pfu_msg "Camera")" "$camera"
|
||||
_fu_row "$(fu_msg "Camera")" "$camera"
|
||||
|
||||
_pfu_row "$(pfu_msg "Lock screen")" "$(_pfu_small_onoff "$( [[ $CFG_ENABLED == yes && $CFG_LOCK == yes ]] && echo yes || echo no)")"
|
||||
_pfu_row "$(pfu_msg "sudo")" "$(_pfu_small_onoff "$(pfu_pam_enabled sudo && echo yes || echo no)")"
|
||||
_pfu_row "$(pfu_msg "Admin prompts")" "$(_pfu_small_onoff "$(pfu_pam_enabled polkit-1 && echo yes || echo no)")"
|
||||
_pfu_row "$(pfu_msg "Photo check")" "$(pfu_value_label Liveness "$CFG_LIVENESS")"
|
||||
_fu_row "$(fu_msg "Lock screen")" "$(_fu_small_onoff "$( [[ $CFG_ENABLED == yes && $CFG_LOCK == yes ]] && echo yes || echo no)")"
|
||||
_fu_row "$(fu_msg "sudo")" "$(_fu_small_onoff "$(fu_pam_enabled sudo && echo yes || echo no)")"
|
||||
_fu_row "$(fu_msg "Admin prompts")" "$(_fu_small_onoff "$(fu_pam_enabled polkit-1 && echo yes || echo no)")"
|
||||
_fu_row "$(fu_msg "Photo check")" "$(fu_value_label Liveness "$CFG_LIVENESS")"
|
||||
|
||||
if (( PFU_ST_LOCKOUT > 0 )); then
|
||||
_pfu_row "$(pfu_msg "Paused")" "${PFU_C_YELLOW}$(pfu_msg "for %d more minutes, or until the password is used" "$(( (PFU_ST_LOCKOUT + 59) / 60 ))")${PFU_C_RESET}"
|
||||
if (( FU_ST_LOCKOUT > 0 )); then
|
||||
_fu_row "$(fu_msg "Paused")" "${FU_C_YELLOW}$(fu_msg "for %d more minutes, or until the password is used" "$(( (FU_ST_LOCKOUT + 59) / 60 ))")${FU_C_RESET}"
|
||||
fi
|
||||
_pfu_row "$(pfu_msg "Last unlock")" "$(pfu_time_ago "$PFU_ST_LAST")"
|
||||
_fu_row "$(fu_msg "Last unlock")" "$(fu_time_ago "$FU_ST_LAST")"
|
||||
|
||||
if [[ $PFU_ST_MODELS != true ]]; then
|
||||
printf '\n %s%s%s\n' "$PFU_C_RED" "$(pfu_msg "The recognition models are missing. Reinstall the package.")" "$PFU_C_RESET"
|
||||
if [[ $FU_ST_MODELS != true ]]; then
|
||||
printf '\n %s%s%s\n' "$FU_C_RED" "$(fu_msg "The recognition models are missing. Reinstall the package.")" "$FU_C_RESET"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ pfu_ui_status() {
|
||||
# type bool, choice (steps through the choices) or camera
|
||||
# needs a bool setting this one does nothing without; it is dimmed while
|
||||
# that is off
|
||||
PFU_SETTINGS=(
|
||||
FU_SETTINGS=(
|
||||
"group|Lock screen"
|
||||
"user|LockScreen|bool|yes|Unlock with your face"
|
||||
"user|ScanOnWake|bool|yes|Scan when you come back||LockScreen"
|
||||
@@ -293,85 +293,85 @@ PFU_SETTINGS=(
|
||||
"user|BubbleForPrompts|bool|yes|Also for sudo and admin prompts||Bubble"
|
||||
)
|
||||
|
||||
# pfu_setting_help <Key> <value>
|
||||
# fu_setting_help <Key> <value>
|
||||
# What a setting does, shown under the list for the selected one.
|
||||
pfu_setting_help() {
|
||||
fu_setting_help() {
|
||||
case "$1:$2" in
|
||||
LockScreen:*) pfu_msg "Unlocks the lock screen when it sees your face. Off: only your password works there." ;;
|
||||
ScanOnWake:*) pfu_msg "Scans when you press a key or move the mouse on the lock screen, and when the computer wakes up." ;;
|
||||
ScanOnLock:*) pfu_msg "Scans as soon as the screen locks. Off by default: if you lock it yourself, it would unlock again right away." ;;
|
||||
sudo:*) pfu_msg "sudo takes your face instead of the password. No match: you type the password as usual." ;;
|
||||
polkit-1:*) pfu_msg "The password windows of Plasma and apps, for example when you install software. No match: you type the password." ;;
|
||||
Liveness:heavy) pfu_msg "You have to blink or turn your head a little. This also stops printed photos." ;;
|
||||
Liveness:off) pfu_msg "No check at all. Only for trying out a camera." ;;
|
||||
Liveness:*) pfu_msg "Stops photos on a phone, a tablet or glossy paper. You do not have to blink. A matte printed photo can get through." ;;
|
||||
Strictness:strict) pfu_msg "Fewer wrong matches, but it may not know you with glasses or in bad light." ;;
|
||||
Strictness:relaxed) pfu_msg "Knows you more easily, but also somebody who looks a lot like you." ;;
|
||||
Strictness:*) pfu_msg "The default. Right for most people." ;;
|
||||
Attention:*) pfu_msg "Your eyes have to be open and on the screen. So it does not unlock while you look away or sleep." ;;
|
||||
Camera:*) pfu_msg "Automatic takes the first normal camera. After a change, set up your face again. An infrared camera needs its light on (linux-enable-ir-emitter)." ;;
|
||||
ScanSeconds:*) pfu_msg "How long the camera looks for your face before it gives up." ;;
|
||||
Adapt:*) pfu_msg "After a sure match it keeps how you look now. So a new haircut or glasses need no new setup." ;;
|
||||
SkipLidClosed:*) pfu_msg "No scan while the laptop is closed, for example at a desk with an external screen." ;;
|
||||
Bubble:*) pfu_msg "The bubble at the top of the screen shows what the camera is doing." ;;
|
||||
BubbleStyle:minimal) pfu_msg "A small pill with a lock that opens." ;;
|
||||
BubbleStyle:*) pfu_msg "An island with a face that looks around, then rings and a tick." ;;
|
||||
AnimationSpeed:*) pfu_msg "How fast the bubble moves." ;;
|
||||
BubbleForPrompts:*) pfu_msg "Shows the bubble when sudo or an admin prompt scans your face, too." ;;
|
||||
LockScreen:*) fu_msg "Unlocks the lock screen when it sees your face. Off: only your password works there." ;;
|
||||
ScanOnWake:*) fu_msg "Scans when you press a key or move the mouse on the lock screen, and when the computer wakes up." ;;
|
||||
ScanOnLock:*) fu_msg "Scans as soon as the screen locks. Off by default: if you lock it yourself, it would unlock again right away." ;;
|
||||
sudo:*) fu_msg "sudo takes your face instead of the password. No match: you type the password as usual." ;;
|
||||
polkit-1:*) fu_msg "The password windows of Plasma and apps, for example when you install software. No match: you type the password." ;;
|
||||
Liveness:heavy) fu_msg "You have to blink or turn your head a little. This also stops printed photos." ;;
|
||||
Liveness:off) fu_msg "No check at all. Only for trying out a camera." ;;
|
||||
Liveness:*) fu_msg "Stops photos on a phone, a tablet or glossy paper. You do not have to blink. A matte printed photo can get through." ;;
|
||||
Strictness:strict) fu_msg "Fewer wrong matches, but it may not know you with glasses or in bad light." ;;
|
||||
Strictness:relaxed) fu_msg "Knows you more easily, but also somebody who looks a lot like you." ;;
|
||||
Strictness:*) fu_msg "The default. Right for most people." ;;
|
||||
Attention:*) fu_msg "Your eyes have to be open and on the screen. So it does not unlock while you look away or sleep." ;;
|
||||
Camera:*) fu_msg "Automatic takes the first normal camera. After a change, set up your face again. An infrared camera needs its light on (linux-enable-ir-emitter)." ;;
|
||||
ScanSeconds:*) fu_msg "How long the camera looks for your face before it gives up." ;;
|
||||
Adapt:*) fu_msg "After a sure match it keeps how you look now. So a new haircut or glasses need no new setup." ;;
|
||||
SkipLidClosed:*) fu_msg "No scan while the laptop is closed, for example at a desk with an external screen." ;;
|
||||
Bubble:*) fu_msg "The bubble at the top of the screen shows what the camera is doing." ;;
|
||||
BubbleStyle:minimal) fu_msg "A small pill with a lock that opens." ;;
|
||||
BubbleStyle:*) fu_msg "An island with a face that looks around, then rings and a tick." ;;
|
||||
AnimationSpeed:*) fu_msg "How fast the bubble moves." ;;
|
||||
BubbleForPrompts:*) fu_msg "Shows the bubble when sudo or an admin prompt scans your face, too." ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# _pfu_wrap <width> <text>
|
||||
# Word wrap, into PFU_WRAP_LINES.
|
||||
PFU_WRAP_LINES=()
|
||||
# _fu_wrap <width> <text>
|
||||
# Word wrap, into FU_WRAP_LINES.
|
||||
FU_WRAP_LINES=()
|
||||
|
||||
_pfu_wrap() {
|
||||
_fu_wrap() {
|
||||
local width="$1" word line='' used=0 c i
|
||||
local -a words
|
||||
PFU_WRAP_LINES=()
|
||||
FU_WRAP_LINES=()
|
||||
read -r -a words <<< "$2"
|
||||
for word in "${words[@]}"; do
|
||||
_pfu_width "$word"
|
||||
if (( used > 0 && used + 1 + PFU_WIDTH > width )); then
|
||||
PFU_WRAP_LINES+=("$line")
|
||||
_fu_width "$word"
|
||||
if (( used > 0 && used + 1 + FU_WIDTH > width )); then
|
||||
FU_WRAP_LINES+=("$line")
|
||||
line='' used=0
|
||||
fi
|
||||
(( used > 0 )) && line+=' ' used=$(( used + 1 ))
|
||||
if (( used + PFU_WIDTH <= width )); then
|
||||
line+="$word" used=$(( used + PFU_WIDTH ))
|
||||
if (( used + FU_WIDTH <= width )); then
|
||||
line+="$word" used=$(( used + FU_WIDTH ))
|
||||
continue
|
||||
fi
|
||||
# Longer than a line: Chinese and Japanese have no spaces, so break
|
||||
# between any two characters.
|
||||
for (( i = 0; i < ${#word}; i++ )); do
|
||||
c="${word:i:1}"
|
||||
_pfu_width "$c"
|
||||
if (( used + PFU_WIDTH > width )); then
|
||||
PFU_WRAP_LINES+=("$line")
|
||||
_fu_width "$c"
|
||||
if (( used + FU_WIDTH > width )); then
|
||||
FU_WRAP_LINES+=("$line")
|
||||
line='' used=0
|
||||
fi
|
||||
line+="$c" used=$(( used + PFU_WIDTH ))
|
||||
line+="$c" used=$(( used + FU_WIDTH ))
|
||||
done
|
||||
done
|
||||
[[ -n $line ]] && PFU_WRAP_LINES+=("$line")
|
||||
[[ -n $line ]] && FU_WRAP_LINES+=("$line")
|
||||
return 0
|
||||
}
|
||||
|
||||
# _pfu_setting_value <scope> <Key> <default>
|
||||
# The current value, in PFU_SETTING_VALUE.
|
||||
PFU_SETTING_VALUE=''
|
||||
# _fu_setting_value <scope> <Key> <default>
|
||||
# The current value, in FU_SETTING_VALUE.
|
||||
FU_SETTING_VALUE=''
|
||||
|
||||
_pfu_setting_value() {
|
||||
_fu_setting_value() {
|
||||
case "$1" in
|
||||
user) _pfu_kv_lookup "$PFU_CONFIG" "$2" "$3"; PFU_SETTING_VALUE="$PFU_KV_VALUE" ;;
|
||||
sys) _pfu_kv_lookup "$PFU_SYSCONFIG" "$2" "$3"; PFU_SETTING_VALUE="$PFU_KV_VALUE" ;;
|
||||
pam) if pfu_pam_enabled "$2"; then PFU_SETTING_VALUE=yes; else PFU_SETTING_VALUE=no; fi ;;
|
||||
user) _fu_kv_lookup "$FU_CONFIG" "$2" "$3"; FU_SETTING_VALUE="$FU_KV_VALUE" ;;
|
||||
sys) _fu_kv_lookup "$FU_SYSCONFIG" "$2" "$3"; FU_SETTING_VALUE="$FU_KV_VALUE" ;;
|
||||
pam) if fu_pam_enabled "$2"; then FU_SETTING_VALUE=yes; else FU_SETTING_VALUE=no; fi ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# _pfu_step <current> <step> <choice>...
|
||||
# _fu_step <current> <step> <choice>...
|
||||
# The choice <step> (1 or -1) away from the current one, round at the ends.
|
||||
_pfu_step() {
|
||||
_fu_step() {
|
||||
local current="$1" step="$2" i
|
||||
shift 2
|
||||
local -a all=("$@")
|
||||
@@ -384,100 +384,100 @@ _pfu_step() {
|
||||
printf '%s\n' "${all[0]}"
|
||||
}
|
||||
|
||||
# _pfu_next_choice <current> <a,b,c> <step>
|
||||
_pfu_next_choice() {
|
||||
# _fu_next_choice <current> <a,b,c> <step>
|
||||
_fu_next_choice() {
|
||||
local -a choices
|
||||
IFS=',' read -r -a choices <<< "$2"
|
||||
_pfu_step "$1" "$3" "${choices[@]}"
|
||||
_fu_step "$1" "$3" "${choices[@]}"
|
||||
}
|
||||
|
||||
# _pfu_next_camera <current> <step>
|
||||
_pfu_next_camera() {
|
||||
pfu_cameras_load
|
||||
_pfu_step "$1" "$2" auto "${PFU_CAM_PATHS[@]}"
|
||||
# _fu_next_camera <current> <step>
|
||||
_fu_next_camera() {
|
||||
fu_cameras_load
|
||||
_fu_step "$1" "$2" auto "${FU_CAM_PATHS[@]}"
|
||||
}
|
||||
|
||||
_pfu_camera_label() {
|
||||
_fu_camera_label() {
|
||||
local value="$1" i
|
||||
if [[ $value == auto ]]; then
|
||||
for i in "${!PFU_CAM_PATHS[@]}"; do
|
||||
if [[ ${PFU_CAM_PATHS[i]} == "$PFU_CAM_AUTO" ]]; then
|
||||
pfu_msg "automatic (%s)" "${PFU_CAM_NAMES[i]}"
|
||||
for i in "${!FU_CAM_PATHS[@]}"; do
|
||||
if [[ ${FU_CAM_PATHS[i]} == "$FU_CAM_AUTO" ]]; then
|
||||
fu_msg "automatic (%s)" "${FU_CAM_NAMES[i]}"
|
||||
return
|
||||
fi
|
||||
done
|
||||
pfu_msg "automatic"
|
||||
fu_msg "automatic"
|
||||
return
|
||||
fi
|
||||
for i in "${!PFU_CAM_PATHS[@]}"; do
|
||||
if [[ ${PFU_CAM_PATHS[i]} == "$value" ]]; then
|
||||
printf '%s' "${PFU_CAM_NAMES[i]}"
|
||||
[[ ${PFU_CAM_IR[i]} == true ]] && printf ' %s' "$(pfu_msg "(infrared)")"
|
||||
for i in "${!FU_CAM_PATHS[@]}"; do
|
||||
if [[ ${FU_CAM_PATHS[i]} == "$value" ]]; then
|
||||
printf '%s' "${FU_CAM_NAMES[i]}"
|
||||
[[ ${FU_CAM_IR[i]} == true ]] && printf ' %s' "$(fu_msg "(infrared)")"
|
||||
return
|
||||
fi
|
||||
done
|
||||
printf '%s %s' "$value" "$(pfu_msg "(not connected)")"
|
||||
printf '%s %s' "$value" "$(fu_msg "(not connected)")"
|
||||
}
|
||||
|
||||
# _pfu_setting_change <scope> <Key> <type> <current> <choices> <step>
|
||||
_pfu_setting_change() {
|
||||
# _fu_setting_change <scope> <Key> <type> <current> <choices> <step>
|
||||
_fu_setting_change() {
|
||||
local scope="$1" key="$2" type="$3" current="$4" choices="$5" step="$6" next
|
||||
|
||||
case "$type" in
|
||||
bool) if pfu_is_true "$current"; then next=no; else next=yes; fi ;;
|
||||
choice) next="$(_pfu_next_choice "$current" "$choices" "$step")" ;;
|
||||
camera) next="$(_pfu_next_camera "$current" "$step")" ;;
|
||||
bool) if fu_is_true "$current"; then next=no; else next=yes; fi ;;
|
||||
choice) next="$(_fu_next_choice "$current" "$choices" "$step")" ;;
|
||||
camera) next="$(_fu_next_camera "$current" "$step")" ;;
|
||||
esac
|
||||
|
||||
case "$scope" in
|
||||
user)
|
||||
pfu_config_set "$key" "$next" || pfu_bad "$(pfu_msg "Could not save the setting.")"
|
||||
fu_config_set "$key" "$next" || fu_bad "$(fu_msg "Could not save the setting.")"
|
||||
;;
|
||||
sys)
|
||||
printf '\n'
|
||||
pfu_ui_cooked pfu_root set "$key" "$next" || pfu_bad "$(pfu_msg "Could not save the setting.")"
|
||||
PFU_KV_CACHE=()
|
||||
fu_ui_cooked fu_root set "$key" "$next" || fu_bad "$(fu_msg "Could not save the setting.")"
|
||||
FU_KV_CACHE=()
|
||||
;;
|
||||
pam)
|
||||
printf '\n'
|
||||
if [[ $next == yes ]]; then
|
||||
pfu_ui_cooked pfu_root pam-enable "$key" || pfu_bad "$(pfu_msg "Could not save the setting.")"
|
||||
fu_ui_cooked fu_root pam-enable "$key" || fu_bad "$(fu_msg "Could not save the setting.")"
|
||||
else
|
||||
pfu_ui_cooked pfu_root pam-disable "$key" || pfu_bad "$(pfu_msg "Could not save the setting.")"
|
||||
fu_ui_cooked fu_root pam-disable "$key" || fu_bad "$(fu_msg "Could not save the setting.")"
|
||||
fi
|
||||
# Remembered, so that turning face unlock off and on again brings
|
||||
# it back.
|
||||
case "$key" in
|
||||
sudo) pfu_config_set Sudo "$next" ;;
|
||||
polkit-1) pfu_config_set Polkit "$next" ;;
|
||||
sudo) fu_config_set Sudo "$next" ;;
|
||||
polkit-1) fu_config_set Polkit "$next" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# pfu_ui_settings
|
||||
# fu_ui_settings
|
||||
# A cursor list in groups, with what the selected setting does under it. The
|
||||
# frame is assembled in memory and written once, and everything constant is
|
||||
# resolved before the loop.
|
||||
pfu_ui_settings() {
|
||||
fu_ui_settings() {
|
||||
local -a scopes=() keys=() types=() defaults=() labels=() widths=() choices=() needs=() values=() rows=()
|
||||
local spec scope key type default label choice need locale i j frame row pad dirty=1 cursor=0 shown
|
||||
local width=0 wrap cols
|
||||
|
||||
locale="$(pfu_ui_locale)"
|
||||
for spec in "${PFU_SETTINGS[@]}"; do
|
||||
locale="$(fu_ui_locale)"
|
||||
for spec in "${FU_SETTINGS[@]}"; do
|
||||
IFS='|' read -r scope key type default label choice need <<< "$spec"
|
||||
# A heading has its label where the key would be.
|
||||
[[ $scope == group ]] && label="$key" key=''
|
||||
scopes+=("$scope"); keys+=("$key"); types+=("$type"); defaults+=("$default")
|
||||
choices+=("$choice"); needs+=("$need")
|
||||
pfu_msg_into "$locale" "$label"
|
||||
labels+=("$PFU_MSG_RESULT")
|
||||
_pfu_width "$PFU_MSG_RESULT"
|
||||
widths+=("$PFU_WIDTH")
|
||||
fu_msg_into "$locale" "$label"
|
||||
labels+=("$FU_MSG_RESULT")
|
||||
_fu_width "$FU_MSG_RESULT"
|
||||
widths+=("$FU_WIDTH")
|
||||
if [[ $scope != group ]]; then
|
||||
rows+=($(( ${#keys[@]} - 1 )))
|
||||
(( PFU_WIDTH > width )) && width=$PFU_WIDTH
|
||||
(( FU_WIDTH > width )) && width=$FU_WIDTH
|
||||
fi
|
||||
done
|
||||
local count=${#rows[@]}
|
||||
@@ -491,77 +491,77 @@ pfu_ui_settings() {
|
||||
rule="${rule// /─}"
|
||||
|
||||
local title hint shared l_on l_off
|
||||
pfu_msg_into "$locale" "Settings"; title="$PFU_MSG_RESULT"
|
||||
pfu_msg_into "$locale" "↑↓ select ←→ or Space: change q: back"; hint="$PFU_MSG_RESULT"
|
||||
pfu_msg_into "$locale" "for all users, asks for your password"; shared="$PFU_MSG_RESULT"
|
||||
pfu_msg_into "$locale" "ON"; l_on="$PFU_MSG_RESULT"
|
||||
pfu_msg_into "$locale" "OFF"; l_off="$PFU_MSG_RESULT"
|
||||
fu_msg_into "$locale" "Settings"; title="$FU_MSG_RESULT"
|
||||
fu_msg_into "$locale" "↑↓ select ←→ or Space: change q: back"; hint="$FU_MSG_RESULT"
|
||||
fu_msg_into "$locale" "for all users, asks for your password"; shared="$FU_MSG_RESULT"
|
||||
fu_msg_into "$locale" "ON"; l_on="$FU_MSG_RESULT"
|
||||
fu_msg_into "$locale" "OFF"; l_off="$FU_MSG_RESULT"
|
||||
|
||||
local clearseq
|
||||
clearseq="$(clear 2>/dev/null)" || clearseq=$'\033[H\033[2J'
|
||||
|
||||
pfu_cameras_load
|
||||
fu_cameras_load
|
||||
|
||||
while true; do
|
||||
if (( dirty )); then
|
||||
PFU_KV_CACHE=()
|
||||
FU_KV_CACHE=()
|
||||
declare -A current=()
|
||||
for i in "${rows[@]}"; do
|
||||
_pfu_setting_value "${scopes[i]}" "${keys[i]}" "${defaults[i]}"
|
||||
values[i]="$PFU_SETTING_VALUE"
|
||||
current[${keys[i]}]="$PFU_SETTING_VALUE"
|
||||
_fu_setting_value "${scopes[i]}" "${keys[i]}" "${defaults[i]}"
|
||||
values[i]="$FU_SETTING_VALUE"
|
||||
current[${keys[i]}]="$FU_SETTING_VALUE"
|
||||
done
|
||||
dirty=0
|
||||
fi
|
||||
|
||||
frame="$clearseq"$'\n'"${PFU_C_BOLD}${PFU_C_BLUE} ${title}${PFU_C_RESET}"$'\n'
|
||||
frame="$clearseq"$'\n'"${FU_C_BOLD}${FU_C_BLUE} ${title}${FU_C_RESET}"$'\n'
|
||||
|
||||
local selected=${rows[cursor]} marker before after dim
|
||||
for i in "${!keys[@]}"; do
|
||||
if [[ ${scopes[i]} == group ]]; then
|
||||
frame+=$'\n'" ${PFU_C_BOLD}${labels[i]}${PFU_C_RESET}"
|
||||
frame+=$'\n'" ${FU_C_BOLD}${labels[i]}${FU_C_RESET}"
|
||||
# The next row says whose settings these are.
|
||||
[[ ${scopes[i + 1]} != user ]] && frame+=" ${PFU_C_DIM}${shared}${PFU_C_RESET}"
|
||||
[[ ${scopes[i + 1]} != user ]] && frame+=" ${FU_C_DIM}${shared}${FU_C_RESET}"
|
||||
frame+=$'\n'
|
||||
continue
|
||||
fi
|
||||
case "${types[i]}" in
|
||||
bool)
|
||||
if pfu_is_true "${values[i]}"; then
|
||||
shown="${PFU_C_GREEN}${l_on}${PFU_C_RESET}"
|
||||
if fu_is_true "${values[i]}"; then
|
||||
shown="${FU_C_GREEN}${l_on}${FU_C_RESET}"
|
||||
else
|
||||
shown="${PFU_C_DIM}${l_off}${PFU_C_RESET}"
|
||||
shown="${FU_C_DIM}${l_off}${FU_C_RESET}"
|
||||
fi
|
||||
;;
|
||||
camera) shown="$(_pfu_camera_label "${values[i]}")" ;;
|
||||
*) shown="$(pfu_value_label "${keys[i]}" "${values[i]}")" ;;
|
||||
camera) shown="$(_fu_camera_label "${values[i]}")" ;;
|
||||
*) shown="$(fu_value_label "${keys[i]}" "${values[i]}")" ;;
|
||||
esac
|
||||
# Arrows on the selected choice: left and right step through it.
|
||||
before=' ' after=''
|
||||
if (( i == selected )) && [[ ${types[i]} != bool ]]; then
|
||||
before="${PFU_C_BLUE}◂${PFU_C_RESET} " after=" ${PFU_C_BLUE}▸${PFU_C_RESET}"
|
||||
before="${FU_C_BLUE}◂${FU_C_RESET} " after=" ${FU_C_BLUE}▸${FU_C_RESET}"
|
||||
fi
|
||||
dim=''
|
||||
[[ -n ${needs[i]} ]] && ! pfu_is_true "${current[${needs[i]}]}" && dim="$PFU_C_DIM"
|
||||
[[ -n ${needs[i]} ]] && ! fu_is_true "${current[${needs[i]}]}" && dim="$FU_C_DIM"
|
||||
pad=$(( width + 2 - widths[i] ))
|
||||
if (( i == selected )); then marker="${PFU_C_BLUE}▸${PFU_C_RESET} "; else marker=' '; fi
|
||||
printf -v row ' %s%s%s%s%*s%s%s%s' "$marker" "$dim" "${labels[i]}" "$PFU_C_RESET" "$pad" '' "$before" "$dim$shown$PFU_C_RESET" "$after"
|
||||
if (( i == selected )); then marker="${FU_C_BLUE}▸${FU_C_RESET} "; else marker=' '; fi
|
||||
printf -v row ' %s%s%s%s%*s%s%s%s' "$marker" "$dim" "${labels[i]}" "$FU_C_RESET" "$pad" '' "$before" "$dim$shown$FU_C_RESET" "$after"
|
||||
frame+="$row"$'\n'
|
||||
done
|
||||
|
||||
# What the selected setting does, in a box of fixed height so the
|
||||
# screen does not jump while moving through the list.
|
||||
_pfu_wrap "$wrap" "$(pfu_setting_help "${keys[selected]}" "${values[selected]}")"
|
||||
frame+=$'\n'" ${PFU_C_DIM}${rule}${PFU_C_RESET}"$'\n'
|
||||
_fu_wrap "$wrap" "$(fu_setting_help "${keys[selected]}" "${values[selected]}")"
|
||||
frame+=$'\n'" ${FU_C_DIM}${rule}${FU_C_RESET}"$'\n'
|
||||
for j in 0 1 2; do
|
||||
frame+=" ${PFU_WRAP_LINES[j]:-}"$'\n'
|
||||
frame+=" ${FU_WRAP_LINES[j]:-}"$'\n'
|
||||
done
|
||||
frame+=$'\n'" ${PFU_C_DIM}${hint}${PFU_C_RESET}"$'\n'
|
||||
_pfu_ui_take_notices
|
||||
frame+="$PFU_UI_NOTICE_TEXT"
|
||||
frame+=$'\n'" ${FU_C_DIM}${hint}${FU_C_RESET}"$'\n'
|
||||
_fu_ui_take_notices
|
||||
frame+="$FU_UI_NOTICE_TEXT"
|
||||
printf '%s' "$frame"
|
||||
|
||||
key="$(pfu_read_key)" || return 0
|
||||
key="$(fu_read_key)" || return 0
|
||||
|
||||
case "$key" in
|
||||
up|k) cursor=$(( (cursor - 1 + count) % count )) ;;
|
||||
@@ -569,7 +569,7 @@ pfu_ui_settings() {
|
||||
space|enter|right|l|left|h)
|
||||
local step=1
|
||||
[[ $key == left || $key == h ]] && step=-1
|
||||
_pfu_setting_change "${scopes[selected]}" "${keys[selected]}" "${types[selected]}" "${values[selected]}" "${choices[selected]}" "$step"
|
||||
_fu_setting_change "${scopes[selected]}" "${keys[selected]}" "${types[selected]}" "${values[selected]}" "${choices[selected]}" "$step"
|
||||
dirty=1
|
||||
;;
|
||||
q|Q|escape) return 0 ;;
|
||||
@@ -582,72 +582,72 @@ pfu_ui_settings() {
|
||||
# Faces
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
pfu_ui_faces() {
|
||||
fu_ui_faces() {
|
||||
local key frame row pad i cursor=0 count locale shown
|
||||
|
||||
locale="$(pfu_ui_locale)"
|
||||
locale="$(fu_ui_locale)"
|
||||
local title hint empty l_on l_off
|
||||
pfu_msg_into "$locale" "Faces"; title="$PFU_MSG_RESULT"
|
||||
fu_msg_into "$locale" "Faces"; title="$FU_MSG_RESULT"
|
||||
# TRANSLATORS: keep the letters, they are the keys.
|
||||
pfu_msg_into "$locale" "Up/Down: select, Space: on/off, r: rename, d: delete, a: add, q: back"; hint="$PFU_MSG_RESULT"
|
||||
pfu_msg_into "$locale" "No face is set up yet. Press a to add one."; empty="$PFU_MSG_RESULT"
|
||||
pfu_msg_into "$locale" "on"; l_on="$PFU_MSG_RESULT"
|
||||
pfu_msg_into "$locale" "off"; l_off="$PFU_MSG_RESULT"
|
||||
fu_msg_into "$locale" "Up/Down: select, Space: on/off, r: rename, d: delete, a: add, q: back"; hint="$FU_MSG_RESULT"
|
||||
fu_msg_into "$locale" "No face is set up yet. Press a to add one."; empty="$FU_MSG_RESULT"
|
||||
fu_msg_into "$locale" "on"; l_on="$FU_MSG_RESULT"
|
||||
fu_msg_into "$locale" "off"; l_off="$FU_MSG_RESULT"
|
||||
|
||||
local clearseq
|
||||
clearseq="$(clear 2>/dev/null)" || clearseq=$'\033[H\033[2J'
|
||||
|
||||
while true; do
|
||||
pfu_faces_load
|
||||
count=${#PFU_FACE_IDS[@]}
|
||||
fu_faces_load
|
||||
count=${#FU_FACE_IDS[@]}
|
||||
(( cursor >= count )) && cursor=$(( count > 0 ? count - 1 : 0 ))
|
||||
|
||||
frame="$clearseq"$'\n'"${PFU_C_BOLD}${PFU_C_BLUE} ${title}${PFU_C_RESET}"$'\n\n'
|
||||
frame="$clearseq"$'\n'"${FU_C_BOLD}${FU_C_BLUE} ${title}${FU_C_RESET}"$'\n\n'
|
||||
if (( count == 0 )); then
|
||||
frame+=" ${PFU_C_DIM}${empty}${PFU_C_RESET}"$'\n'
|
||||
frame+=" ${FU_C_DIM}${empty}${FU_C_RESET}"$'\n'
|
||||
fi
|
||||
local marker selected="${PFU_C_BLUE}▸${PFU_C_RESET} " samples
|
||||
for i in "${!PFU_FACE_IDS[@]}"; do
|
||||
if [[ ${PFU_FACE_ON[i]} == true ]]; then shown="${PFU_C_GREEN}${l_on}${PFU_C_RESET}"; else shown="${PFU_C_DIM}${l_off}${PFU_C_RESET}"; fi
|
||||
samples="$(pfu_msg "%s samples, %s learned" "${PFU_FACE_SAMPLES[i]}" "${PFU_FACE_LEARNED[i]}")"
|
||||
_pfu_width "${PFU_FACE_NAMES[i]}"
|
||||
pad=$(( 30 - PFU_WIDTH ))
|
||||
local marker selected="${FU_C_BLUE}▸${FU_C_RESET} " samples
|
||||
for i in "${!FU_FACE_IDS[@]}"; do
|
||||
if [[ ${FU_FACE_ON[i]} == true ]]; then shown="${FU_C_GREEN}${l_on}${FU_C_RESET}"; else shown="${FU_C_DIM}${l_off}${FU_C_RESET}"; fi
|
||||
samples="$(fu_msg "%s samples, %s learned" "${FU_FACE_SAMPLES[i]}" "${FU_FACE_LEARNED[i]}")"
|
||||
_fu_width "${FU_FACE_NAMES[i]}"
|
||||
pad=$(( 30 - FU_WIDTH ))
|
||||
(( pad < 0 )) && pad=0
|
||||
if (( i == cursor )); then marker="$selected"; else marker=' '; fi
|
||||
printf -v row ' %s%s%*s %s %s%s%s' "$marker" "${PFU_FACE_NAMES[i]}" "$pad" '' "$shown" "$PFU_C_DIM" "$samples" "$PFU_C_RESET"
|
||||
printf -v row ' %s%s%*s %s %s%s%s' "$marker" "${FU_FACE_NAMES[i]}" "$pad" '' "$shown" "$FU_C_DIM" "$samples" "$FU_C_RESET"
|
||||
frame+="$row"$'\n'
|
||||
done
|
||||
frame+=$'\n'" ${PFU_C_DIM}${hint}${PFU_C_RESET}"$'\n'
|
||||
_pfu_ui_take_notices
|
||||
frame+="$PFU_UI_NOTICE_TEXT"
|
||||
frame+=$'\n'" ${FU_C_DIM}${hint}${FU_C_RESET}"$'\n'
|
||||
_fu_ui_take_notices
|
||||
frame+="$FU_UI_NOTICE_TEXT"
|
||||
printf '%s' "$frame"
|
||||
|
||||
key="$(pfu_read_key)" || return 0
|
||||
key="$(fu_read_key)" || return 0
|
||||
case "$key" in
|
||||
up|k) (( count )) && cursor=$(( (cursor - 1 + count) % count )) ;;
|
||||
down|j) (( count )) && cursor=$(( (cursor + 1) % count )) ;;
|
||||
space|enter)
|
||||
(( count )) || continue
|
||||
if [[ ${PFU_FACE_ON[cursor]} == true ]]; then
|
||||
pfu_ctl disable "${PFU_FACE_IDS[cursor]}" > /dev/null
|
||||
if [[ ${FU_FACE_ON[cursor]} == true ]]; then
|
||||
fu_ctl disable "${FU_FACE_IDS[cursor]}" > /dev/null
|
||||
else
|
||||
pfu_ctl enable "${PFU_FACE_IDS[cursor]}" > /dev/null
|
||||
fu_ctl enable "${FU_FACE_IDS[cursor]}" > /dev/null
|
||||
fi
|
||||
;;
|
||||
r|R)
|
||||
(( count )) || continue
|
||||
printf '\n %s ' "$(pfu_msg "New name:")"
|
||||
if pfu_ui_read_line "${PFU_FACE_NAMES[cursor]}" && [[ -n $PFU_LINE_RESULT ]]; then
|
||||
pfu_ctl rename "${PFU_FACE_IDS[cursor]}" "$PFU_LINE_RESULT" > /dev/null
|
||||
printf '\n %s ' "$(fu_msg "New name:")"
|
||||
if fu_ui_read_line "${FU_FACE_NAMES[cursor]}" && [[ -n $FU_LINE_RESULT ]]; then
|
||||
fu_ctl rename "${FU_FACE_IDS[cursor]}" "$FU_LINE_RESULT" > /dev/null
|
||||
fi
|
||||
;;
|
||||
d|D)
|
||||
(( count )) || continue
|
||||
if pfu_ui_confirm "$(pfu_msg "Delete \"%s\"?" "${PFU_FACE_NAMES[cursor]}")"; then
|
||||
pfu_ctl remove "${PFU_FACE_IDS[cursor]}" > /dev/null
|
||||
if fu_ui_confirm "$(fu_msg "Delete \"%s\"?" "${FU_FACE_NAMES[cursor]}")"; then
|
||||
fu_ctl remove "${FU_FACE_IDS[cursor]}" > /dev/null
|
||||
fi
|
||||
;;
|
||||
a|A) pfu_ui_cooked pfu_do_setup ;;
|
||||
a|A) fu_ui_cooked fu_do_setup ;;
|
||||
q|Q|escape) return 0 ;;
|
||||
*) ;;
|
||||
esac
|
||||
@@ -658,11 +658,11 @@ pfu_ui_faces() {
|
||||
# The menu
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
pfu_ui_menu() {
|
||||
fu_ui_menu() {
|
||||
local choice keep=0
|
||||
|
||||
pfu_ui_term_raw
|
||||
trap 'pfu_ui_term_restore' EXIT INT TERM
|
||||
fu_ui_term_raw
|
||||
trap 'fu_ui_term_restore' EXIT INT TERM
|
||||
|
||||
while true; do
|
||||
# After a test the menu goes under what the camera saw instead.
|
||||
@@ -671,21 +671,21 @@ pfu_ui_menu() {
|
||||
else
|
||||
clear 2>/dev/null || true
|
||||
fi
|
||||
pfu_head " $PFU_PRETTY"
|
||||
pfu_ui_status
|
||||
fu_head " $FU_PRETTY"
|
||||
fu_ui_status
|
||||
printf '\n'
|
||||
printf ' [1] %s\n' "$(pfu_msg "Turn face unlock on or off")"
|
||||
printf ' [2] %s\n' "$(pfu_msg "Add a face")"
|
||||
printf ' [3] %s\n' "$(pfu_msg "Faces")"
|
||||
printf ' [4] %s\n' "$(pfu_msg "Settings")"
|
||||
printf ' [5] %s\n' "$(pfu_msg "Try it")"
|
||||
printf ' [q] %s\n' "$(pfu_msg "Quit")"
|
||||
_pfu_ui_take_notices
|
||||
printf '%s' "$PFU_UI_NOTICE_TEXT"
|
||||
printf ' [1] %s\n' "$(fu_msg "Turn face unlock on or off")"
|
||||
printf ' [2] %s\n' "$(fu_msg "Add a face")"
|
||||
printf ' [3] %s\n' "$(fu_msg "Faces")"
|
||||
printf ' [4] %s\n' "$(fu_msg "Settings")"
|
||||
printf ' [5] %s\n' "$(fu_msg "Try it")"
|
||||
printf ' [q] %s\n' "$(fu_msg "Quit")"
|
||||
_fu_ui_take_notices
|
||||
printf '%s' "$FU_UI_NOTICE_TEXT"
|
||||
printf '\n > '
|
||||
|
||||
choice="$(pfu_read_key)" || {
|
||||
printf '\n'; pfu_ui_term_restore; trap - EXIT INT TERM; return 0
|
||||
choice="$(fu_read_key)" || {
|
||||
printf '\n'; fu_ui_term_restore; trap - EXIT INT TERM; return 0
|
||||
}
|
||||
case "$choice" in
|
||||
enter|space|up|down|left|right|escape) choice='' ;;
|
||||
@@ -694,24 +694,24 @@ pfu_ui_menu() {
|
||||
|
||||
case "$choice" in
|
||||
1)
|
||||
pfu_config_load
|
||||
fu_config_load
|
||||
if [[ $CFG_ENABLED == yes ]]; then
|
||||
pfu_ui_cooked pfu_do_disable
|
||||
fu_ui_cooked fu_do_disable
|
||||
else
|
||||
pfu_ui_cooked pfu_do_enable
|
||||
fu_ui_cooked fu_do_enable
|
||||
fi
|
||||
;;
|
||||
2) pfu_ui_cooked pfu_do_setup ;;
|
||||
3) pfu_ui_faces ;;
|
||||
4) pfu_ui_settings ;;
|
||||
2) fu_ui_cooked fu_do_setup ;;
|
||||
3) fu_ui_faces ;;
|
||||
4) fu_ui_settings ;;
|
||||
5)
|
||||
printf '\n'
|
||||
pfu_ui_cooked pfu_test
|
||||
fu_ui_cooked fu_test
|
||||
# Already on screen, with the rest of the test.
|
||||
PFU_UI_NOTICES=()
|
||||
FU_UI_NOTICES=()
|
||||
keep=1
|
||||
;;
|
||||
q|Q) pfu_ui_term_restore; trap - EXIT INT TERM; return 0 ;;
|
||||
q|Q) fu_ui_term_restore; trap - EXIT INT TERM; return 0 ;;
|
||||
# Anything else (Enter, arrow keys, stray characters) just
|
||||
# redraws. Escape is deliberately not a quit key, so a mistyped
|
||||
# arrow key cannot close the menu.
|
||||
|
||||
+49
-49
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# The line that goes in:
|
||||
#
|
||||
# -auth sufficient /usr/lib/security/pam_plasma_face_unlock.so
|
||||
# -auth sufficient /usr/lib/security/pam_face_unlock.so
|
||||
#
|
||||
# "sufficient": a match lets the person in, anything else falls through to the
|
||||
# lines below as if this one were not there. The dash makes PAM skip it
|
||||
@@ -26,24 +26,24 @@
|
||||
# an update to that file still counts.
|
||||
# Undoing takes out exactly those lines, or that file.
|
||||
|
||||
PFU_PAM_MARK="# plasma-face-unlock: the face first, the password if that does not work"
|
||||
PFU_PAM_WRAPPER_MARK="# Written by plasma-face-unlock."
|
||||
PFU_PAM_SERVICES=(sudo polkit-1)
|
||||
FU_PAM_MARK="# face-unlock: the face first, the password if that does not work"
|
||||
FU_PAM_WRAPPER_MARK="# Written by face-unlock."
|
||||
FU_PAM_SERVICES=(sudo polkit-1)
|
||||
|
||||
# Overridable for the tests only; the root side never takes them from the
|
||||
# environment (see the top of plasma-face-unlock).
|
||||
PFU_PAM_ETC_DIR="${PFU_PAM_ETC_DIR:-/etc/pam.d}"
|
||||
read -r -a PFU_PAM_VENDOR_DIRS <<< "${PFU_PAM_VENDOR_DIRS:-/usr/lib/pam.d /usr/share/pam.d /lib/pam.d}"
|
||||
# environment (see the top of face-unlock).
|
||||
FU_PAM_ETC_DIR="${FU_PAM_ETC_DIR:-/etc/pam.d}"
|
||||
read -r -a FU_PAM_VENDOR_DIRS <<< "${FU_PAM_VENDOR_DIRS:-/usr/lib/pam.d /usr/share/pam.d /lib/pam.d}"
|
||||
|
||||
pfu_pam_etc() {
|
||||
printf '%s/%s\n' "$PFU_PAM_ETC_DIR" "$1"
|
||||
fu_pam_etc() {
|
||||
printf '%s/%s\n' "$FU_PAM_ETC_DIR" "$1"
|
||||
}
|
||||
|
||||
# pfu_pam_vendor <service>
|
||||
# fu_pam_vendor <service>
|
||||
# The distribution's own copy, when it keeps one outside /etc.
|
||||
pfu_pam_vendor() {
|
||||
fu_pam_vendor() {
|
||||
local dir
|
||||
for dir in "${PFU_PAM_VENDOR_DIRS[@]}"; do
|
||||
for dir in "${FU_PAM_VENDOR_DIRS[@]}"; do
|
||||
if [[ -f $dir/$1 ]]; then
|
||||
printf '%s\n' "$dir/$1"
|
||||
return 0
|
||||
@@ -52,24 +52,24 @@ pfu_pam_vendor() {
|
||||
return 1
|
||||
}
|
||||
|
||||
pfu_pam_line() {
|
||||
printf -- '-auth sufficient %s\n' "$PFU_PAM_MODULE"
|
||||
fu_pam_line() {
|
||||
printf -- '-auth sufficient %s\n' "$FU_PAM_MODULE"
|
||||
}
|
||||
|
||||
# pfu_pam_enabled <service>
|
||||
pfu_pam_enabled() {
|
||||
# fu_pam_enabled <service>
|
||||
fu_pam_enabled() {
|
||||
local file
|
||||
file="$(pfu_pam_etc "$1")"
|
||||
[[ -r $file ]] && grep -q 'pam_plasma_face_unlock\.so' "$file"
|
||||
file="$(fu_pam_etc "$1")"
|
||||
[[ -r $file ]] && grep -q 'pam_face_unlock\.so' "$file"
|
||||
}
|
||||
|
||||
# pfu_pam_insert <file>
|
||||
# fu_pam_insert <file>
|
||||
# Prints the file with the line added before its first auth line. Debian and
|
||||
# Ubuntu have none in sudo's file, only "@include common-auth", and that
|
||||
# counts as one: after it the password has already been asked for. A file
|
||||
# with neither (which would be odd for either service) gets it at the end.
|
||||
pfu_pam_insert() {
|
||||
awk -v mark="$PFU_PAM_MARK" -v line="$(pfu_pam_line)" '
|
||||
fu_pam_insert() {
|
||||
awk -v mark="$FU_PAM_MARK" -v line="$(fu_pam_line)" '
|
||||
!done && ($0 ~ /^[[:space:]]*-?auth[[:space:]]/ || $0 ~ /^[[:space:]]*@include[[:space:]]+common-auth([[:space:]]|$)/) {
|
||||
print mark
|
||||
print line
|
||||
@@ -85,35 +85,35 @@ pfu_pam_insert() {
|
||||
' "$1"
|
||||
}
|
||||
|
||||
# pfu_pam_remove_lines <file>
|
||||
# fu_pam_remove_lines <file>
|
||||
# Prints the file without our comment and our line.
|
||||
pfu_pam_remove_lines() {
|
||||
awk -v mark="$PFU_PAM_MARK" '
|
||||
fu_pam_remove_lines() {
|
||||
awk -v mark="$FU_PAM_MARK" '
|
||||
$0 == mark { next }
|
||||
/pam_plasma_face_unlock\.so/ { next }
|
||||
/pam_face_unlock\.so/ { next }
|
||||
{ print }
|
||||
' "$1"
|
||||
}
|
||||
|
||||
pfu_pam_wrapper() {
|
||||
fu_pam_wrapper() {
|
||||
local vendor="$1"
|
||||
printf '#%%PAM-1.0\n'
|
||||
printf '%s The face first, then everything\n' "$PFU_PAM_WRAPPER_MARK"
|
||||
printf '%s The face first, then everything\n' "$FU_PAM_WRAPPER_MARK"
|
||||
printf '# %s does for this service. Removed again by\n' "$vendor"
|
||||
printf '# "plasma-face-unlock disable" or from its settings.\n\n'
|
||||
pfu_pam_line
|
||||
printf '# "face-unlock disable" or from its settings.\n\n'
|
||||
fu_pam_line
|
||||
printf 'auth include %s\n' "$vendor"
|
||||
printf 'account include %s\n' "$vendor"
|
||||
printf 'password include %s\n' "$vendor"
|
||||
printf 'session include %s\n' "$vendor"
|
||||
}
|
||||
|
||||
# _pfu_pam_replace <file> <content>
|
||||
# _fu_pam_replace <file> <content>
|
||||
# Writes the new file next to the old one and swaps it in, with the old one's
|
||||
# owner and mode. A half-written PAM file is a locked-out machine.
|
||||
_pfu_pam_replace() {
|
||||
_fu_pam_replace() {
|
||||
local file="$1" content="$2" tmp
|
||||
tmp="$(mktemp "${file}.pfu.XXXXXX")" || return 1
|
||||
tmp="$(mktemp "${file}.fu.XXXXXX")" || return 1
|
||||
printf '%s\n' "$content" > "$tmp" || { rm -f "$tmp"; return 1; }
|
||||
if [[ -e $file ]]; then
|
||||
chown --reference="$file" "$tmp" 2>/dev/null
|
||||
@@ -124,40 +124,40 @@ _pfu_pam_replace() {
|
||||
mv -f "$tmp" "$file"
|
||||
}
|
||||
|
||||
# pfu_pam_enable <service> (root)
|
||||
pfu_pam_enable() {
|
||||
# fu_pam_enable <service> (root)
|
||||
fu_pam_enable() {
|
||||
local service="$1" file vendor content
|
||||
file="$(pfu_pam_etc "$service")"
|
||||
file="$(fu_pam_etc "$service")"
|
||||
|
||||
[[ -e $PFU_PAM_MODULE ]] || { pfu_bad "$(pfu_msg "The PAM module is not installed at %s." "$PFU_PAM_MODULE")"; return 1; }
|
||||
pfu_pam_enabled "$service" && return 0
|
||||
[[ -e $FU_PAM_MODULE ]] || { fu_bad "$(fu_msg "The PAM module is not installed at %s." "$FU_PAM_MODULE")"; return 1; }
|
||||
fu_pam_enabled "$service" && return 0
|
||||
|
||||
if [[ -f $file ]]; then
|
||||
content="$(pfu_pam_insert "$file")" || return 1
|
||||
elif vendor="$(pfu_pam_vendor "$service")"; then
|
||||
content="$(pfu_pam_wrapper "$vendor")"
|
||||
content="$(fu_pam_insert "$file")" || return 1
|
||||
elif vendor="$(fu_pam_vendor "$service")"; then
|
||||
content="$(fu_pam_wrapper "$vendor")"
|
||||
else
|
||||
pfu_bad "$(pfu_msg "There is no PAM configuration for %s on this system." "$service")"
|
||||
fu_bad "$(fu_msg "There is no PAM configuration for %s on this system." "$service")"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_pfu_pam_replace "$file" "$content"
|
||||
_fu_pam_replace "$file" "$content"
|
||||
}
|
||||
|
||||
# pfu_pam_disable <service> (root)
|
||||
pfu_pam_disable() {
|
||||
# fu_pam_disable <service> (root)
|
||||
fu_pam_disable() {
|
||||
local service="$1" file content
|
||||
file="$(pfu_pam_etc "$service")"
|
||||
file="$(fu_pam_etc "$service")"
|
||||
|
||||
pfu_pam_enabled "$service" || return 0
|
||||
fu_pam_enabled "$service" || return 0
|
||||
|
||||
if head -n 3 "$file" | grep -qF "$PFU_PAM_WRAPPER_MARK"; then
|
||||
if head -n 3 "$file" | grep -qF "$FU_PAM_WRAPPER_MARK"; then
|
||||
# Ours from the first line to the last. Without it the distribution's
|
||||
# own copy is in charge again.
|
||||
rm -f -- "$file"
|
||||
return
|
||||
fi
|
||||
|
||||
content="$(pfu_pam_remove_lines "$file")" || return 1
|
||||
_pfu_pam_replace "$file" "$content"
|
||||
content="$(fu_pam_remove_lines "$file")" || return 1
|
||||
_fu_pam_replace "$file" "$content"
|
||||
}
|
||||
+34
-34
@@ -8,17 +8,17 @@
|
||||
# is already looking at. The verbs are all there is: there is no way to hand
|
||||
# the root side a command of one's own.
|
||||
#
|
||||
# --root set <Key> <Value> one line of /etc/plasma-face-unlock/config
|
||||
# --root set <Key> <Value> one line of /etc/face-unlock/config
|
||||
# --root pam-enable <service> sudo or polkit-1, see pam.sh
|
||||
# --root pam-disable <service>
|
||||
# --root socket-enable start the daemon's socket, and at boot
|
||||
# --root socket-disable
|
||||
|
||||
PFU_SELF="${PFU_SELF:-$(readlink -f "${BASH_SOURCE[1]:-$0}")}"
|
||||
FU_SELF="${FU_SELF:-$(readlink -f "${BASH_SOURCE[1]:-$0}")}"
|
||||
|
||||
# What each system setting may be set to. Anything else is refused on the root
|
||||
# side, whatever the menu sent.
|
||||
declare -A PFU_SYS_VALID=(
|
||||
declare -A FU_SYS_VALID=(
|
||||
[Camera]='^(auto|/dev/video[0-9]+)$'
|
||||
[Liveness]='^(off|light|heavy)$'
|
||||
[Strictness]='^(relaxed|normal|strict)$'
|
||||
@@ -30,63 +30,63 @@ declare -A PFU_SYS_VALID=(
|
||||
[LockoutMinutes]='^[1-9][0-9]{0,3}$'
|
||||
)
|
||||
|
||||
# pfu_root <verb> [args...]
|
||||
pfu_root() {
|
||||
# fu_root <verb> [args...]
|
||||
fu_root() {
|
||||
local candidate
|
||||
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
pfu_root_verb "$@"
|
||||
fu_root_verb "$@"
|
||||
return
|
||||
fi
|
||||
for candidate in sudo run0 doas; do
|
||||
if pfu_have "$candidate"; then
|
||||
"$candidate" "$PFU_SELF" --root "$@"
|
||||
if fu_have "$candidate"; then
|
||||
"$candidate" "$FU_SELF" --root "$@"
|
||||
return
|
||||
fi
|
||||
done
|
||||
pfu_bad "$(pfu_msg "This needs root, and neither sudo, run0 nor doas is installed.")"
|
||||
fu_bad "$(fu_msg "This needs root, and neither sudo, run0 nor doas is installed.")"
|
||||
return 1
|
||||
}
|
||||
|
||||
pfu_root_verb() {
|
||||
fu_root_verb() {
|
||||
local verb="${1:-}"
|
||||
[[ $# -gt 0 ]] && shift
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
pfu_bad "$(pfu_msg "This command has to run as root.")"
|
||||
fu_bad "$(fu_msg "This command has to run as root.")"
|
||||
return 2
|
||||
fi
|
||||
|
||||
case "$verb" in
|
||||
set)
|
||||
local key="${1:-}" value="${2:-}"
|
||||
if [[ -z ${PFU_SYS_VALID[$key]+set} || ! $value =~ ${PFU_SYS_VALID[$key]} ]]; then
|
||||
pfu_bad "$(pfu_msg "Not a valid setting: %s=%s" "$key" "$value")"
|
||||
if [[ -z ${FU_SYS_VALID[$key]+set} || ! $value =~ ${FU_SYS_VALID[$key]} ]]; then
|
||||
fu_bad "$(fu_msg "Not a valid setting: %s=%s" "$key" "$value")"
|
||||
return 1
|
||||
fi
|
||||
pfu_kv_set "$PFU_SYSCONFIG" "$key" "$value" "$PFU_PRETTY (system settings)" || return 1
|
||||
chmod 0644 "$PFU_SYSCONFIG"
|
||||
fu_kv_set "$FU_SYSCONFIG" "$key" "$value" "$FU_PRETTY (system settings)" || return 1
|
||||
chmod 0644 "$FU_SYSCONFIG"
|
||||
;;
|
||||
pam-enable|pam-disable)
|
||||
local service="${1:-}" known=0 s
|
||||
for s in "${PFU_PAM_SERVICES[@]}"; do
|
||||
for s in "${FU_PAM_SERVICES[@]}"; do
|
||||
[[ $s == "$service" ]] && known=1
|
||||
done
|
||||
(( known )) || { pfu_bad "$(pfu_msg "Not a service this can be used for: %s" "$service")"; return 1; }
|
||||
(( known )) || { fu_bad "$(fu_msg "Not a service this can be used for: %s" "$service")"; return 1; }
|
||||
if [[ $verb == pam-enable ]]; then
|
||||
pfu_pam_enable "$service"
|
||||
fu_pam_enable "$service"
|
||||
else
|
||||
pfu_pam_disable "$service"
|
||||
fu_pam_disable "$service"
|
||||
fi
|
||||
;;
|
||||
socket-enable)
|
||||
systemctl enable --now "$PFU_UNIT_SOCKET" > /dev/null 2>&1
|
||||
systemctl enable --now "$FU_UNIT_SOCKET" > /dev/null 2>&1
|
||||
;;
|
||||
socket-disable)
|
||||
systemctl disable --now "$PFU_UNIT_SOCKET" > /dev/null 2>&1
|
||||
systemctl disable --now "$FU_UNIT_SOCKET" > /dev/null 2>&1
|
||||
;;
|
||||
*)
|
||||
pfu_bad "$(pfu_msg "Unknown command: %s" "$verb")"
|
||||
fu_bad "$(fu_msg "Unknown command: %s" "$verb")"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
@@ -96,27 +96,27 @@ pfu_root_verb() {
|
||||
# The two services
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
pfu_socket_enabled() {
|
||||
systemctl is-enabled --quiet "$PFU_UNIT_SOCKET" 2>/dev/null
|
||||
fu_socket_enabled() {
|
||||
systemctl is-enabled --quiet "$FU_UNIT_SOCKET" 2>/dev/null
|
||||
}
|
||||
|
||||
pfu_agent_available() {
|
||||
pfu_have systemctl && [[ -n ${XDG_RUNTIME_DIR:-} ]]
|
||||
fu_agent_available() {
|
||||
fu_have systemctl && [[ -n ${XDG_RUNTIME_DIR:-} ]]
|
||||
}
|
||||
|
||||
pfu_agent_enabled() {
|
||||
systemctl --user is-enabled --quiet "$PFU_UNIT_AGENT" 2>/dev/null
|
||||
fu_agent_enabled() {
|
||||
systemctl --user is-enabled --quiet "$FU_UNIT_AGENT" 2>/dev/null
|
||||
}
|
||||
|
||||
pfu_agent_running() {
|
||||
systemctl --user is-active --quiet "$PFU_UNIT_AGENT" 2>/dev/null
|
||||
fu_agent_running() {
|
||||
systemctl --user is-active --quiet "$FU_UNIT_AGENT" 2>/dev/null
|
||||
}
|
||||
|
||||
pfu_agent_enable() {
|
||||
fu_agent_enable() {
|
||||
systemctl --user daemon-reload > /dev/null 2>&1 || true
|
||||
systemctl --user enable --now "$PFU_UNIT_AGENT" > /dev/null 2>&1
|
||||
systemctl --user enable --now "$FU_UNIT_AGENT" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
pfu_agent_disable() {
|
||||
systemctl --user disable --now "$PFU_UNIT_AGENT" > /dev/null 2>&1 || true
|
||||
fu_agent_disable() {
|
||||
systemctl --user disable --now "$FU_UNIT_AGENT" > /dev/null 2>&1 || true
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
//
|
||||
// pam_plasma_face_unlock: face unlock for sudo and for admin prompts.
|
||||
// pam_face_unlock: face unlock for sudo and for admin prompts.
|
||||
//
|
||||
// All the vision is in the daemon. This asks it to scan for the user and
|
||||
// turns the answer into a PAM result, and it is meant to sit first in a stack
|
||||
@@ -49,7 +49,7 @@
|
||||
#include <systemd/sd-login.h>
|
||||
#endif
|
||||
|
||||
#define DOMAIN PFU_NAME
|
||||
#define DOMAIN FU_NAME
|
||||
// Marks a message for translation. say() translates it.
|
||||
#define _(s) (s)
|
||||
|
||||
@@ -62,7 +62,7 @@ struct options {
|
||||
|
||||
static void parse_options(struct options *o, int argc, const char **argv)
|
||||
{
|
||||
o->socket = PFU_SOCKET;
|
||||
o->socket = FU_SOCKET;
|
||||
o->purpose = NULL;
|
||||
o->timeout = 25;
|
||||
o->debug = false;
|
||||
@@ -229,7 +229,7 @@ __attribute__((visibility("default"))) PAM_EXTERN int pam_sm_authenticate(pam_ha
|
||||
{
|
||||
struct options o;
|
||||
parse_options(&o, argc, argv);
|
||||
bindtextdomain(DOMAIN, PFU_LOCALEDIR);
|
||||
bindtextdomain(DOMAIN, FU_LOCALEDIR);
|
||||
|
||||
const char *user = NULL;
|
||||
if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || !nonempty(user)) {
|
||||
@@ -1,229 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# plasma-face-unlock: face unlock for KDE Plasma
|
||||
#
|
||||
# Look at the screen and it unlocks, the way a phone does. The lock screen,
|
||||
# sudo in a terminal and the admin password prompts can all take a face
|
||||
# instead of a password, with a check that it is a face and not a photo of one.
|
||||
#
|
||||
# This is the front end: the menu and the commands. The camera, the face data
|
||||
# and the decision are the daemon's (plasma-face-unlockd, running as root),
|
||||
# the lock screen and the bubble at the top of the screen are the agent's
|
||||
# (plasma-face-unlock-agent, in the session), and sudo and polkit reach the
|
||||
# daemon through a PAM module. See the man page for how the pieces fit.
|
||||
#
|
||||
# Copyright (C) 2026 Felitendo
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
PFU_SELF="$(readlink -f "${BASH_SOURCE[0]}")"
|
||||
|
||||
# Run as root (through sudo from the menu), only what was installed counts.
|
||||
# An environment that points the libraries somewhere else is ignored then.
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
unset PFU_LIBDIR PFU_LIBEXECDIR PFU_LOCALEDIR PFU_PAMDIR PFU_CTL PFU_AGENT PFU_PAM_MODULE PFU_SYSCONFIG \
|
||||
PFU_PAM_ETC_DIR PFU_PAM_VENDOR_DIRS
|
||||
fi
|
||||
|
||||
PFU_LIBDIR="${PFU_LIBDIR:-@LIBDIR@}"
|
||||
|
||||
for _mod in common config daemon pam system menu; do
|
||||
# shellcheck source=/dev/null
|
||||
if ! source "$PFU_LIBDIR/$_mod.sh"; then
|
||||
printf 'plasma-face-unlock: cannot load %s/%s.sh\n' "$PFU_LIBDIR" "$_mod" >&2
|
||||
exit 14
|
||||
fi
|
||||
done
|
||||
unset _mod
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Commands
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# The daemon is started by its socket. Enabling the socket is the one thing
|
||||
# that needs root once per machine.
|
||||
pfu_ensure_service() {
|
||||
pfu_status_load && return 0
|
||||
|
||||
if ! pfu_socket_enabled; then
|
||||
pfu_say " $(pfu_msg "Face unlock's service has to be switched on once for this computer. That needs your password.")"
|
||||
pfu_root socket-enable || return 1
|
||||
sleep 0.3
|
||||
fi
|
||||
pfu_status_load && return 0
|
||||
|
||||
pfu_bad "$(pfu_reason_text unreachable)"
|
||||
pfu_note "$(pfu_msg "Check it with: systemctl status %s" "$PFU_UNIT_SOCKET")"
|
||||
return 1
|
||||
}
|
||||
|
||||
pfu_do_setup() {
|
||||
local name="${1:-}" rc
|
||||
|
||||
pfu_ensure_service || return 1
|
||||
|
||||
if [[ -z ${WAYLAND_DISPLAY:-} && -z ${DISPLAY:-} ]]; then
|
||||
pfu_bad "$(pfu_msg "Setting up a face needs the camera picture on screen. Run this inside your Plasma session.")"
|
||||
return 1
|
||||
fi
|
||||
|
||||
pfu_say " $(pfu_msg "The setup window is open. Follow it there.")"
|
||||
if [[ -n $name ]]; then
|
||||
"$PFU_AGENT" --enroll --name "$name" > /dev/null 2>&1
|
||||
else
|
||||
"$PFU_AGENT" --enroll > /dev/null 2>&1
|
||||
fi
|
||||
rc=$?
|
||||
|
||||
if (( rc == 0 )); then
|
||||
pfu_ok "$(pfu_msg "The face is set up.")"
|
||||
pfu_config_load
|
||||
if [[ $CFG_ENABLED != yes ]]; then
|
||||
pfu_note "$(pfu_msg "Face unlock is still off. Turn it on with [1] or \`%s enable\`." "$PFU_NAME")"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
pfu_note "$(pfu_msg "No face was added.")"
|
||||
return 1
|
||||
}
|
||||
|
||||
pfu_do_enable() {
|
||||
pfu_ensure_service || return 1
|
||||
|
||||
pfu_faces_load
|
||||
if (( ${#PFU_FACE_IDS[@]} == 0 )); then
|
||||
pfu_say " $(pfu_msg "First, set up your face.")"
|
||||
pfu_do_setup || return 1
|
||||
fi
|
||||
|
||||
pfu_config_set Enabled yes || { pfu_bad "$(pfu_msg "Could not save the setting.")"; return 1; }
|
||||
pfu_config_load
|
||||
|
||||
if pfu_agent_available; then
|
||||
pfu_agent_enable || pfu_bad "$(pfu_msg "Could not start the lock screen agent.")"
|
||||
else
|
||||
pfu_note "$(pfu_msg "No systemd user session, so the lock screen agent was not started.")"
|
||||
fi
|
||||
|
||||
# What was on the last time face unlock was on.
|
||||
[[ $CFG_SUDO == yes ]] && ! pfu_pam_enabled sudo && pfu_root pam-enable sudo
|
||||
[[ $CFG_POLKIT == yes ]] && ! pfu_pam_enabled polkit-1 && pfu_root pam-enable polkit-1
|
||||
|
||||
pfu_ok "$(pfu_msg "Face unlock is on. Lock the screen and look at it to try.")"
|
||||
if [[ $CFG_SUDO != yes && $CFG_POLKIT != yes ]]; then
|
||||
pfu_note "$(pfu_msg "It can do sudo and admin prompts too. See Settings.")"
|
||||
fi
|
||||
}
|
||||
|
||||
pfu_do_disable() {
|
||||
pfu_config_set Enabled no || { pfu_bad "$(pfu_msg "Could not save the setting.")"; return 1; }
|
||||
pfu_agent_available && pfu_agent_disable
|
||||
|
||||
local service
|
||||
for service in "${PFU_PAM_SERVICES[@]}"; do
|
||||
if pfu_pam_enabled "$service"; then
|
||||
pfu_root pam-disable "$service" || true
|
||||
fi
|
||||
done
|
||||
|
||||
pfu_ok "$(pfu_msg "Face unlock is off. Your faces are kept; delete them under Faces.")"
|
||||
}
|
||||
|
||||
pfu_do_status() {
|
||||
pfu_head " $PFU_PRETTY"
|
||||
pfu_ui_status
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
pfu_do_faces() {
|
||||
local i state
|
||||
pfu_status_load || { pfu_bad "$(pfu_reason_text unreachable)"; return 1; }
|
||||
pfu_faces_load
|
||||
if (( ${#PFU_FACE_IDS[@]} == 0 )); then
|
||||
pfu_note "$(pfu_msg "No face is set up yet.")"
|
||||
return 0
|
||||
fi
|
||||
for i in "${!PFU_FACE_IDS[@]}"; do
|
||||
if [[ ${PFU_FACE_ON[i]} == true ]]; then state="$(pfu_msg "on")"; else state="$(pfu_msg "off")"; fi
|
||||
printf ' %s %-24s %-4s %s\n' "${PFU_FACE_IDS[i]}" "${PFU_FACE_NAMES[i]}" "$state" \
|
||||
"$(pfu_msg "%s samples, %s learned" "${PFU_FACE_SAMPLES[i]}" "${PFU_FACE_LEARNED[i]}")"
|
||||
done
|
||||
}
|
||||
|
||||
pfu_do_remove() {
|
||||
local id="${1:-}" line
|
||||
[[ -n $id ]] || { pfu_bad "$(pfu_msg "Which face? See \`%s faces\` for the ids." "$PFU_NAME")"; return 1; }
|
||||
line="$(pfu_ctl remove "$id" | tail -n1)"
|
||||
_pfu_fields "$line"
|
||||
if [[ ${PFU_F[ok]:-} == true ]]; then
|
||||
pfu_ok "$(pfu_msg "Deleted.")"
|
||||
else
|
||||
pfu_bad "$(pfu_reason_text "${PFU_F[reason]:-unreachable}")"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
pfu_do_help() {
|
||||
cat <<- EOF
|
||||
$PFU_PRETTY $PFU_VERSION
|
||||
|
||||
$(pfu_msg "Usage: plasma-face-unlock [command]")
|
||||
|
||||
$(pfu_msg "Commands:")
|
||||
enable $(pfu_msg "Turn face unlock on")
|
||||
disable $(pfu_msg "Turn it off (faces are kept)")
|
||||
setup [NAME] $(pfu_msg "Add a face")
|
||||
faces $(pfu_msg "List the faces")
|
||||
remove ID $(pfu_msg "Delete a face")
|
||||
test $(pfu_msg "Look at the camera and see what it sees")
|
||||
status $(pfu_msg "Show what is on")
|
||||
-h, --help $(pfu_msg "Show this help")
|
||||
-V, --version $(pfu_msg "Show the version")
|
||||
|
||||
$(pfu_msg "Without a command an interactive menu is shown.")
|
||||
EOF
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Dispatch
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
main() {
|
||||
local cmd="${1:-}"
|
||||
[[ $# -gt 0 ]] && shift
|
||||
|
||||
case "$cmd" in
|
||||
--root) pfu_root_verb "$@"; return ;;
|
||||
esac
|
||||
|
||||
# Face data and settings are per user; root has neither a lock screen
|
||||
# nor a face of its own to set up.
|
||||
if [[ $EUID -eq 0 && -z ${PFU_ALLOW_ROOT:-} ]]; then
|
||||
pfu_bad "$(pfu_msg "Run this as your own user, not as root. It asks for your password when it needs to.")"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
case "$cmd" in
|
||||
enable) pfu_do_enable ;;
|
||||
disable) pfu_do_disable ;;
|
||||
setup|add|enroll) pfu_do_setup "$@" ;;
|
||||
faces|list) pfu_do_faces ;;
|
||||
remove|delete) pfu_do_remove "$@" ;;
|
||||
test|try) pfu_ensure_service && pfu_test ;;
|
||||
status) pfu_do_status ;;
|
||||
|
||||
-h|--help|help) pfu_do_help ;;
|
||||
-V|--version) printf '%s %s\n' "$PFU_NAME" "$PFU_VERSION" ;;
|
||||
|
||||
'') pfu_ui_menu ;;
|
||||
*)
|
||||
pfu_bad "$(pfu_msg "Unknown command: %s" "$cmd")"
|
||||
printf '\n'
|
||||
pfu_do_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -2,11 +2,11 @@
|
||||
// rest of the installation is.
|
||||
#pragma once
|
||||
|
||||
#define PFU_VERSION "@PFU_VERSION@"
|
||||
#define PFU_NAME "plasma-face-unlock"
|
||||
#define PFU_LIBEXECDIR "@PFU_LIBEXECDIR@"
|
||||
#define PFU_MODELDIR "@PFU_MODELDIR@"
|
||||
#define PFU_LOCALEDIR "@PFU_LOCALEDIR@"
|
||||
#define PFU_SOCKET "@PFU_SOCKET@"
|
||||
#define PFU_STATEDIR "@PFU_STATEDIR@"
|
||||
#define PFU_CONFIG "@PFU_CONFIG@"
|
||||
#define FU_VERSION "@FU_VERSION@"
|
||||
#define FU_NAME "face-unlock"
|
||||
#define FU_LIBEXECDIR "@FU_LIBEXECDIR@"
|
||||
#define FU_MODELDIR "@FU_MODELDIR@"
|
||||
#define FU_LOCALEDIR "@FU_LOCALEDIR@"
|
||||
#define FU_SOCKET "@FU_SOCKET@"
|
||||
#define FU_STATEDIR "@FU_STATEDIR@"
|
||||
#define FU_CONFIG "@FU_CONFIG@"
|
||||
+27
-27
@@ -17,19 +17,19 @@ here="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
tmp="$(mktemp -d)"
|
||||
trap 'rm -rf -- "$tmp"' EXIT
|
||||
|
||||
export PFU_PAM_ETC_DIR="$tmp/etc"
|
||||
export PFU_PAM_VENDOR_DIRS="$tmp/vendor"
|
||||
PFU_LIBDIR="$here/src/lib"
|
||||
export FU_PAM_ETC_DIR="$tmp/etc"
|
||||
export FU_PAM_VENDOR_DIRS="$tmp/vendor"
|
||||
FU_LIBDIR="$here/src/lib"
|
||||
# shellcheck source=/dev/null
|
||||
source "$PFU_LIBDIR/common.sh"
|
||||
source "$FU_LIBDIR/common.sh"
|
||||
# shellcheck source=/dev/null
|
||||
source "$PFU_LIBDIR/config.sh"
|
||||
source "$FU_LIBDIR/config.sh"
|
||||
# shellcheck source=/dev/null
|
||||
source "$PFU_LIBDIR/pam.sh"
|
||||
source "$FU_LIBDIR/pam.sh"
|
||||
|
||||
PFU_PAM_MODULE="$tmp/lib/pam_plasma_face_unlock.so"
|
||||
FU_PAM_MODULE="$tmp/lib/pam_face_unlock.so"
|
||||
mkdir -p "$tmp/lib" "$tmp/etc" "$tmp/vendor"
|
||||
: > "$PFU_PAM_MODULE"
|
||||
: > "$FU_PAM_MODULE"
|
||||
|
||||
failures=0
|
||||
check() {
|
||||
@@ -86,33 +86,33 @@ for layout in arch_sudo debian_sudo fedora_sudo; do
|
||||
printf '%s\n' "${!layout}" > "$tmp/etc/sudo"
|
||||
cp "$tmp/etc/sudo" "$tmp/original"
|
||||
|
||||
pfu_pam_enable sudo
|
||||
check "$layout: turned on" 'pfu_pam_enabled sudo'
|
||||
check "$layout: the face comes before the password" '[[ "$(first_auth "$tmp/etc/sudo")" == *pam_plasma_face_unlock.so* ]]'
|
||||
check "$layout: with the dash and as sufficient" 'grep -qE "^-auth[[:space:]]+sufficient[[:space:]]+$PFU_PAM_MODULE\$" "$tmp/etc/sudo"'
|
||||
fu_pam_enable sudo
|
||||
check "$layout: turned on" 'fu_pam_enabled sudo'
|
||||
check "$layout: the face comes before the password" '[[ "$(first_auth "$tmp/etc/sudo")" == *pam_face_unlock.so* ]]'
|
||||
check "$layout: with the dash and as sufficient" 'grep -qE "^-auth[[:space:]]+sufficient[[:space:]]+$FU_PAM_MODULE\$" "$tmp/etc/sudo"'
|
||||
check "$layout: the header stays first" '[[ "$(head -n1 "$tmp/etc/sudo")" == "#%PAM-1.0" ]]'
|
||||
|
||||
pfu_pam_enable sudo
|
||||
check "$layout: turning it on twice adds it once" '[[ $(grep -c pam_plasma_face_unlock "$tmp/etc/sudo") -eq 1 ]]'
|
||||
fu_pam_enable sudo
|
||||
check "$layout: turning it on twice adds it once" '[[ $(grep -c pam_face_unlock "$tmp/etc/sudo") -eq 1 ]]'
|
||||
|
||||
pfu_pam_disable sudo
|
||||
fu_pam_disable sudo
|
||||
check "$layout: turning it off gives back the same file" 'cmp -s "$tmp/etc/sudo" "$tmp/original"'
|
||||
check "$layout: turned off" '! pfu_pam_enabled sudo'
|
||||
check "$layout: turned off" '! fu_pam_enabled sudo'
|
||||
rm -f "$tmp/etc/sudo"
|
||||
done
|
||||
|
||||
# Only the distribution's copy, in /usr/lib/pam.d.
|
||||
printf '%s\n' "$arch_polkit" > "$tmp/vendor/polkit-1"
|
||||
pfu_pam_enable polkit-1
|
||||
check "vendor polkit-1: a small file of our own in /etc" '[[ -f $tmp/etc/polkit-1 ]] && grep -qF "$PFU_PAM_WRAPPER_MARK" "$tmp/etc/polkit-1"'
|
||||
fu_pam_enable polkit-1
|
||||
check "vendor polkit-1: a small file of our own in /etc" '[[ -f $tmp/etc/polkit-1 ]] && grep -qF "$FU_PAM_WRAPPER_MARK" "$tmp/etc/polkit-1"'
|
||||
check "vendor polkit-1: it includes the distribution's file" 'grep -qE "^auth[[:space:]]+include[[:space:]]+$tmp/vendor/polkit-1\$" "$tmp/etc/polkit-1"'
|
||||
check "vendor polkit-1: face first" '[[ "$(first_auth "$tmp/etc/polkit-1")" == *pam_plasma_face_unlock.so* ]]'
|
||||
check "vendor polkit-1: face first" '[[ "$(first_auth "$tmp/etc/polkit-1")" == *pam_face_unlock.so* ]]'
|
||||
check "vendor polkit-1: the distribution's file is left alone" '[[ "$(cat "$tmp/vendor/polkit-1")" == "$arch_polkit" ]]'
|
||||
pfu_pam_disable polkit-1
|
||||
fu_pam_disable polkit-1
|
||||
check "vendor polkit-1: turning it off removes our file" '[[ ! -e $tmp/etc/polkit-1 ]]'
|
||||
|
||||
# No configuration at all.
|
||||
check "an unknown service is refused" '! pfu_pam_enable nosuchservice 2>/dev/null'
|
||||
check "an unknown service is refused" '! fu_pam_enable nosuchservice 2>/dev/null'
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Through real PAM
|
||||
@@ -122,12 +122,12 @@ harness="$here/build/pam_harness"
|
||||
if [[ -x $harness ]]; then
|
||||
mkdir -p "$tmp/real/vendor" "$tmp/real/etc"
|
||||
printf 'auth required pam_permit.so\naccount required pam_permit.so\n' > "$tmp/real/vendor/svc"
|
||||
PFU_PAM_ETC_DIR="$tmp/real/etc"
|
||||
PFU_PAM_VENDOR_DIRS=("$tmp/real/vendor")
|
||||
PFU_PAM_MODULE="$tmp/real/missing/pam_plasma_face_unlock.so"
|
||||
mkdir -p "$tmp/real/missing" && : > "$PFU_PAM_MODULE"
|
||||
pfu_pam_enable svc
|
||||
rm -f "$PFU_PAM_MODULE"
|
||||
FU_PAM_ETC_DIR="$tmp/real/etc"
|
||||
FU_PAM_VENDOR_DIRS=("$tmp/real/vendor")
|
||||
FU_PAM_MODULE="$tmp/real/missing/pam_face_unlock.so"
|
||||
mkdir -p "$tmp/real/missing" && : > "$FU_PAM_MODULE"
|
||||
fu_pam_enable svc
|
||||
rm -f "$FU_PAM_MODULE"
|
||||
check "a missing module is skipped, the rest of the stack still decides" '"$harness" "$tmp/real/etc" svc "$(id -un)" > /dev/null 2>&1'
|
||||
|
||||
printf 'auth required pam_deny.so\n' > "$tmp/real/vendor/svc"
|
||||
|
||||
Reference in new issue
Block a user