all Dbus methods covered.
Now to add some niceties and add tests.
This commit is contained in:
parent
8ab14af06c
commit
25f9c3c1c9
6
TODO
6
TODO
@ -1,3 +1,9 @@
|
|||||||
- XML import/export?
|
- XML import/export?
|
||||||
-- compat with kwalletmanager
|
-- compat with kwalletmanager
|
||||||
--- Will require conversion to different struct model.
|
--- Will require conversion to different struct model.
|
||||||
|
|
||||||
|
- Write* and Create*/New* methods
|
||||||
|
-- return relevant entry as native item
|
||||||
|
-- confirm i'm checking the result code for all of them.
|
||||||
|
|
||||||
|
- TESTS
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package gokwallet
|
package gokwallet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/godbus/dbus/v5"
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NewBlob returns a Blob. It requires a RecurseOpts
|
NewBlob returns a Blob. It requires a RecurseOpts
|
||||||
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
|
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
|
||||||
@ -37,7 +41,15 @@ func NewBlob(f *Folder, keyName string, recursion *RecurseOpts) (blob *Blob, err
|
|||||||
// Update fetches a Blob's Blob.Value.
|
// Update fetches a Blob's Blob.Value.
|
||||||
func (b *Blob) Update() (err error) {
|
func (b *Blob) Update() (err error) {
|
||||||
|
|
||||||
// TODO.
|
var v dbus.Variant
|
||||||
|
|
||||||
|
if err = b.Dbus.Call(
|
||||||
|
DbusWMReadEntry, 0, b.folder.wallet.handle, b.folder.Name, b.Name, b.folder.wallet.wm.AppID,
|
||||||
|
).Store(&v); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Value = v.Value().([]byte)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
18
consts.go
18
consts.go
@ -6,13 +6,15 @@ const (
|
|||||||
DbusFailure int32 = 1
|
DbusFailure int32 = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type kwalletdEnumType int32
|
||||||
|
|
||||||
// KwalletD Dbus enums for WalletItem types.
|
// KwalletD Dbus enums for WalletItem types.
|
||||||
const (
|
const (
|
||||||
kwalletdEnumTypeUnknown int32 = iota // UnknownItem (0)
|
KwalletdEnumTypeUnknown kwalletdEnumType = iota // UnknownItem (0)
|
||||||
kwalletdEnumTypePassword // Password (1)
|
KwalletdEnumTypePassword // Password (1)
|
||||||
kwalletdEnumTypeStream // Blob (2)
|
KwalletdEnumTypeStream // Blob (2)
|
||||||
kwalletdEnumTypeMap // Map (3)
|
KwalletdEnumTypeMap // Map (3)
|
||||||
kwalletdEnumTypeUnused = 0xffff // 65535
|
KwalletdEnumTypeUnused = 0xffff // 65535
|
||||||
)
|
)
|
||||||
|
|
||||||
// KWalletD Dbus interfaces.
|
// KWalletD Dbus interfaces.
|
||||||
@ -147,7 +149,7 @@ const (
|
|||||||
|
|
||||||
Deprecated: use DbusWMEntriesList instead.
|
Deprecated: use DbusWMEntriesList instead.
|
||||||
*/
|
*/
|
||||||
DbusWMReadEntryList string = DbusInterfaceWM + ".readEntryList"
|
// DbusWMReadEntryList string = DbusInterfaceWM + ".readEntryList"
|
||||||
|
|
||||||
// DbusWMReadMap returns a Map from a Folder (as a byteslice).
|
// DbusWMReadMap returns a Map from a Folder (as a byteslice).
|
||||||
DbusWMReadMap string = DbusInterfaceWM + ".readMap"
|
DbusWMReadMap string = DbusInterfaceWM + ".readMap"
|
||||||
@ -157,7 +159,7 @@ const (
|
|||||||
|
|
||||||
Deprecated: use DbusWMMapList instead.
|
Deprecated: use DbusWMMapList instead.
|
||||||
*/
|
*/
|
||||||
DbusWMReadMapList string = DbusInterfaceWM + ".readMapList"
|
// DbusWMReadMapList string = DbusInterfaceWM + ".readMapList"
|
||||||
|
|
||||||
// DbusWMReadPassword returns a Password from a Folder (as a byteslice).
|
// DbusWMReadPassword returns a Password from a Folder (as a byteslice).
|
||||||
DbusWMReadPassword string = DbusInterfaceWM + ".readPassword"
|
DbusWMReadPassword string = DbusInterfaceWM + ".readPassword"
|
||||||
@ -167,7 +169,7 @@ const (
|
|||||||
|
|
||||||
Deprecated: use DbusWMPasswordList instead.
|
Deprecated: use DbusWMPasswordList instead.
|
||||||
*/
|
*/
|
||||||
DbusWMReadPasswordList string = DbusInterfaceWM + ".readPasswordList"
|
// DbusWMReadPasswordList string = DbusInterfaceWM + ".readPasswordList"
|
||||||
|
|
||||||
// DbusWMReconfigure is [FUNCTION UNKNOWN/UNDOCUMENTED; TODO? NOT IMPLEMENTED.]
|
// DbusWMReconfigure is [FUNCTION UNKNOWN/UNDOCUMENTED; TODO? NOT IMPLEMENTED.]
|
||||||
// DbusWMReconfigure string = DbusInterfaceWM + ".reconfigure"
|
// DbusWMReconfigure string = DbusInterfaceWM + ".reconfigure"
|
||||||
|
2
errs.go
2
errs.go
@ -23,4 +23,6 @@ var (
|
|||||||
ErrNoCreate error = errors.New("failed to create an object")
|
ErrNoCreate error = errors.New("failed to create an object")
|
||||||
// ErrNoDisconnect can occur if trying to disconnect a Wallet from a WalletManager/application and a failure occurs.
|
// ErrNoDisconnect can occur if trying to disconnect a Wallet from a WalletManager/application and a failure occurs.
|
||||||
ErrNoDisconnect error = errors.New("failed to disconnect wallet from application")
|
ErrNoDisconnect error = errors.New("failed to disconnect wallet from application")
|
||||||
|
// ErrInvalidMap will get triggered if a populated map[string]string (even an empty one) is expected but a nil is received.
|
||||||
|
ErrInvalidMap error = errors.New("invalid map; cannot be nil")
|
||||||
)
|
)
|
||||||
|
166
folder_funcs.go
166
folder_funcs.go
@ -44,6 +44,78 @@ func NewFolder(w *Wallet, name string, recursion *RecurseOpts) (folder *Folder,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasEntry specifies if a Folder has an entry (WalletItem item) by the give entryName.
|
||||||
|
func (f *Folder) HasEntry(entryName string) (hasEntry bool, err error) {
|
||||||
|
|
||||||
|
if err = f.Dbus.Call(
|
||||||
|
DbusWMHasEntry, 0, f.wallet.handle, f.Name, entryName, f.wallet.wm.AppID,
|
||||||
|
).Store(&hasEntry); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
KeyNotExist returns true if a key/entry name entryName does *not* exist.
|
||||||
|
Essentially the same as Folder.HasEntry, but whereas Folder.HasEntry requires the parent wallet
|
||||||
|
to be open/unlocked, Folder.KeyNotExist does not require this.
|
||||||
|
*/
|
||||||
|
func (f *Folder) KeyNotExist(entryName string) (doesNotExist bool, err error) {
|
||||||
|
|
||||||
|
if err = f.Dbus.Call(
|
||||||
|
DbusWMKeyNotExist, 0, f.wallet.Name, f.Name, entryName,
|
||||||
|
).Store(&doesNotExist); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEntries lists all entries (WalletItem items) in a Folder (regardless of type) by name.
|
||||||
|
func (f *Folder) ListEntries() (entryNames []string, err error) {
|
||||||
|
|
||||||
|
if err = f.Dbus.Call(
|
||||||
|
DbusWMEntryList, 0, f.wallet.handle, f.Name, f.wallet.wm.AppID,
|
||||||
|
).Store(&entryNames); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveEntry removes a WalletItem from a Folder given its entryName (key).
|
||||||
|
func (f *Folder) RemoveEntry(entryName string) (err error) {
|
||||||
|
|
||||||
|
var rslt int32
|
||||||
|
|
||||||
|
if err = f.Dbus.Call(
|
||||||
|
DbusWMRemoveEntry, 0, f.wallet.handle, f.Name, entryName, f.wallet.wm.AppID,
|
||||||
|
).Store(&rslt); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resultCheck(rslt)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenameEntry renames a WalletItem in a Folder from entryName to newEntryName.
|
||||||
|
func (f *Folder) RenameEntry(entryName, newEntryName string) (err error) {
|
||||||
|
|
||||||
|
var rslt int32
|
||||||
|
|
||||||
|
if err = f.Dbus.Call(
|
||||||
|
DbusWMRenameEntry, 0, f.wallet.handle, f.Name, entryName, newEntryName, f.wallet.wm.AppID,
|
||||||
|
).Store(&rslt); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resultCheck(rslt)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Update runs all of the configured Update[type] methods for a Folder, depending on Folder.Recurse configuration.
|
// Update runs all of the configured Update[type] methods for a Folder, depending on Folder.Recurse configuration.
|
||||||
func (f *Folder) Update() (err error) {
|
func (f *Folder) Update() (err error) {
|
||||||
|
|
||||||
@ -172,7 +244,7 @@ func (f *Folder) UpdateBlobs() (err error) {
|
|||||||
f.BinaryData = make(map[string]*Blob, len(mapKeys))
|
f.BinaryData = make(map[string]*Blob, len(mapKeys))
|
||||||
|
|
||||||
for _, k := range mapKeys {
|
for _, k := range mapKeys {
|
||||||
if isBlob, err = f.isType(k, kwalletdEnumTypeStream); err != nil {
|
if isBlob, err = f.isType(k, KwalletdEnumTypeStream); err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
err = nil
|
err = nil
|
||||||
continue
|
continue
|
||||||
@ -218,7 +290,7 @@ func (f *Folder) UpdateUnknowns() (err error) {
|
|||||||
f.Unknown = make(map[string]*UnknownItem, len(mapKeys))
|
f.Unknown = make(map[string]*UnknownItem, len(mapKeys))
|
||||||
|
|
||||||
for _, k := range mapKeys {
|
for _, k := range mapKeys {
|
||||||
if isUnknown, err = f.isType(k, kwalletdEnumTypeUnknown); err != nil {
|
if isUnknown, err = f.isType(k, KwalletdEnumTypeUnknown); err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
err = nil
|
err = nil
|
||||||
continue
|
continue
|
||||||
@ -240,8 +312,90 @@ func (f *Folder) UpdateUnknowns() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// isType checks if a certain key keyName is of type typeCheck (via kwalletdEnumType*).
|
// WriteBlob adds or replaces a Blob to/in a Folder.
|
||||||
func (f *Folder) isType(keyName string, typeCheck int32) (isOfType bool, err error) {
|
func (f *Folder) WriteBlob(entryName string, entryValue []byte) (err error) {
|
||||||
|
|
||||||
|
if err = f.WriteEntry(entryName, KwalletdEnumTypeStream, entryValue); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
WriteEntry is used for adding/replacing a WalletItem as a general interface.
|
||||||
|
If possible, you'll want to use a item-type-specific method (e.g. Folder.WritePassword) as this one is a little unwieldy to use.
|
||||||
|
entryType must be the relevant KwalletdEnumType* constant (do not use KwalletdEnumTypeUnused).
|
||||||
|
*/
|
||||||
|
func (f *Folder) WriteEntry(entryName string, entryType kwalletdEnumType, entryValue []byte) (err error) {
|
||||||
|
|
||||||
|
var rslt int32
|
||||||
|
|
||||||
|
if entryType == KwalletdEnumTypeUnused {
|
||||||
|
err = ErrNoCreate
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = f.Dbus.Call(
|
||||||
|
DbusWMWriteEntry, 0, f.wallet.handle, f.Name, entryName, entryValue, int32(entryType), f.wallet.wm.AppID,
|
||||||
|
).Store(&rslt); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resultCheck(rslt)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteMap adds or replaces a Map to/in a Folder.
|
||||||
|
func (f *Folder) WriteMap(entryName string, entryValue map[string]string) (err error) {
|
||||||
|
|
||||||
|
var rslt int32
|
||||||
|
var b []byte
|
||||||
|
|
||||||
|
if b, err = mapToBytes(entryValue); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = f.Dbus.Call(
|
||||||
|
DbusWMWriteMap, 0, f.wallet.handle, f.Name, entryName, b, f.wallet.wm.AppID,
|
||||||
|
).Store(&rslt); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resultCheck(rslt)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WritePassword adds or replaces a Password to/in a Folder.
|
||||||
|
func (f *Folder) WritePassword(entryName, entryValue string) (err error) {
|
||||||
|
|
||||||
|
var rslt int32
|
||||||
|
|
||||||
|
if err = f.Dbus.Call(
|
||||||
|
DbusWMWritePassword, 0, f.wallet.handle, f.Name, entryName, entryValue, f.wallet.wm.AppID,
|
||||||
|
).Store(&rslt); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = resultCheck(rslt)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteUnknown adds or replaces an UnknownItem to/in a Folder.
|
||||||
|
func (f *Folder) WriteUnknown(entryName string, entryValue []byte) (err error) {
|
||||||
|
|
||||||
|
if err = f.WriteEntry(entryName, KwalletdEnumTypeUnknown, entryValue); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// isType checks if a certain key keyName is of type typeCheck (via KwalletdEnumType*).
|
||||||
|
func (f *Folder) isType(keyName string, typeCheck kwalletdEnumType) (isOfType bool, err error) {
|
||||||
|
|
||||||
var entryType int32
|
var entryType int32
|
||||||
|
|
||||||
@ -251,5 +405,9 @@ func (f *Folder) isType(keyName string, typeCheck int32) (isOfType bool, err err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if int32(typeCheck) == entryType {
|
||||||
|
isOfType = true
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
5
go.mod
5
go.mod
@ -2,7 +2,4 @@ module r00t2.io/gokwallet
|
|||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require github.com/godbus/dbus/v5 v5.0.6
|
||||||
github.com/godbus/dbus/v5 v5.0.6
|
|
||||||
r00t2.io/goutils v1.1.0
|
|
||||||
)
|
|
||||||
|
5
go.sum
5
go.sum
@ -1,7 +1,2 @@
|
|||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
|
||||||
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/jszwec/csvutil v1.5.0/go.mod h1:Rpu7Uu9giO9subDyMCIQfHVDuLrcaC36UA4YcJjGBkg=
|
|
||||||
r00t2.io/goutils v1.1.0 h1:vJqEWvdX0TKDyT+hTgws0wA1dc/F8JkQKw5cDHz0wH0=
|
|
||||||
r00t2.io/goutils v1.1.0/go.mod h1:CMK3RGnMSyjDSfYxeFQl/oJTkkUMS1jhSTdGTkAPpQw=
|
|
||||||
r00t2.io/sysutils v0.0.0-20210224054841-55ac47c86928/go.mod h1:XzJkBF6SHAODEszJlOcjtGoTHwYnZZNmseA6PyOujes=
|
|
||||||
|
12
map_funcs.go
12
map_funcs.go
@ -37,7 +37,17 @@ func NewMap(f *Folder, keyName string, recursion *RecurseOpts) (m *Map, err erro
|
|||||||
// Update fetches a Map's Map.Value.
|
// Update fetches a Map's Map.Value.
|
||||||
func (m *Map) Update() (err error) {
|
func (m *Map) Update() (err error) {
|
||||||
|
|
||||||
// TODO.
|
var b []byte
|
||||||
|
|
||||||
|
if err = m.Dbus.Call(
|
||||||
|
DbusWMReadMap, 0, m.folder.wallet.handle, m.folder.Name, m.Name, m.folder.wallet.wm.AppID,
|
||||||
|
).Store(&b); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Value, _, err = bytesToMap(b); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ func NewErrors(errs ...error) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error returns a string representation of a MultiError (to conform with the error interface).
|
||||||
func (e *MultiError) Error() (errStr string) {
|
func (e *MultiError) Error() (errStr string) {
|
||||||
|
|
||||||
var numErrs int
|
var numErrs int
|
||||||
|
@ -37,7 +37,15 @@ func NewPassword(f *Folder, keyName string, recursion *RecurseOpts) (password *P
|
|||||||
// Update fetches a Password's Password.Value.
|
// Update fetches a Password's Password.Value.
|
||||||
func (p *Password) Update() (err error) {
|
func (p *Password) Update() (err error) {
|
||||||
|
|
||||||
// TODO.
|
var b []byte
|
||||||
|
|
||||||
|
if err = p.Dbus.Call(
|
||||||
|
DbusWMReadPassword, 0, p.folder.wallet.handle, p.folder.Name, p.Name, p.folder.wallet.wm.AppID,
|
||||||
|
).Store(&b); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Value = string(b)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
5
types.go
5
types.go
@ -184,15 +184,14 @@ type Blob struct {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
UnknownItem is a secret item of unknown classification, so there isn't exactly a good way of determining a type for UnknownItem.Value.
|
UnknownItem is a secret item of unknown classification, so there isn't exactly a good way of determining a type for UnknownItem.Value.
|
||||||
As such, its dbus.ObjectPath is used.
|
As such, its UnknownItem.Value is just raw bytes.
|
||||||
TODO: There may be a method to fetch the raw bytes of the object (such as one would use with Blob) in the future.
|
|
||||||
*/
|
*/
|
||||||
type UnknownItem struct {
|
type UnknownItem struct {
|
||||||
*DbusObject
|
*DbusObject
|
||||||
// Name is the name of this UnknownItem.
|
// Name is the name of this UnknownItem.
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// Value is the Dbus path of this UnknownItem.
|
// Value is the Dbus path of this UnknownItem.
|
||||||
Value dbus.ObjectPath `json:"value"`
|
Value []byte `json:"value"`
|
||||||
// Recurse contains the relevant RecurseOpts.
|
// Recurse contains the relevant RecurseOpts.
|
||||||
Recurse *RecurseOpts `json:"recurse_opts"`
|
Recurse *RecurseOpts `json:"recurse_opts"`
|
||||||
// wm is the parent WalletManager that UnknownItem.folder.wallet was fetched from.
|
// wm is the parent WalletManager that UnknownItem.folder.wallet was fetched from.
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package gokwallet
|
package gokwallet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/godbus/dbus/v5"
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NewUnknownItem returns an UnknownItem. It requires a RecurseOpts
|
NewUnknownItem returns an UnknownItem. It requires a RecurseOpts
|
||||||
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
|
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
|
||||||
@ -37,7 +41,15 @@ func NewUnknownItem(f *Folder, keyName string, recursion *RecurseOpts) (unknown
|
|||||||
// Update fetches an UnknownItem's UnknownItem.Value.
|
// Update fetches an UnknownItem's UnknownItem.Value.
|
||||||
func (u *UnknownItem) Update() (err error) {
|
func (u *UnknownItem) Update() (err error) {
|
||||||
|
|
||||||
// TODO.
|
var v dbus.Variant
|
||||||
|
|
||||||
|
if err = u.Dbus.Call(
|
||||||
|
DbusWMReadEntry, 0, u.folder.wallet.handle, u.folder.Name, u.Name, u.folder.wallet.wm.AppID,
|
||||||
|
).Store(&v); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
u.Value = v.Value().([]byte)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
112
utils.go
112
utils.go
@ -1,6 +1,10 @@
|
|||||||
package gokwallet
|
package gokwallet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/godbus/dbus/v5"
|
"github.com/godbus/dbus/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -59,3 +63,111 @@ func bytemapKeys(variant dbus.Variant) (keyNames []string) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bytesToMap takes a byte slice and returns a map[string]string based on a Dbus QMap struct(ure).
|
||||||
|
func bytesToMap(raw []byte) (m map[string]string, numEntries uint32, err error) {
|
||||||
|
|
||||||
|
var buf *bytes.Reader
|
||||||
|
var kLen uint32
|
||||||
|
var vLen uint32
|
||||||
|
var k []byte
|
||||||
|
var v []byte
|
||||||
|
|
||||||
|
/*
|
||||||
|
I considered using:
|
||||||
|
- https://github.com/lunixbochs/struc
|
||||||
|
- https://github.com/roman-kachanovsky/go-binary-pack
|
||||||
|
- https://github.com/go-restruct/restruct
|
||||||
|
|
||||||
|
The second hasn't been updated in quite some time, the first or third would have been a headache due to the variable length,
|
||||||
|
and ultimately I felt it was silly to add a dependency for only a single piece of data (Map).
|
||||||
|
So sticking to stdlib.
|
||||||
|
*/
|
||||||
|
|
||||||
|
buf = bytes.NewReader(raw)
|
||||||
|
|
||||||
|
if err = binary.Read(buf, binary.BigEndian, &numEntries); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m = make(map[string]string, numEntries)
|
||||||
|
|
||||||
|
for i := uint32(0); i < numEntries; i++ {
|
||||||
|
if err = binary.Read(buf, binary.BigEndian, &kLen); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
k = make([]byte, kLen)
|
||||||
|
|
||||||
|
if err = binary.Read(buf, binary.BigEndian, &k); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = binary.Read(buf, binary.BigEndian, &vLen); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v = make([]byte, vLen)
|
||||||
|
|
||||||
|
if err = binary.Read(buf, binary.BigEndian, &v); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// QMap does this infuriating thing where it separates each character with a null byte. So we need to strip them out.
|
||||||
|
k = bytes.ReplaceAll(k, []byte{0x0}, []byte{})
|
||||||
|
v = bytes.ReplaceAll(v, []byte{0x0}, []byte{})
|
||||||
|
|
||||||
|
m[string(k)] = string(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapToBytes performs the inverse of bytesToMap.
|
||||||
|
func mapToBytes(m map[string]string) (raw []byte, err error) {
|
||||||
|
|
||||||
|
var numEntries uint32
|
||||||
|
var buf *bytes.Buffer
|
||||||
|
var kLen uint32
|
||||||
|
var vLen uint32
|
||||||
|
var kB []byte
|
||||||
|
var vB []byte
|
||||||
|
|
||||||
|
if m == nil {
|
||||||
|
err = ErrInvalidMap
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
numEntries = uint32(len(m))
|
||||||
|
|
||||||
|
buf = &bytes.Buffer{}
|
||||||
|
|
||||||
|
if err = binary.Write(buf, binary.BigEndian, &numEntries); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range m {
|
||||||
|
kB = []byte(strings.Join(strings.Split(k, ""), "\x00"))
|
||||||
|
vB = []byte(strings.Join(strings.Split(v, ""), "\x00"))
|
||||||
|
kLen = uint32(len(kB))
|
||||||
|
vLen = uint32(len(vB))
|
||||||
|
|
||||||
|
if err = binary.Write(buf, binary.BigEndian, &kLen); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = binary.Write(buf, binary.BigEndian, &k); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = binary.Write(buf, binary.BigEndian, &vLen); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = binary.Write(buf, binary.BigEndian, &v); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
raw = buf.Bytes()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -223,6 +223,18 @@ func (w *Wallet) ForceClose() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasFolder indicates if a Wallet has a Folder in it named folderName.
|
||||||
|
func (w *Wallet) HasFolder(folderName string) (hasFolder bool, err error) {
|
||||||
|
|
||||||
|
if err = w.Dbus.Call(
|
||||||
|
DbusWMHasFolder, 0, w.handle, folderName, w.wm.AppID,
|
||||||
|
).Store(&hasFolder); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// IsOpen returns whether a Wallet is open ("unlocked") or not (as well as updates Wallet.IsOpen).
|
// IsOpen returns whether a Wallet is open ("unlocked") or not (as well as updates Wallet.IsOpen).
|
||||||
func (w *Wallet) IsOpen() (isOpen bool, err error) {
|
func (w *Wallet) IsOpen() (isOpen bool, err error) {
|
||||||
|
|
||||||
@ -286,6 +298,28 @@ func (w *Wallet) Open() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
RemoveFolder removes a Folder folderName from a Wallet.
|
||||||
|
Note that this will also remove all WalletItems in the given Folder.
|
||||||
|
*/
|
||||||
|
func (w *Wallet) RemoveFolder(folderName string) (err error) {
|
||||||
|
|
||||||
|
var success bool
|
||||||
|
|
||||||
|
if err = w.Dbus.Call(
|
||||||
|
DbusWMRemoveFolder, 0, w.handle, folderName, w.wm.AppID,
|
||||||
|
).Store(&success); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !success {
|
||||||
|
err = ErrOperationFailed
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Update fetches/updates all Folder objects in a Wallet.
|
// Update fetches/updates all Folder objects in a Wallet.
|
||||||
func (w *Wallet) Update() (err error) {
|
func (w *Wallet) Update() (err error) {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user