Files
portmaster/service/profile/binmeta/icon.go
Daniel Hååvi 80664d1a27 Restructure modules (#1572)
* 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>
2024-08-09 18:15:48 +03:00

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
}