【发布时间】:2018-11-21 00:41:53
【问题描述】:
我正在尝试从 awesome-wm 会话的密钥环获取密码(通过 lgi 库使用 DBus)。
我能够找到密钥环入口路径,打开通信会话并解锁入口。
然后我调用GetSecrets 方法并将结果存储到secret 变量中。
根据文档,它应该是struct Secret。似乎lgi 无法处理此类型并将其作为userdata 类型传递(至少我无法使其访问结构字段)。有没有办法在不编写自定义 C 处理程序的情况下获取 struct Secret value 字段内容?
代码如下:
local bus = Gio.bus_get_sync(Gio.BusType.SESSION, nil)
local attr = {}
attr[1] = {attribute = "value"} -- attribute-value pair to search for
-- search for secret path
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "SearchItems"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(a{ss})", attr))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
local location
for _, l in result:get_body():pairs() do
if #l > 0 then location = l[1] end
end
print(location) -- returns "/org/freedesktop/secrets/collection/Default/1"
-- open session
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "OpenSession"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(sv)", {"plain", GLib.Variant("s", "")}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
local session = result:get_body()[2]
print(session) -- returns "/org/freedesktop/secrets/session/s4"
-- unlock key
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "Unlock"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(ao)", {{location}}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
-- at this point key property "Locked" if false. tested using d-feet
-- get secret
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "GetSecrets"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(aoo)", {{location},session}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
local secret = result:get_body()
print(#secret) -- returns "1"
print(secret) -- returns table address
print(type(secret)) -- returns "userdata"
-- lock key
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "Lock"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(ao)", {{location}}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
-- close session
local name = "org.freedesktop.secrets"
local object = location
local interface = "org.freedesktop.Secret.Session"
local method = "Close"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
编辑
当我执行print(secret) 时,会返回lgi.rec 0x7f57d0014960:GLib.Variant。
所以,secret 是一个对象。如何从GLib.Variant 对象中检索value 字段?
编辑 2
secret:get_data_as_bytes():get_data() 以字节数组形式转储结构; secret:print() 返回结构体的格式化字符串。不知道有没有更好的办法。
编辑 3
secret 变量的类型是 (a{o(oayays)})
重新创建该类型对象的代码:
local lgi = require 'lgi'
local Gio = lgi.require 'Gio'
local GLib = lgi.require 'GLib'
local var = GLib.Variant("(a{o(oayays)})", {{["/path/to/object"]={"/path/to/session","parameters","value","content_type"}}})
【问题讨论】:
-
你可以检查用户数据是否有一个带有
__index元方法的元表来访问结构的字段。 -
@cyclaminist 证明
secret是GLib.Variant类型的对象。现在我需要弄清楚如何从中获取value。
标签: lua dbus awesome-wm lgi