// package win_root_set -- задаёт рутовый пароль на приложение package win_root_set import ( _ "embed" "fmt" "log" "net/url" "runtime" "sync" "time" "github.com/zserge/lorca" "wartank/pkg/types" ) //go:embed win_root_set.html var strWinHtml string // WinRootMake -- задаёт рутовый пароль на приложение type WinRootMake struct { desktop types.IDesktop store types.IStore win lorca.UI ws types.IWebSocket rootPass string // Пароль рута из формы block sync.Mutex } // NewWinRootMake -- возвращает новое окно пароля для рута func NewWinRootMake(desktop types.IDesktop) (*WinRootMake, error) { if desktop == nil { return nil, fmt.Errorf("NewWinRootMake(): IDesktop == nil") } sf := &WinRootMake{ desktop: desktop, store: desktop.Store(), ws: desktop.Ws(), } args := []string{} if runtime.GOOS == "linux" { args = append(args, "--class=Lorca") } var err error sf.win, err = lorca.New("data:text/html,"+url.PathEscape(strWinHtml), "", 640, 480, args...) if err != nil { return nil, fmt.Errorf("WinRoot(): in create win, err=\n\t%w", err) } go sf.close() return sf, nil } // GetPass -- возвращает полученный пароль из формы func (sf *WinRootMake) GetPass() string { fnCheck := func() bool { sf.block.Lock() defer sf.block.Unlock() return len(sf.rootPass) > 7 } for !fnCheck() { time.Sleep(time.Millisecond * 20) } sf.block.Lock() defer sf.block.Unlock() return sf.rootPass } // SetError -- устанавливает признак ошибки при операциях с паролем func (sf *WinRootMake) SetError(err error) { js := fmt.Sprintf(` function SetErrorSave(){ var _el=document.getElementById("/root/password/err"); _el.innerText="WinRootMake.onSetPass(): ошибка передачи при сохранении пароля, err=\n\t%v" } SetErrorSave()`, err) sf.win.Eval(js) } func (sf *WinRootMake) Close() { sf.win.Close() } // Работает в отдельном потоке, главный цикл окна func (sf *WinRootMake) Run() { log.Println("WinRootMake.Run()") sf.win.Bind("close_win", sf.onClose) sf.win.Bind("set_pass", sf.onSetPass) <-sf.win.Done() // Ожидание закрытия окна } // Сохраняет пароль рута func (sf *WinRootMake) onSetPass() { log.Printf("WinRootMake.onSetPass()\n") sf.block.Lock() defer sf.block.Unlock() sf.rootPass = sf.win.Eval(`document.getElementById("/root/password/val").value`).String() if len(sf.rootPass) < 8 { js := ` function SetError(){ var _el=document.getElementById("/root/password/err"); _el.innerText="WinRootMake.onSetPass(): пароль слишком короткий" } SetError() ` sf.win.Eval(js) return } js := ` function ResetError(){ var _el=document.getElementById("/root/password/err"); _el.innerText="" } ResetError() ` sf.win.Eval(js) log.Printf("WinRootMake.onSetPass(): pass=%q\n", sf.rootPass) } // Закрывает приложение func (sf *WinRootMake) onClose() { log.Println("WinRootMake.onClose()") sf.win.Close() } // close -- ожидает отмены глобального контекста func (sf *WinRootMake) close() { <-sf.desktop.CtxApp().Done() log.Println("WinRootMake.close()") sf.win.Close() }