Files
keepassgo/cmd/keepassgo-browser-bridge/main.go
T
2026-04-11 00:52:01 -07:00

122 lines
3.3 KiB
Go

package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"git.julianfamily.org/keepassgo/internal/browserbridge"
)
func main() {
if len(os.Args) > 1 {
switch strings.TrimSpace(os.Args[1]) {
case "install-native-host":
if err := runInstallNativeHost(os.Args[2:]); err != nil {
fail(err)
}
return
case "status":
if err := runStatus(os.Args[2:]); err != nil {
fail(err)
}
return
}
}
if err := runNativeMessage(); err != nil {
_ = browserbridge.WriteResponse(os.Stdout, browserbridge.Response{Success: false, Error: err.Error()})
os.Exit(1)
}
}
func runInstallNativeHost(args []string) error {
fs := flag.NewFlagSet("install-native-host", flag.ContinueOnError)
browserName := fs.String("browser", string(browserbridge.BrowserFirefox), "target browser: firefox, chrome, chromium")
binaryPath := fs.String("binary", "", "path to keepassgo-browser-bridge binary")
extensionID := fs.String("extension-id", "", "browser extension id (required for chrome/chromium)")
outputPath := fs.String("output", "", "native host manifest output path")
if err := fs.Parse(args); err != nil {
return err
}
path := strings.TrimSpace(*binaryPath)
if path == "" {
resolved, err := defaultBinaryPath()
if err != nil {
return err
}
path = resolved
}
installed, err := browserbridge.InstallManifest(browserbridge.Browser(strings.TrimSpace(*browserName)), path, strings.TrimSpace(*extensionID), strings.TrimSpace(*outputPath))
if err != nil {
return err
}
fmt.Fprintln(os.Stdout, installed)
return nil
}
func runStatus(args []string) error {
fs := flag.NewFlagSet("status", flag.ContinueOnError)
grpcAddr := fs.String("grpc-addr", browserbridge.DefaultGRPCAddress, "KeePassGO local gRPC address")
token := fs.String("token", "", "KeePassGO API bearer token")
if err := fs.Parse(args); err != nil {
return err
}
req := browserbridge.Request{
Action: "status",
GRPCAddress: strings.TrimSpace(*grpcAddr),
BearerToken: strings.TrimSpace(*token),
}
connCfg, err := req.Connection()
if err != nil {
return err
}
conn, client, ctx, err := browserbridge.Dial(context.Background(), connCfg)
if err != nil {
return err
}
defer func() { _ = conn.Close() }()
resp := browserbridge.HandleRequest(ctx, req, client)
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
return enc.Encode(resp)
}
func runNativeMessage() error {
req, err := browserbridge.ReadRequest(os.Stdin)
if err != nil {
return err
}
connCfg, err := req.Connection()
if err != nil {
return browserbridge.WriteResponse(os.Stdout, browserbridge.Response{Success: false, Error: err.Error()})
}
conn, client, ctx, err := browserbridge.Dial(context.Background(), connCfg)
if err != nil {
return browserbridge.WriteResponse(os.Stdout, browserbridge.Response{Success: false, Error: err.Error()})
}
defer func() { _ = conn.Close() }()
return browserbridge.WriteResponse(os.Stdout, browserbridge.HandleRequest(ctx, req, client))
}
func defaultBinaryPath() (string, error) {
self, err := os.Executable()
if err == nil && strings.TrimSpace(self) != "" {
return self, nil
}
self, err = exec.LookPath("keepassgo-browser-bridge")
if err == nil {
return self, nil
}
return filepath.Abs("./keepassgo-browser-bridge")
}
func fail(err error) {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}