blob: 1bf3e4ddf76ce6086d6fefa44ec81bb667fb1f6a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#!/bin/bash
#
# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# One state dump for the KDE Connect module: the daemon's devices and any
# pending pairing requests, as tab-separated lines on stdout.
#
# device<TAB>id<TAB>name<TAB>type<TAB>paired<TAB>reachable<TAB>pairRequested<TAB>pairRequestedByPeer<TAB>key<TAB>charge<TAB>charging
# request<TAB>id
#
# request lines come first. A daemon query that fails exits non-zero with no
# output, so the caller keeps its last list rather than showing an empty one;
# a query that succeeds with no devices exits zero and also prints nothing.
#
# The test stubs qdbus6 on PATH; see test-kdeconnect-state.sh.
set -u
BUS=org.kde.kdeconnect
ROOT=/modules/kdeconnect
QDBUS=qdbus6
# A scalar property or method value for a device, empty on any failure.
prop() {
"$QDBUS" "$BUS" "$ROOT/devices/$1" "org.kde.kdeconnect.device.$2" 2>/dev/null
}
bool() {
case "$(prop "$1" "$2")" in
true) printf 1 ;;
*) printf 0 ;;
esac
}
# A device name is attacker-adjacent text; a tab or newline in it must not
# break the line protocol.
sanitize() {
printf '%s' "$1" | tr '\t\n' ' '
}
emit_device() {
local id="$1" name type paired reachable pr pbp key charge charging
name="$(sanitize "$(prop "$id" name)")"
type="$(sanitize "$(prop "$id" type)")"
paired="$(bool "$id" isPaired)"
reachable="$(bool "$id" isReachable)"
pr="$(bool "$id" isPairRequested)"
pbp="$(bool "$id" isPairRequestedByPeer)"
# The key only means anything while a pairing is in flight.
key=""
if [[ "$pr" == 1 || "$pbp" == 1 ]]; then
key="$(sanitize "$(prop "$id" verificationKey)")"
fi
# The battery plugin is not on every device: a desktop without a battery
# object already returned qdbus an error. An absent query is an empty
# field, never a zero.
charge="$("$QDBUS" "$BUS" "$ROOT/devices/$id/battery" \
org.freedesktop.DBus.Properties.Get \
org.kde.kdeconnect.device.battery charge 2>/dev/null)"
[[ "$charge" =~ ^[0-9]+$ ]] || charge=""
charging=0
if [[ -n "$charge" ]]; then
case "$("$QDBUS" "$BUS" "$ROOT/devices/$id/battery" \
org.freedesktop.DBus.Properties.Get \
org.kde.kdeconnect.device.battery isCharging 2>/dev/null)" in
true) charging=1 ;;
esac
fi
printf 'device\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
"$id" "$name" "$type" "$paired" "$reachable" "$pr" "$pbp" \
"$key" "$charge" "$charging"
}
main() {
local ids
# Command substitution carries qdbus's exit status; a failed list is the
# error case, not an empty device list.
ids="$("$QDBUS" "$BUS" "$ROOT" org.kde.kdeconnect.daemon.devices 2>/dev/null)" || exit 1
local reqs r
reqs="$("$QDBUS" "$BUS" "$ROOT" org.freedesktop.DBus.Properties.Get \
org.kde.kdeconnect.daemon pairingRequests 2>/dev/null)" || exit 1
for r in $reqs; do
printf 'request\t%s\n' "$r"
done
local id
for id in $ids; do
[[ -n "$id" ]] && emit_device "$id"
done
}
main "$@"
|