From 0abd40cb117dce747c498c5c603f5a52bf1b3046 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Wed, 11 May 2022 17:49:15 +0100 Subject: [PATCH] Username (macOS). --- cmd/zenity/main.go | 12 +++++++ date.go | 4 +-- file_darwin.go | 4 +-- internal/zenutil/osa_generated.go | 31 ++++++++++++++++-- internal/zenutil/osascripts/date.gojs | 2 +- internal/zenutil/osascripts/dialog.gojs | 2 +- internal/zenutil/osascripts/pwd.gojs | 43 +++++++++++++++++++++++++ internal/zenutil/run_darwin.go | 29 +++++++++++++++++ list_unix.go | 4 +-- msg_unix.go | 4 +-- notify_unix.go | 4 +-- progress_unix.go | 4 +-- pwd_darwin.go | 33 +++++++++++++++++++ pwd_test.go | 2 +- pwd_unix.go | 18 ++--------- pwd_stub.go => pwd_windows.go | 2 -- scripts/password.sh | 14 ++++++++ util_unix.go | 14 ++++++++ 18 files changed, 185 insertions(+), 41 deletions(-) create mode 100644 internal/zenutil/osascripts/pwd.gojs create mode 100644 pwd_darwin.go rename pwd_stub.go => pwd_windows.go (89%) create mode 100755 scripts/password.sh diff --git a/cmd/zenity/main.go b/cmd/zenity/main.go index a0944a7..0cc5407 100644 --- a/cmd/zenity/main.go +++ b/cmd/zenity/main.go @@ -61,6 +61,9 @@ var ( entryText string hideText bool + // Password options + username bool + // List options columns int allowEmpty bool @@ -219,6 +222,9 @@ func setupFlags() { flag.StringVar(&entryText, "entry-text", "", "Set the entry `text`") flag.BoolVar(&hideText, "hide-text", false, "Hide the entry text") + // Password options + flag.BoolVar(&username, "username", false, "Display the username option") + // List options flag.Func("column", "Set the column `header`", addColumn) flag.Bool("hide-header", true, "Hide the column headers") @@ -435,6 +441,12 @@ func loadFlags() []zenity.Option { opts = append(opts, zenity.HideText()) } + // Password options + + if username { + opts = append(opts, zenity.Username()) + } + // List options if !allowEmpty { diff --git a/date.go b/date.go index 1ecafd9..07b354f 100644 --- a/date.go +++ b/date.go @@ -1,8 +1,6 @@ package zenity -import ( - "time" -) +import "time" // Calendar displays the calendar dialog. // diff --git a/file_darwin.go b/file_darwin.go index 668424d..92cc4cb 100644 --- a/file_darwin.go +++ b/file_darwin.go @@ -1,8 +1,6 @@ package zenity -import ( - "github.com/ncruces/zenity/internal/zenutil" -) +import "github.com/ncruces/zenity/internal/zenutil" func selectFile(opts options) (string, error) { var data zenutil.File diff --git a/internal/zenutil/osa_generated.go b/internal/zenutil/osa_generated.go index bde7b69..c3c39c6 100644 --- a/internal/zenutil/osa_generated.go +++ b/internal/zenutil/osa_generated.go @@ -52,7 +52,7 @@ var res=alert.runModal switch(res){case $.NSAlertThirdButtonReturn:$.puts({{json .Extra}}) case $.NSAlertSecondButtonReturn:$.exit(1)} var fmt=$.NSDateFormatter.alloc.init -fmt.locale=$.NSLocale.localeWithLocaleIdentifier("en_US_POSIX") +fmt.locale=$.NSLocale.localeWithLocaleIdentifier('en_US_POSIX') fmt.dateFormat={{json .Format}} fmt.stringFromDate(date.dateValue) {{- end}} @@ -70,7 +70,7 @@ try{var res=app.{{.Operation}}({{json .Text}},opts)}catch(e){if(e.errorNumber=== $.dprintf(2,e) $.exit(-1)} if(res.gaveUp){$.exit(5)} -if(res.buttonReturned==={{json .Extra}}){$.puts(res.buttonReturned) +if(res.buttonReturned==={{json .Extra}}){$.puts({{json .Extra}}) $.exit(1)} res.textReturned {{- end}} @@ -118,4 +118,31 @@ if(s.indexOf('#')===0){Progress.additionalDescription=s.slice(1) continue} var i=parseInt(s) if(i>=0&&Progress.totalUnitCount>0){Progress.completedUnitCount=i}} +{{- end}} +{{define "pwd" -}} +var app=Application.currentApplication() +app.includeStandardAdditions=true +app.activate() +ObjC.import('stdio') +ObjC.import('stdlib') +var opts={{json .Options}} +{{- if .IconPath}} +opts.withIcon=Path({{json .IconPath}}) +{{- end}} +function dialog(text){try{var res=app.displayDialog(text,opts)}catch(e){if(e.errorNumber===-128)$.exit(1) +$.dprintf(2,e) +$.exit(-1)} +if(res.gaveUp){$.exit(5)} +if(res.buttonReturned==={{json .Extra}}){$.puts({{json .Extra}}) +$.exit(1)} +return res.textReturned} +var start=Date.now() +opts.defaultAnswer='' +var username=dialog('Username:') +{{- if .Options.Timeout}} +opts.givingUpAfter-=(Date.now()-start)/1000|0 +{{- end}} +opts.hiddenAnswer=true +var password=dialog('Password:') +username+{{json .Separator}}+password {{- end}}`)) diff --git a/internal/zenutil/osascripts/date.gojs b/internal/zenutil/osascripts/date.gojs index 66cbe70..a70078f 100644 --- a/internal/zenutil/osascripts/date.gojs +++ b/internal/zenutil/osascripts/date.gojs @@ -35,6 +35,6 @@ case $.NSAlertSecondButtonReturn: } var fmt = $.NSDateFormatter.alloc.init -fmt.locale = $.NSLocale.localeWithLocaleIdentifier("en_US_POSIX") +fmt.locale = $.NSLocale.localeWithLocaleIdentifier('en_US_POSIX') fmt.dateFormat = {{json .Format}} fmt.stringFromDate(date.dateValue) \ No newline at end of file diff --git a/internal/zenutil/osascripts/dialog.gojs b/internal/zenutil/osascripts/dialog.gojs index 4e94869..8ad51df 100644 --- a/internal/zenutil/osascripts/dialog.gojs +++ b/internal/zenutil/osascripts/dialog.gojs @@ -22,7 +22,7 @@ if (res.gaveUp) { $.exit(5) } if (res.buttonReturned === {{json .Extra}}) { - $.puts(res.buttonReturned) + $.puts({{json .Extra}}) $.exit(1) } res.textReturned \ No newline at end of file diff --git a/internal/zenutil/osascripts/pwd.gojs b/internal/zenutil/osascripts/pwd.gojs new file mode 100644 index 0000000..7a8fef9 --- /dev/null +++ b/internal/zenutil/osascripts/pwd.gojs @@ -0,0 +1,43 @@ +var app = Application.currentApplication() +app.includeStandardAdditions = true +app.activate() + +ObjC.import('stdio') +ObjC.import('stdlib') + +var opts = {{json .Options}} +{{- if .IconPath}} + opts.withIcon = Path({{json .IconPath}}) +{{- end}} + +function dialog(text) { + try { + var res = app.displayDialog(text, opts) + } catch (e) { + if (e.errorNumber === -128) $.exit(1) + $.dprintf(2, e) + $.exit(-1) + } + + if (res.gaveUp) { + $.exit(5) + } + if (res.buttonReturned === {{json .Extra}}) { + $.puts({{json .Extra}}) + $.exit(1) + } + return res.textReturned +} + +var start = Date.now() +opts.defaultAnswer = '' +var username = dialog('Username:') + +{{- if .Options.Timeout}} + opts.givingUpAfter -= (Date.now() - start) / 1000 |0 +{{- end}} + +opts.hiddenAnswer = true +var password = dialog('Password:') + +username + {{json .Separator}} + password \ No newline at end of file diff --git a/internal/zenutil/run_darwin.go b/internal/zenutil/run_darwin.go index d3d71b3..a4fead0 100644 --- a/internal/zenutil/run_darwin.go +++ b/internal/zenutil/run_darwin.go @@ -147,6 +147,24 @@ type DialogOptions struct { Timeout int `json:"givingUpAfter,omitempty"` } +// Password is internal. +type Password struct { + Separator string + Extra *string + Options PasswordOptions + IconPath string +} + +// PasswordOptions is internal. +type PasswordOptions struct { + Title *string `json:"withTitle,omitempty"` + Icon string `json:"withIcon,omitempty"` + Buttons []string `json:"buttons,omitempty"` + Cancel int `json:"cancelButton,omitempty"` + Default int `json:"defaultButton,omitempty"` + Timeout int `json:"givingUpAfter,omitempty"` +} + // DialogButtons is internal. type DialogButtons struct { Buttons []string @@ -166,6 +184,17 @@ func (d *Dialog) SetButtons(btns DialogButtons) { } } +// SetButtons is internal. +func (d *Password) SetButtons(btns DialogButtons) { + d.Options.Buttons = btns.Buttons + d.Options.Default = btns.Default + d.Options.Cancel = btns.Cancel + if btns.Extra > 0 { + name := btns.Buttons[btns.Extra-1] + d.Extra = &name + } +} + // List is internal. type List struct { Items []string diff --git a/list_unix.go b/list_unix.go index b2fb8b5..83b1661 100644 --- a/list_unix.go +++ b/list_unix.go @@ -2,9 +2,7 @@ package zenity -import ( - "github.com/ncruces/zenity/internal/zenutil" -) +import "github.com/ncruces/zenity/internal/zenutil" func list(text string, items []string, opts options) (string, error) { args := []string{"--list", "--column=", "--hide-header", "--text", text} diff --git a/msg_unix.go b/msg_unix.go index f200b7c..a0783a9 100644 --- a/msg_unix.go +++ b/msg_unix.go @@ -2,9 +2,7 @@ package zenity -import ( - "github.com/ncruces/zenity/internal/zenutil" -) +import "github.com/ncruces/zenity/internal/zenutil" func message(kind messageKind, text string, opts options) error { args := []string{"--text", text, "--no-markup"} diff --git a/notify_unix.go b/notify_unix.go index c36797a..fd1c4cc 100644 --- a/notify_unix.go +++ b/notify_unix.go @@ -2,9 +2,7 @@ package zenity -import ( - "github.com/ncruces/zenity/internal/zenutil" -) +import "github.com/ncruces/zenity/internal/zenutil" func notify(text string, opts options) error { args := []string{"--notification", "--text", text} diff --git a/progress_unix.go b/progress_unix.go index bd026e2..c9309f0 100644 --- a/progress_unix.go +++ b/progress_unix.go @@ -2,9 +2,7 @@ package zenity -import ( - "github.com/ncruces/zenity/internal/zenutil" -) +import "github.com/ncruces/zenity/internal/zenutil" func progress(opts options) (ProgressDialog, error) { args := []string{"--progress"} diff --git a/pwd_darwin.go b/pwd_darwin.go new file mode 100644 index 0000000..ac13431 --- /dev/null +++ b/pwd_darwin.go @@ -0,0 +1,33 @@ +package zenity + +import ( + "os" + + "github.com/ncruces/zenity/internal/zenutil" +) + +func password(opts options) (string, string, error) { + if !opts.username { + opts.hideText = true + str, err := entry("Password:", opts) + return "", str, err + } + + var data zenutil.Password + data.Separator = zenutil.Separator + data.Options.Title = opts.title + data.Options.Timeout = zenutil.Timeout + if opts.customIcon != "" { + _, err := os.Stat(opts.customIcon) + if err != nil { + return "", "", err + } + data.IconPath = opts.customIcon + } else { + data.Options.Icon = opts.icon.String() + } + data.SetButtons(getButtons(true, true, opts)) + + out, err := zenutil.Run(opts.ctx, "pwd", data) + return pwdResult(zenutil.Separator, opts, out, err) +} diff --git a/pwd_test.go b/pwd_test.go index bbca524..abfdeec 100644 --- a/pwd_test.go +++ b/pwd_test.go @@ -60,7 +60,7 @@ func TestPassword_username(t *testing.T) { if skip, err := skip(err); skip { t.Skip("skipping:", err) } - if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { + if runtime.GOOS == "windows" { if errors.Is(err, zenity.ErrUnsupported) { t.Skip("was not unsupported:", err) } else { diff --git a/pwd_unix.go b/pwd_unix.go index 39f1bdd..c720459 100644 --- a/pwd_unix.go +++ b/pwd_unix.go @@ -2,12 +2,7 @@ package zenity -import ( - "os/exec" - "strings" - - "github.com/ncruces/zenity/internal/zenutil" -) +import "github.com/ncruces/zenity/internal/zenutil" func password(opts options) (string, string, error) { args := []string{"--password"} @@ -18,14 +13,5 @@ func password(opts options) (string, string, error) { } out, err := zenutil.Run(opts.ctx, args) - str, err := strResult(opts, out, err) - if opts.username { - if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 255 { - return "", "", ErrUnsupported - } - if split := strings.SplitN(str, "|", 2); err == nil && len(split) == 2 { - return split[0], split[1], nil - } - } - return "", str, err + return pwdResult("|", opts, out, err) } diff --git a/pwd_stub.go b/pwd_windows.go similarity index 89% rename from pwd_stub.go rename to pwd_windows.go index 16f5a0f..9fb1faf 100644 --- a/pwd_stub.go +++ b/pwd_windows.go @@ -1,5 +1,3 @@ -//go:build windows || darwin - package zenity import "fmt" diff --git a/scripts/password.sh b/scripts/password.sh new file mode 100755 index 0000000..01841d1 --- /dev/null +++ b/scripts/password.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +ENTRY=`zenity --password --username` + +case $? in + 0) + echo "User Name: `echo $ENTRY | cut -d'|' -f1`" + echo "Password : `echo $ENTRY | cut -d'|' -f2`" + ;; + 1) + echo "Stop login.";; + -1) + echo "An unexpected error has occurred.";; +esac \ No newline at end of file diff --git a/util_unix.go b/util_unix.go index 5d5a3ce..bf39dd7 100644 --- a/util_unix.go +++ b/util_unix.go @@ -82,3 +82,17 @@ func lstResult(opts options, out []byte, err error) ([]string, error) { } return strings.Split(str, zenutil.Separator), nil } + +func pwdResult(sep string, opts options, out []byte, err error) (string, string, error) { + str, err := strResult(opts, out, err) + if opts.username { + if err, ok := err.(*exec.ExitError); ok && err.ExitCode() == 255 { + return "", "", ErrUnsupported + } + + if split := strings.SplitN(str, sep, 2); err == nil && len(split) == 2 { + return split[0], split[1], nil + } + } + return "", str, err +}