From 96334dd05480d10fe9d43b8f5d192a6e9a08b315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Markowski?= Date: Wed, 10 Aug 2022 20:07:51 +0200 Subject: [PATCH] clipboard module update and updated readme readme explains that the clip module requires extra system packages like xclip --- README.md | 9 +- go.mod | 2 +- go.sum | 4 +- .../github.com/atotto/clipboard/.travis.yml | 22 +++++ vendor/github.com/atotto/clipboard/README.md | 48 ++++++++++ .../atotto/clipboard/clipboard_plan9.go | 42 +++++++++ .../atotto/clipboard/clipboard_unix.go | 59 +++++++++++- .../atotto/clipboard/clipboard_windows.go | 92 +++++++++++++++---- vendor/github.com/atotto/clipboard/go.mod | 1 + vendor/modules.txt | 3 + 10 files changed, 255 insertions(+), 27 deletions(-) create mode 100644 vendor/github.com/atotto/clipboard/.travis.yml create mode 100644 vendor/github.com/atotto/clipboard/README.md create mode 100644 vendor/github.com/atotto/clipboard/clipboard_plan9.go create mode 100644 vendor/github.com/atotto/clipboard/go.mod create mode 100644 vendor/modules.txt diff --git a/README.md b/README.md index 7d7c063..21636a7 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,12 @@ By default the new key generates 6-digit codes; the `-7` and `-8` flags select `2fa name` prints a two-factor authentication code from the key with the given name. If `-clip` is specified, `2fa` also copies to the code to the system -clipboard. +clipboard. If you have a problems with `-clip` flag - check if you have installed any +any clipboard management utility like `xclip`. + +For instance in Ubuntu: + + sudo apt install xclip With no arguments, `2fa` prints two-factor authentication codes from all known time-based keys. @@ -55,5 +60,5 @@ Then whenever GitHub prompts for a 2FA code, run 2fa to obtain one: Or to type less: $ 2fa - 268346 github + 268346 github $ diff --git a/go.mod b/go.mod index 330c197..5596af8 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module rsc.io/2fa go 1.16 -require github.com/atotto/clipboard v0.1.2 +require github.com/atotto/clipboard v0.1.4 diff --git a/go.sum b/go.sum index 243ea9b..244b67e 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,2 @@ -github.com/atotto/clipboard v0.1.2 h1:YZCtFu5Ie8qX2VmVTBnrqLSiU9XOWwqNRmdT3gIQzbY= -github.com/atotto/clipboard v0.1.2/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= diff --git a/vendor/github.com/atotto/clipboard/.travis.yml b/vendor/github.com/atotto/clipboard/.travis.yml new file mode 100644 index 0000000..23f21d8 --- /dev/null +++ b/vendor/github.com/atotto/clipboard/.travis.yml @@ -0,0 +1,22 @@ +language: go + +os: + - linux + - osx + - windows + +go: + - go1.13.x + - go1.x + +services: + - xvfb + +before_install: + - export DISPLAY=:99.0 + +script: + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install xsel; fi + - go test -v . + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install xclip; fi + - go test -v . diff --git a/vendor/github.com/atotto/clipboard/README.md b/vendor/github.com/atotto/clipboard/README.md new file mode 100644 index 0000000..41fdd57 --- /dev/null +++ b/vendor/github.com/atotto/clipboard/README.md @@ -0,0 +1,48 @@ +[![Build Status](https://travis-ci.org/atotto/clipboard.svg?branch=master)](https://travis-ci.org/atotto/clipboard) + +[![GoDoc](https://godoc.org/github.com/atotto/clipboard?status.svg)](http://godoc.org/github.com/atotto/clipboard) + +# Clipboard for Go + +Provide copying and pasting to the Clipboard for Go. + +Build: + + $ go get github.com/atotto/clipboard + +Platforms: + +* OSX +* Windows 7 (probably work on other Windows) +* Linux, Unix (requires 'xclip' or 'xsel' command to be installed) + + +Document: + +* http://godoc.org/github.com/atotto/clipboard + +Notes: + +* Text string only +* UTF-8 text encoding only (no conversion) + +TODO: + +* Clipboard watcher(?) + +## Commands: + +paste shell command: + + $ go get github.com/atotto/clipboard/cmd/gopaste + $ # example: + $ gopaste > document.txt + +copy shell command: + + $ go get github.com/atotto/clipboard/cmd/gocopy + $ # example: + $ cat document.txt | gocopy + + + diff --git a/vendor/github.com/atotto/clipboard/clipboard_plan9.go b/vendor/github.com/atotto/clipboard/clipboard_plan9.go new file mode 100644 index 0000000..9d2fef4 --- /dev/null +++ b/vendor/github.com/atotto/clipboard/clipboard_plan9.go @@ -0,0 +1,42 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build plan9 + +package clipboard + +import ( + "os" + "io/ioutil" +) + +func readAll() (string, error) { + f, err := os.Open("/dev/snarf") + if err != nil { + return "", err + } + defer f.Close() + + str, err := ioutil.ReadAll(f) + if err != nil { + return "", err + } + + return string(str), nil +} + +func writeAll(text string) error { + f, err := os.OpenFile("/dev/snarf", os.O_WRONLY, 0666) + if err != nil { + return err + } + defer f.Close() + + _, err = f.Write([]byte(text)) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/atotto/clipboard/clipboard_unix.go b/vendor/github.com/atotto/clipboard/clipboard_unix.go index 0acd5fa..d9f6a56 100644 --- a/vendor/github.com/atotto/clipboard/clipboard_unix.go +++ b/vendor/github.com/atotto/clipboard/clipboard_unix.go @@ -8,16 +8,24 @@ package clipboard import ( "errors" + "os" "os/exec" ) const ( - xsel = "xsel" - xclip = "xclip" + xsel = "xsel" + xclip = "xclip" + powershellExe = "powershell.exe" + clipExe = "clip.exe" + wlcopy = "wl-copy" + wlpaste = "wl-paste" + termuxClipboardGet = "termux-clipboard-get" + termuxClipboardSet = "termux-clipboard-set" ) var ( Primary bool + trimDos bool pasteCmdArgs []string copyCmdArgs []string @@ -28,10 +36,30 @@ var ( xclipPasteArgs = []string{xclip, "-out", "-selection", "clipboard"} xclipCopyArgs = []string{xclip, "-in", "-selection", "clipboard"} - missingCommands = errors.New("No clipboard utilities available. Please install xsel or xclip.") + powershellExePasteArgs = []string{powershellExe, "Get-Clipboard"} + clipExeCopyArgs = []string{clipExe} + + wlpasteArgs = []string{wlpaste, "--no-newline"} + wlcopyArgs = []string{wlcopy} + + termuxPasteArgs = []string{termuxClipboardGet} + termuxCopyArgs = []string{termuxClipboardSet} + + missingCommands = errors.New("No clipboard utilities available. Please install xsel, xclip, wl-clipboard or Termux:API add-on for termux-clipboard-get/set.") ) func init() { + if os.Getenv("WAYLAND_DISPLAY") != "" { + pasteCmdArgs = wlpasteArgs + copyCmdArgs = wlcopyArgs + + if _, err := exec.LookPath(wlcopy); err == nil { + if _, err := exec.LookPath(wlpaste); err == nil { + return + } + } + } + pasteCmdArgs = xclipPasteArgs copyCmdArgs = xclipCopyArgs @@ -46,6 +74,25 @@ func init() { return } + pasteCmdArgs = termuxPasteArgs + copyCmdArgs = termuxCopyArgs + + if _, err := exec.LookPath(termuxClipboardSet); err == nil { + if _, err := exec.LookPath(termuxClipboardGet); err == nil { + return + } + } + + pasteCmdArgs = powershellExePasteArgs + copyCmdArgs = clipExeCopyArgs + trimDos = true + + if _, err := exec.LookPath(clipExe); err == nil { + if _, err := exec.LookPath(powershellExe); err == nil { + return + } + } + Unsupported = true } @@ -72,7 +119,11 @@ func readAll() (string, error) { if err != nil { return "", err } - return string(out), nil + result := string(out) + if trimDos && len(result) > 1 { + result = result[:len(result)-2] + } + return result, nil } func writeAll(text string) error { diff --git a/vendor/github.com/atotto/clipboard/clipboard_windows.go b/vendor/github.com/atotto/clipboard/clipboard_windows.go index 5dbb562..253bb93 100644 --- a/vendor/github.com/atotto/clipboard/clipboard_windows.go +++ b/vendor/github.com/atotto/clipboard/clipboard_windows.go @@ -7,22 +7,25 @@ package clipboard import ( + "runtime" "syscall" + "time" "unsafe" ) const ( cfUnicodetext = 13 - gmemFixed = 0x0000 + gmemMoveable = 0x0002 ) var ( - user32 = syscall.MustLoadDLL("user32") - openClipboard = user32.MustFindProc("OpenClipboard") - closeClipboard = user32.MustFindProc("CloseClipboard") - emptyClipboard = user32.MustFindProc("EmptyClipboard") - getClipboardData = user32.MustFindProc("GetClipboardData") - setClipboardData = user32.MustFindProc("SetClipboardData") + user32 = syscall.MustLoadDLL("user32") + isClipboardFormatAvailable = user32.MustFindProc("IsClipboardFormatAvailable") + openClipboard = user32.MustFindProc("OpenClipboard") + closeClipboard = user32.MustFindProc("CloseClipboard") + emptyClipboard = user32.MustFindProc("EmptyClipboard") + getClipboardData = user32.MustFindProc("GetClipboardData") + setClipboardData = user32.MustFindProc("SetClipboardData") kernel32 = syscall.NewLazyDLL("kernel32") globalAlloc = kernel32.NewProc("GlobalAlloc") @@ -32,69 +35,122 @@ var ( lstrcpy = kernel32.NewProc("lstrcpyW") ) +// waitOpenClipboard opens the clipboard, waiting for up to a second to do so. +func waitOpenClipboard() error { + started := time.Now() + limit := started.Add(time.Second) + var r uintptr + var err error + for time.Now().Before(limit) { + r, _, err = openClipboard.Call(0) + if r != 0 { + return nil + } + time.Sleep(time.Millisecond) + } + return err +} + func readAll() (string, error) { - r, _, err := openClipboard.Call(0) - if r == 0 { + // LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution). + // Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + if formatAvailable, _, err := isClipboardFormatAvailable.Call(cfUnicodetext); formatAvailable == 0 { + return "", err + } + err := waitOpenClipboard() + if err != nil { return "", err } - defer closeClipboard.Call() h, _, err := getClipboardData.Call(cfUnicodetext) - if r == 0 { + if h == 0 { + _, _, _ = closeClipboard.Call() return "", err } l, _, err := globalLock.Call(h) if l == 0 { + _, _, _ = closeClipboard.Call() return "", err } text := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(l))[:]) - r, _, err = globalUnlock.Call(h) + r, _, err := globalUnlock.Call(h) if r == 0 { + _, _, _ = closeClipboard.Call() return "", err } + closed, _, err := closeClipboard.Call() + if closed == 0 { + return "", err + } return text, nil } func writeAll(text string) error { - r, _, err := openClipboard.Call(0) - if r == 0 { + // LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution). + // Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := waitOpenClipboard() + if err != nil { return err } - defer closeClipboard.Call() - r, _, err = emptyClipboard.Call(0) + r, _, err := emptyClipboard.Call(0) if r == 0 { + _, _, _ = closeClipboard.Call() return err } data := syscall.StringToUTF16(text) - h, _, err := globalAlloc.Call(gmemFixed, uintptr(len(data)*int(unsafe.Sizeof(data[0])))) + // "If the hMem parameter identifies a memory object, the object must have + // been allocated using the function with the GMEM_MOVEABLE flag." + h, _, err := globalAlloc.Call(gmemMoveable, uintptr(len(data)*int(unsafe.Sizeof(data[0])))) if h == 0 { + _, _, _ = closeClipboard.Call() return err } + defer func() { + if h != 0 { + globalFree.Call(h) + } + }() l, _, err := globalLock.Call(h) if l == 0 { + _, _, _ = closeClipboard.Call() return err } r, _, err = lstrcpy.Call(l, uintptr(unsafe.Pointer(&data[0]))) if r == 0 { + _, _, _ = closeClipboard.Call() return err } r, _, err = globalUnlock.Call(h) if r == 0 { - return err + if err.(syscall.Errno) != 0 { + _, _, _ = closeClipboard.Call() + return err + } } r, _, err = setClipboardData.Call(cfUnicodetext, h) if r == 0 { + _, _, _ = closeClipboard.Call() + return err + } + h = 0 // suppress deferred cleanup + closed, _, err := closeClipboard.Call() + if closed == 0 { return err } return nil diff --git a/vendor/github.com/atotto/clipboard/go.mod b/vendor/github.com/atotto/clipboard/go.mod new file mode 100644 index 0000000..68ec980 --- /dev/null +++ b/vendor/github.com/atotto/clipboard/go.mod @@ -0,0 +1 @@ +module github.com/atotto/clipboard diff --git a/vendor/modules.txt b/vendor/modules.txt new file mode 100644 index 0000000..3d31469 --- /dev/null +++ b/vendor/modules.txt @@ -0,0 +1,3 @@ +# github.com/atotto/clipboard v0.1.4 +## explicit +github.com/atotto/clipboard