* Move portbase into monorepo * Add new simple module mgr * [WIP] Switch to new simple module mgr * Add StateMgr and more worker variants * [WIP] Switch more modules * [WIP] Switch more modules * [WIP] swtich more modules * [WIP] switch all SPN modules * [WIP] switch all service modules * [WIP] Convert all workers to the new module system * [WIP] add new task system to module manager * [WIP] Add second take for scheduling workers * [WIP] Add FIXME for bugs in new scheduler * [WIP] Add minor improvements to scheduler * [WIP] Add new worker scheduler * [WIP] Fix more bug related to new module system * [WIP] Fix start handing of the new module system * [WIP] Improve startup process * [WIP] Fix minor issues * [WIP] Fix missing subsystem in settings * [WIP] Initialize managers in constructor * [WIP] Move module event initialization to constrictors * [WIP] Fix setting for enabling and disabling the SPN module * [WIP] Move API registeration into module construction * [WIP] Update states mgr for all modules * [WIP] Add CmdLine operation support * Add state helper methods to module group and instance * Add notification and module status handling to status package * Fix starting issues * Remove pilot widget and update security lock to new status data * Remove debug logs * Improve http server shutdown * Add workaround for cleanly shutting down firewall+netquery * Improve logging * Add syncing states with notifications for new module system * Improve starting, stopping, shutdown; resolve FIXMEs/TODOs * [WIP] Fix most unit tests * Review new module system and fix minor issues * Push shutdown and restart events again via API * Set sleep mode via interface * Update example/template module * [WIP] Fix spn/cabin unit test * Remove deprecated UI elements * Make log output more similar for the logging transition phase * Switch spn hub and observer cmds to new module system * Fix log sources * Make worker mgr less error prone * Fix tests and minor issues * Fix observation hub * Improve shutdown and restart handling * Split up big connection.go source file * Move varint and dsd packages to structures repo * Improve expansion test * Fix linter warnings * Fix interception module on windows * Fix linter errors --------- Co-authored-by: Vladimir Stoilov <vladimir@safing.io>
166 lines
3.3 KiB
Go
166 lines
3.3 KiB
Go
package binmeta
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/vincent-petithory/dataurl"
|
|
"golang.org/x/exp/slices"
|
|
|
|
"github.com/safing/portmaster/base/database"
|
|
"github.com/safing/portmaster/base/database/record"
|
|
)
|
|
|
|
// Icon describes an icon.
|
|
type Icon struct {
|
|
Type IconType
|
|
Value string
|
|
Source IconSource
|
|
}
|
|
|
|
// IconType describes the type of an Icon.
|
|
type IconType string
|
|
|
|
// Supported icon types.
|
|
const (
|
|
IconTypeFile IconType = "path"
|
|
IconTypeDatabase IconType = "database"
|
|
IconTypeAPI IconType = "api"
|
|
)
|
|
|
|
func (t IconType) sortOrder() int {
|
|
switch t {
|
|
case IconTypeAPI:
|
|
return 1
|
|
case IconTypeDatabase:
|
|
return 2
|
|
case IconTypeFile:
|
|
return 3
|
|
default:
|
|
return 9
|
|
}
|
|
}
|
|
|
|
// IconSource describes the source of an Icon.
|
|
type IconSource string
|
|
|
|
// Supported icon sources.
|
|
const (
|
|
IconSourceUser IconSource = "user"
|
|
IconSourceImport IconSource = "import"
|
|
IconSourceUI IconSource = "ui"
|
|
IconSourceCore IconSource = "core"
|
|
)
|
|
|
|
func (s IconSource) sortOrder() int {
|
|
switch s {
|
|
case IconSourceUser:
|
|
return 10
|
|
case IconSourceImport:
|
|
return 20
|
|
case IconSourceUI:
|
|
return 30
|
|
case IconSourceCore:
|
|
return 40
|
|
default:
|
|
return 90
|
|
}
|
|
}
|
|
|
|
func (icon Icon) sortOrder() int {
|
|
return icon.Source.sortOrder() + icon.Type.sortOrder()
|
|
}
|
|
|
|
// SortAndCompactIcons sorts and compacts a list of icons.
|
|
func SortAndCompactIcons(icons []Icon) []Icon {
|
|
// Sort.
|
|
slices.SortFunc[[]Icon, Icon](icons, func(a, b Icon) int {
|
|
aOrder := a.sortOrder()
|
|
bOrder := b.sortOrder()
|
|
|
|
switch {
|
|
case aOrder != bOrder:
|
|
return aOrder - bOrder
|
|
case a.Value != b.Value:
|
|
return strings.Compare(a.Value, b.Value)
|
|
default:
|
|
return 0
|
|
}
|
|
})
|
|
|
|
// De-duplicate.
|
|
icons = slices.CompactFunc[[]Icon, Icon](icons, func(a, b Icon) bool {
|
|
return a.Type == b.Type && a.Value == b.Value
|
|
})
|
|
|
|
return icons
|
|
}
|
|
|
|
// GetIconAsDataURL returns the icon data as a data URL.
|
|
func (icon Icon) GetIconAsDataURL() (bloburl string, err error) {
|
|
switch icon.Type {
|
|
case IconTypeFile:
|
|
return "", errors.New("getting icon from file is not supported")
|
|
|
|
case IconTypeDatabase:
|
|
if !strings.HasPrefix(icon.Value, "cache:icons/") {
|
|
return "", errors.New("invalid icon db key")
|
|
}
|
|
r, err := iconDB.Get(icon.Value)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
dbIcon, err := EnsureIconInDatabase(r)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return dbIcon.IconData, nil
|
|
|
|
case IconTypeAPI:
|
|
data, err := GetProfileIcon(icon.Value)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return dataurl.EncodeBytes(data), nil
|
|
|
|
default:
|
|
return "", errors.New("unknown icon type")
|
|
}
|
|
}
|
|
|
|
var iconDB = database.NewInterface(&database.Options{
|
|
Local: true,
|
|
Internal: true,
|
|
})
|
|
|
|
// IconInDatabase represents an icon saved to the database.
|
|
type IconInDatabase struct {
|
|
sync.Mutex
|
|
record.Base
|
|
|
|
IconData string `json:"iconData,omitempty"` // DataURL
|
|
}
|
|
|
|
// EnsureIconInDatabase ensures that the given record is a *IconInDatabase, and returns it.
|
|
func EnsureIconInDatabase(r record.Record) (*IconInDatabase, error) {
|
|
// unwrap
|
|
if r.IsWrapped() {
|
|
// only allocate a new struct, if we need it
|
|
newIcon := &IconInDatabase{}
|
|
err := record.Unwrap(r, newIcon)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return newIcon, nil
|
|
}
|
|
|
|
// or adjust type
|
|
newIcon, ok := r.(*IconInDatabase)
|
|
if !ok {
|
|
return nil, fmt.Errorf("record not of type *IconInDatabase, but %T", r)
|
|
}
|
|
return newIcon, nil
|
|
}
|