folder mostly done, types (partially) stubbed out.

This commit is contained in:
brent s. 2021-12-20 04:02:48 -05:00
parent d76746d79e
commit 8ab14af06c
Signed by: bts
GPG Key ID: 8C004C2F93481F6B
11 changed files with 605 additions and 35 deletions

51
blob_funcs.go Normal file
View File

@ -0,0 +1,51 @@
package gokwallet

/*
NewBlob returns a Blob. It requires a RecurseOpts
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
It also requires a Folder.
*/
func NewBlob(f *Folder, keyName string, recursion *RecurseOpts) (blob *Blob, err error) {

if !f.isInit {
err = ErrNotInitialized
return
}

blob = &Blob{
DbusObject: f.DbusObject,
Name: keyName,
// Value: "",
Recurse: recursion,
wm: f.wallet.wm,
wallet: f.wallet,
folder: f,
isInit: false,
}

if blob.Recurse.AllWalletItems || blob.Recurse.Blobs {
if err = blob.Update(); err != nil {
return
}
}

blob.isInit = true

return
}

// Update fetches a Blob's Blob.Value.
func (b *Blob) Update() (err error) {

// TODO.

return
}

// isWalletItem is needed for interface membership.
func (b *Blob) isWalletItem() (isWalletItem bool) {

isWalletItem = true

return
}

View File

@ -8,11 +8,11 @@ const (

// KwalletD Dbus enums for WalletItem types.
const (
kwalletdEnumTypeUnknown = iota // UnknownItem
kwalletdEnumTypePassword // Password
kwalletdEnumTypeStream // Blob
kwalletdEnumTypeMap // Map
kwalletdEnumTypeUnused = 0xffff // 65535
kwalletdEnumTypeUnknown int32 = iota // UnknownItem (0)
kwalletdEnumTypePassword // Password (1)
kwalletdEnumTypeStream // Blob (2)
kwalletdEnumTypeMap // Map (3)
kwalletdEnumTypeUnused = 0xffff // 65535
)

// KWalletD Dbus interfaces.

View File

@ -17,4 +17,10 @@ var (
ErrOperationFailed is a generic failure message that will occur of a Dbus operation returns non-success.
*/
ErrOperationFailed error = errors.New("a Dbus operation has failed to execute successfully")
/*
ErrNoCreate is triggered if attempting to create an item (Folder, Password, etc.) but it fails.
*/
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 error = errors.New("failed to disconnect wallet from application")
)

View File

@ -1,9 +1,13 @@
package gokwallet

import (
"github.com/godbus/dbus/v5"
)

/*
NewF returns a Wallet. It requires a RecurseOpts
NewFolder returns a Folder. It requires a RecurseOpts
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
It also requires a WalletManager and wallet name.
It also requires a Wallet.
*/
func NewFolder(w *Wallet, name string, recursion *RecurseOpts) (folder *Folder, err error) {

@ -22,15 +26,14 @@ func NewFolder(w *Wallet, name string, recursion *RecurseOpts) (folder *Folder,
Recurse: recursion,
wm: w.wm,
wallet: w,
// handle: 0,
isInit: false,
isInit: false,
}

if err = folder.folderCheck(); err != nil {
return
}

if folder.Recurse.All || folder.Recurse.Wallets {
if folder.Recurse.AllWalletItems ||
folder.Recurse.Passwords ||
folder.Recurse.Maps ||
folder.Recurse.Blobs ||
folder.Recurse.UnknownItems {
if err = folder.Update(); err != nil {
return
}
@ -41,16 +44,212 @@ func NewFolder(w *Wallet, name string, recursion *RecurseOpts) (folder *Folder,
return
}

// Update runs all of the configured Update[type] methods for a Folder, depending on Folder.Recurse configuration.
func (f *Folder) Update() (err error) {

// TODO.
var errs []error = make([]error, 0)

if f.Recurse.AllWalletItems || f.Recurse.Passwords {
if err = f.UpdatePasswords(); err != nil {
errs = append(errs, err)
err = nil
}
}
if f.Recurse.AllWalletItems || f.Recurse.Maps {
if err = f.UpdateMaps(); err != nil {
errs = append(errs, err)
err = nil
}
}
if f.Recurse.AllWalletItems || f.Recurse.Blobs {
if err = f.UpdateBlobs(); err != nil {
errs = append(errs, err)
err = nil
}
}
if f.Recurse.AllWalletItems || f.Recurse.UnknownItems {
if err = f.UpdateUnknowns(); err != nil {
errs = append(errs, err)
err = nil
}
}

if errs != nil && len(errs) > 0 {
err = NewErrors(errs...)
}

return
}

func (f *Folder) folderCheck() (err error) {
// UpdatePasswords updates (populates) a Folder's Folder.Passwords.
func (f *Folder) UpdatePasswords() (err error) {

// TODO.
var mapKeys []string
var variant dbus.Variant
var errs []error = make([]error, 0)

if !f.isInit {
err = ErrNotInitialized
return
}

if err = f.Dbus.Call(
DbusWMPasswordList, 0, f.wallet.handle, f.Name, f.wallet.wm.AppID,
).Store(&variant); err != nil {
return
}

mapKeys = bytemapKeys(variant)

f.Passwords = make(map[string]*Password, len(mapKeys))

for _, k := range mapKeys {
if f.Passwords[k], err = NewPassword(f, k, f.Recurse); err != nil {
errs = append(errs, err)
err = nil
}
}

if errs != nil && len(errs) > 0 {
err = NewErrors(errs...)
}

return
}

// UpdateMaps updates (populates) a Folder's Folder.Maps.
func (f *Folder) UpdateMaps() (err error) {

var mapKeys []string
var variant dbus.Variant
var errs []error = make([]error, 0)

if err = f.Dbus.Call(
DbusWMMapList, 0, f.wallet.handle, f.Name, f.wallet.wm.AppID,
).Store(&variant); err != nil {
return
}

mapKeys = bytemapKeys(variant)

f.Maps = make(map[string]*Map, len(mapKeys))

for _, k := range mapKeys {
if f.Maps[k], err = NewMap(f, k, f.Recurse); err != nil {
errs = append(errs, err)
err = nil
}
}

if errs != nil && len(errs) > 0 {
err = NewErrors(errs...)
}

return
}

// UpdateBlobs updates (populates) a Folder's Folder.BinaryData.
func (f *Folder) UpdateBlobs() (err error) {

var mapKeys []string
var isBlob bool
var variant dbus.Variant
var errs []error = make([]error, 0)

if !f.isInit {
err = ErrNotInitialized
return
}

if err = f.Dbus.Call(
DbusWMEntriesList, 0, f.wallet.handle, f.Name, f.wallet.wm.AppID,
).Store(&variant); err != nil {
return
}

mapKeys = bytemapKeys(variant)

f.BinaryData = make(map[string]*Blob, len(mapKeys))

for _, k := range mapKeys {
if isBlob, err = f.isType(k, kwalletdEnumTypeStream); err != nil {
errs = append(errs, err)
err = nil
continue
}
if !isBlob {
continue
}

if f.BinaryData[k], err = NewBlob(f, k, f.Recurse); err != nil {
errs = append(errs, err)
err = nil
}
}

if errs != nil && len(errs) > 0 {
err = NewErrors(errs...)
}

return
}

// UpdateUnknowns updates (populates) a Folder's Folder.Unknown.
func (f *Folder) UpdateUnknowns() (err error) {

var mapKeys []string
var isUnknown bool
var variant dbus.Variant
var errs []error = make([]error, 0)

if !f.isInit {
err = ErrNotInitialized
return
}

if err = f.Dbus.Call(
DbusWMEntriesList, 0, f.wallet.handle, f.Name, f.wallet.wm.AppID,
).Store(&variant); err != nil {
return
}

mapKeys = bytemapKeys(variant)

f.Unknown = make(map[string]*UnknownItem, len(mapKeys))

for _, k := range mapKeys {
if isUnknown, err = f.isType(k, kwalletdEnumTypeUnknown); err != nil {
errs = append(errs, err)
err = nil
continue
}
if !isUnknown {
continue
}

if f.Unknown[k], err = NewUnknownItem(f, k, f.Recurse); err != nil {
errs = append(errs, err)
err = nil
}
}

if errs != nil && len(errs) > 0 {
err = NewErrors(errs...)
}

return
}

// isType checks if a certain key keyName is of type typeCheck (via kwalletdEnumType*).
func (f *Folder) isType(keyName string, typeCheck int32) (isOfType bool, err error) {

var entryType int32

if err = f.Dbus.Call(
DbusWMEntryType, 0, f.wallet.handle, f.Name, keyName, f.wallet.wm.AppID,
).Store(&entryType); err != nil {
return
}

return
}

51
map_funcs.go Normal file
View File

@ -0,0 +1,51 @@
package gokwallet

/*
NewMap returns a Map. It requires a RecurseOpts
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
It also requires a Folder.
*/
func NewMap(f *Folder, keyName string, recursion *RecurseOpts) (m *Map, err error) {

if !f.isInit {
err = ErrNotInitialized
return
}

m = &Map{
DbusObject: f.DbusObject,
Name: keyName,
// Value: "",
Recurse: recursion,
wm: f.wallet.wm,
wallet: f.wallet,
folder: f,
isInit: false,
}

if m.Recurse.AllWalletItems || m.Recurse.Maps {
if err = m.Update(); err != nil {
return
}
}

m.isInit = true

return
}

// Update fetches a Map's Map.Value.
func (m *Map) Update() (err error) {

// TODO.

return
}

// isWalletItem is needed for interface membership.
func (m *Map) isWalletItem() (isWalletItem bool) {

isWalletItem = true

return
}

51
password_funcs.go Normal file
View File

@ -0,0 +1,51 @@
package gokwallet

/*
NewPassword returns a Password. It requires a RecurseOpts
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
It also requires a Folder.
*/
func NewPassword(f *Folder, keyName string, recursion *RecurseOpts) (password *Password, err error) {

if !f.isInit {
err = ErrNotInitialized
return
}

password = &Password{
DbusObject: f.DbusObject,
Name: keyName,
// Value: "",
Recurse: recursion,
wm: f.wallet.wm,
wallet: f.wallet,
folder: f,
isInit: false,
}

if password.Recurse.AllWalletItems || password.Recurse.Passwords {
if err = password.Update(); err != nil {
return
}
}

password.isInit = true

return
}

// Update fetches a Password's Password.Value.
func (p *Password) Update() (err error) {

// TODO.

return
}

// isWalletItem is needed for interface membership.
func (p *Password) isWalletItem() (isWalletItem bool) {

isWalletItem = true

return
}

View File

@ -121,8 +121,6 @@ type Folder struct {
wm *WalletManager
// wallet is the parent Wallet this Folder was fetched from.
wallet *Wallet
// handle is this Folder's handler number.
handle int32
// isInit flags whether this is "properly" set up (i.e. has a handle).
isInit bool
}
@ -142,8 +140,6 @@ type Password struct {
wallet *Wallet
// folder is the parent Folder this Password was fetched from.
folder *Folder
// handle is this Password's handler number.
handle int32
// isInit flags whether this is "properly" set up (i.e. has a handle).
isInit bool
}
@ -163,8 +159,6 @@ type Map struct {
wallet *Wallet
// folder is the parent Folder this Map was fetched from.
folder *Folder
// handle is this Map's handler number.
handle int32
// isInit flags whether this is "properly" set up (i.e. has a handle).
isInit bool
}
@ -184,8 +178,6 @@ type Blob struct {
wallet *Wallet
// folder is the parent Folder this Blob was fetched from.
folder *Folder
// handle is this Blob's handler number.
handle int32
// isInit flags whether this is "properly" set up (i.e. has a handle).
isInit bool
}
@ -209,8 +201,6 @@ type UnknownItem struct {
wallet *Wallet
// folder is the parent Folder this UnknownItem was fetched from.
folder *Folder
// handle is this UnknownItem's handler number.
handle int32
// isInit flags whether this is "properly" set up (i.e. has a handle).
isInit bool
}

51
unknownitem_funcs.go Normal file
View File

@ -0,0 +1,51 @@
package gokwallet

/*
NewUnknownItem returns an UnknownItem. It requires a RecurseOpts
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
It also requires a Folder.
*/
func NewUnknownItem(f *Folder, keyName string, recursion *RecurseOpts) (unknown *UnknownItem, err error) {

if !f.isInit {
err = ErrNotInitialized
return
}

unknown = &UnknownItem{
DbusObject: f.DbusObject,
Name: keyName,
// Value: "",
Recurse: recursion,
wm: f.wallet.wm,
wallet: f.wallet,
folder: f,
isInit: false,
}

if unknown.Recurse.AllWalletItems || unknown.Recurse.UnknownItems {
if err = unknown.Update(); err != nil {
return
}
}

unknown.isInit = true

return
}

// Update fetches an UnknownItem's UnknownItem.Value.
func (u *UnknownItem) Update() (err error) {

// TODO.

return
}

// isWalletItem is needed for interface membership.
func (u *UnknownItem) isWalletItem() (isWalletItem bool) {

isWalletItem = true

return
}

View File

@ -1,5 +1,9 @@
package gokwallet

import (
"github.com/godbus/dbus/v5"
)

/*
resultCheck checks the result code from a Dbus call and returns an error if not successful.
See also resultPassed.
@ -12,6 +16,8 @@ func resultCheck(result int32) (err error) {
err = nil
case DbusFailure:
err = ErrOperationFailed
default:
err = ErrOperationFailed
}

return
@ -29,6 +35,26 @@ func resultPassed(result int32) (passed bool) {
passed = true
case DbusFailure:
passed = false
default:
passed = false
}

return
}

// bytemapKeys is used to parse out Map names when fetching from Dbus.
func bytemapKeys(variant dbus.Variant) (keyNames []string) {

var d map[string]dbus.Variant

d = variant.Value().(map[string]dbus.Variant)

keyNames = make([]string, len(d))

idx := 0
for k, _ := range d {
keyNames[idx] = k
idx++
}

return

View File

@ -1,5 +1,9 @@
package gokwallet

import (
"github.com/godbus/dbus/v5"
)

/*
NewWallet returns a Wallet. It requires a RecurseOpts
(you can use DefaultRecurseOpts, call NewRecurseOpts, or provide your own RecurseOpts struct).
@ -27,7 +31,7 @@ func NewWallet(wm *WalletManager, name string, recursion *RecurseOpts) (wallet *
return
}

if wallet.Recurse.All || wallet.Recurse.Wallets {
if wallet.Recurse.All || wallet.Recurse.Folders {
if err = wallet.Update(); err != nil {
return
}
@ -38,13 +42,73 @@ func NewWallet(wm *WalletManager, name string, recursion *RecurseOpts) (wallet *
return
}

// Disconnect disconnects this Wallet from its parent WalletManager.
func (w *Wallet) Disconnect() (err error) {

var ok bool

if err = w.walletCheck(); err != nil {
return
}

if err = w.Dbus.Call(
DbusWMDisconnectApp, 0, w.Name, w.wm.AppID,
).Store(&ok); err != nil {
return
}

if !ok {
err = ErrNoDisconnect
}

return
}

// DisconnectApplication disconnects this Wallet from a specified WalletManager/application (see Wallet.Connections).
func (w *Wallet) DisconnectApplication(appName string) (err error) {

var ok bool

if err = w.walletCheck(); err != nil {
return
}

if err = w.Dbus.Call(
DbusWMDisconnectApp, 0, appName, w.wm.AppID,
).Store(&ok); err != nil {
return
}

if !ok {
err = ErrNoDisconnect
}

return
}

/*
ChangePassword will change (or set) the password for a Wallet.
Note that this *must* be done via the windowing layer.
*/
func (w *Wallet) ChangePassword() (err error) {

var call *dbus.Call

call = w.Dbus.Call(
DbusWMChangePassword, 0, w.Name, DefaultWindowID, w.wm.AppID,
)

err = call.Err

return
}

// Close closes a Wallet.
func (w *Wallet) Close() (err error) {

var rslt int32

if !w.isInit {
err = ErrNotInitialized
if err = w.walletCheck(); err != nil {
return
}

@ -60,6 +124,80 @@ func (w *Wallet) Close() (err error) {
return
}

// Connections lists the application names for connections to ("users of") this Wallet.
func (w *Wallet) Connections() (connList []string, err error) {

if err = w.walletCheck(); err != nil {
return
}

if err = w.Dbus.Call(
DbusWMUsers, 0, w.Name,
).Store(&connList); err != nil {
return
}

return
}

// CreateFolder creates a new Folder in a Wallet.
func (w *Wallet) CreateFolder(name string) (err error) {

var ok bool

if err = w.walletCheck(); err != nil {
return
}

if err = w.Dbus.Call(
DbusWMCreateFolder, 0, w.handle, name, w.wm.AppID,
).Store(&ok); err != nil {
return
}

if !ok {
err = ErrNoCreate
}

return
}

// Delete deletes a Wallet.
func (w *Wallet) Delete() (err error) {

var rslt int32

if err = w.walletCheck(); err != nil {
return
}

if err = w.Dbus.Call(
DbusWMDeleteWallet, 0, w.Name,
).Store(&rslt); err != nil {
return
}

err = resultCheck(rslt)

return
}

// FolderExists indicates if a Folder exists in a Wallet or not.
func (w *Wallet) FolderExists(folderName string) (exists bool, err error) {

var notExists bool

if err = w.Dbus.Call(
DbusWMFolderNotExist, 0, w.Name, folderName,
).Store(&notExists); err != nil {
return
}

exists = !notExists

return
}

/*
ForceClose is like Close but will still close a Wallet even if currently in use by the WalletManager.
(Despite the insinuation by the name, this should be a relatively safe operation).
@ -83,8 +221,6 @@ func (w *Wallet) ForceClose() (err error) {
err = resultCheck(rslt)

return

return
}

// IsOpen returns whether a Wallet is open ("unlocked") or not (as well as updates Wallet.IsOpen).
@ -124,6 +260,8 @@ func (w *Wallet) ListFolders() (folderList []string, err error) {
*/
func (w *Wallet) Open() (err error) {

var handler *int32

if _, err = w.IsOpen(); err != nil {
return
}
@ -131,11 +269,18 @@ func (w *Wallet) Open() (err error) {
if !w.IsUnlocked {
if err = w.Dbus.Call(
DbusWMOpen, 0,
).Store(&w.handle); err != nil {
).Store(handler); err != nil {
return
}
}

if handler == nil {
err = ErrOperationFailed
return
} else {
w.handle = *handler
}

w.IsUnlocked = true

return

View File

@ -104,7 +104,7 @@ func (wm *WalletManager) CloseWallet(walletName string) (err error) {
Unlike Wallet.ForceClose, this closes access for ALL applications/WalletManagers
for the specified Wallet - not just this WalletManager.
*/
func (wm *WalletManager) FprceCloseWallet(walletName string) (err error) {
func (wm *WalletManager) ForceCloseWallet(walletName string) (err error) {

var rslt int32

@ -202,7 +202,7 @@ func (wm *WalletManager) NetworkWallet() (w *Wallet, err error) {
return
}

// WalletNames returns a list of available Wallet names.
// WalletNames returns a list of existing Wallet names.
func (wm *WalletManager) WalletNames() (wallets []string, err error) {

if err = wm.Dbus.Call(