From 71d36d23fb48218f10f0f200401b93c633e3a700 Mon Sep 17 00:00:00 2001 From: Tsachi Herman Date: Fri, 2 Oct 2020 15:35:33 -0400 Subject: [PATCH 1/5] Avoid printing control characters as part of the goal output. --- cmd/goal/application.go | 16 +++++++++++++--- cmd/goal/commands.go | 34 +++++++++++++++++++++------------- cmd/goal/interact.go | 6 +++--- cmd/goal/messages.go | 14 ++++++++------ 4 files changed, 45 insertions(+), 25 deletions(-) diff --git a/cmd/goal/application.go b/cmd/goal/application.go index 4121564adc..1ecf85ca45 100644 --- a/cmd/goal/application.go +++ b/cmd/goal/application.go @@ -920,13 +920,23 @@ var deleteAppCmd = &cobra.Command{ }, } -func unicodePrintable(str string) bool { +// unicodePrintable scan the input string str, and find if it contains any +// non-printable unicode characters. If so, it returns false, along with the +// printable characters that do appear in the input string. Otherwise, it +// returns true, along with a copy of the original string. The returned string +// printableString is gurenteed to be printable in all cases. +func unicodePrintable(str string) (isPrintable bool, printableString string) { + isPrintable = true + encRuneBuf := make([]byte, 8) for _, r := range str { if !unicode.IsPrint(r) { - return false + isPrintable = false + } else { + n := utf8.EncodeRune(encRuneBuf, r) + printableString += string(encRuneBuf[:n+1]) } } - return true + return } func jsonPrintable(str string) bool { diff --git a/cmd/goal/commands.go b/cmd/goal/commands.go index d458beef45..fa8f14f6d2 100644 --- a/cmd/goal/commands.go +++ b/cmd/goal/commands.go @@ -492,36 +492,44 @@ func ensurePassword() []byte { } func reportInfoln(args ...interface{}) { - fmt.Println(args...) - // log.Infoln(args...) + printable, outStr := unicodePrintable(fmt.Sprint(args...)) + if !printable { + fmt.Println(infoNonPrintableCharacters) + } + fmt.Println(outStr) } func reportInfof(format string, args ...interface{}) { - fmt.Printf(format+"\n", args...) - // log.Infof(format, args...) + reportInfoln(fmt.Sprintf(format, args...)) } func reportWarnln(args ...interface{}) { fmt.Print("Warning: ") - fmt.Println(args...) - // log.Warnln(args...) + + printable, outStr := unicodePrintable(fmt.Sprint(args...)) + if !printable { + fmt.Println(infoNonPrintableCharacters) + } + + fmt.Println(outStr) } func reportWarnf(format string, args ...interface{}) { - fmt.Printf("Warning: "+format+"\n", args...) - // log.Warnf(format, args...) + reportWarnln(fmt.Sprintf(format, args...)) } func reportErrorln(args ...interface{}) { - fmt.Fprintln(os.Stderr, args...) - // log.Warnln(args...) + outStr := fmt.Sprint(args...) + printable, outStr := unicodePrintable(outStr) + if !printable { + fmt.Fprintln(os.Stderr, errorNonPrintableCharacters) + } + fmt.Fprintln(os.Stderr, outStr) os.Exit(1) } func reportErrorf(format string, args ...interface{}) { - fmt.Fprintf(os.Stderr, format+"\n", args...) - // log.Warnf(format, args...) - os.Exit(1) + reportErrorln(fmt.Sprintf(format, args...)) } // writeFile is a wrapper of ioutil.WriteFile which considers the special diff --git a/cmd/goal/interact.go b/cmd/goal/interact.go index a619f163db..4f08f5c8a1 100644 --- a/cmd/goal/interact.go +++ b/cmd/goal/interact.go @@ -128,7 +128,7 @@ func appSpecStringInvalid(s string) error { } func appSpecHelpStringInvalid(s string) error { - if !unicodePrintable(s) { + if printable, _ := unicodePrintable(s); !printable { return fmt.Errorf("%s is not Unicode printable", strconv.Quote(s)) } return nil @@ -715,7 +715,7 @@ var appQueryCmd = &cobra.Command{ case "int", "integer": if tealval.Type == 0 { if meta.Explicit { - reportErrorf("%s not set for %s.%s", param, appIdx, storeName) + reportErrorf("%s not set for %d.%s", param, appIdx, storeName) } } else if tealval.Type != basics.TealUintType { reportErrorf("Expected kind %s but got teal type %s", meta.Kind, tealval.Type) @@ -724,7 +724,7 @@ var appQueryCmd = &cobra.Command{ default: if tealval.Type == 0 { if meta.Explicit { - reportErrorf("%s not set for %s.%s", param, appIdx, storeName) + reportErrorf("%s not set for %d.%s", param, appIdx, storeName) } } else if tealval.Type != basics.TealBytesType { reportErrorf("Expected kind %s but got teal type %s", meta.Kind, tealval.Type) diff --git a/cmd/goal/messages.go b/cmd/goal/messages.go index 868447aaf6..439b24014b 100644 --- a/cmd/goal/messages.go +++ b/cmd/goal/messages.go @@ -18,12 +18,14 @@ package main const ( // General - errorNoDataDirectory = "Data directory not specified. Please use -d or set $ALGORAND_DATA in your environment. Exiting." - errorOneDataDirSupported = "Only one data directory can be specified for this command." - errorRequestFail = "Error processing command: %s" - errorGenesisIDFail = "Error determining kmd folder (%s). Ensure the node is running in %s." - errorDirectoryNotExist = "Specified directory '%s' does not exist." - errorParseAddr = "Failed to parse addr: %v" + errorNoDataDirectory = "Data directory not specified. Please use -d or set $ALGORAND_DATA in your environment. Exiting." + errorOneDataDirSupported = "Only one data directory can be specified for this command." + errorRequestFail = "Error processing command: %s" + errorGenesisIDFail = "Error determining kmd folder (%s). Ensure the node is running in %s." + errorDirectoryNotExist = "Specified directory '%s' does not exist." + errorParseAddr = "Failed to parse addr: %v" + errorNonPrintableCharacters = "One or more non-printable characters were ommited from the following error message:" + infoNonPrintableCharacters = "One or more non-printable characters were ommited from the subsequent line:" // Account infoNoAccounts = "Did not find any account. Please import or create a new one." From bc00052adb5f4fb97f6505f15a7e87219d8ab2f2 Mon Sep 17 00:00:00 2001 From: Tsachi Herman Date: Sat, 3 Oct 2020 21:38:31 -0400 Subject: [PATCH 2/5] update unicodePrintable --- cmd/goal/application.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/goal/application.go b/cmd/goal/application.go index 1ecf85ca45..caa8e4a49f 100644 --- a/cmd/goal/application.go +++ b/cmd/goal/application.go @@ -933,7 +933,7 @@ func unicodePrintable(str string) (isPrintable bool, printableString string) { isPrintable = false } else { n := utf8.EncodeRune(encRuneBuf, r) - printableString += string(encRuneBuf[:n+1]) + printableString += string(encRuneBuf[:n]) } } return From bdba49f616cd3c8abc6f3cfef263264017c35b28 Mon Sep 17 00:00:00 2001 From: Tsachi Herman Date: Sat, 3 Oct 2020 23:22:28 -0400 Subject: [PATCH 3/5] Handle line return --- cmd/goal/commands.go | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/cmd/goal/commands.go b/cmd/goal/commands.go index fa8f14f6d2..72719bdfae 100644 --- a/cmd/goal/commands.go +++ b/cmd/goal/commands.go @@ -492,11 +492,13 @@ func ensurePassword() []byte { } func reportInfoln(args ...interface{}) { - printable, outStr := unicodePrintable(fmt.Sprint(args...)) - if !printable { - fmt.Println(infoNonPrintableCharacters) + for _, line := range strings.Split(fmt.Sprint(args...), "\n") { + printable, line := unicodePrintable(line) + if !printable { + fmt.Println(infoNonPrintableCharacters) + } + fmt.Println(line) } - fmt.Println(outStr) } func reportInfof(format string, args ...interface{}) { @@ -506,12 +508,14 @@ func reportInfof(format string, args ...interface{}) { func reportWarnln(args ...interface{}) { fmt.Print("Warning: ") - printable, outStr := unicodePrintable(fmt.Sprint(args...)) - if !printable { - fmt.Println(infoNonPrintableCharacters) - } + for _, line := range strings.Split(fmt.Sprint(args...), "\n") { + printable, line := unicodePrintable(line) + if !printable { + fmt.Println(infoNonPrintableCharacters) + } - fmt.Println(outStr) + fmt.Println(line) + } } func reportWarnf(format string, args ...interface{}) { @@ -520,11 +524,13 @@ func reportWarnf(format string, args ...interface{}) { func reportErrorln(args ...interface{}) { outStr := fmt.Sprint(args...) - printable, outStr := unicodePrintable(outStr) - if !printable { - fmt.Fprintln(os.Stderr, errorNonPrintableCharacters) + for _, line := range strings.Split(outStr, "\n") { + printable, line := unicodePrintable(line) + if !printable { + fmt.Fprintln(os.Stderr, errorNonPrintableCharacters) + } + fmt.Fprintln(os.Stderr, line) } - fmt.Fprintln(os.Stderr, outStr) os.Exit(1) } From 501187f0a91eedae02a0d228950318e81cbf132d Mon Sep 17 00:00:00 2001 From: Tsachi Herman Date: Mon, 5 Oct 2020 11:22:42 -0400 Subject: [PATCH 4/5] Move unicodePrintable and jsonPrintable to it's own file, and add unit test --- cmd/goal/application.go | 176 -------------------------------- cmd/goal/formatting.go | 198 ++++++++++++++++++++++++++++++++++++ cmd/goal/formatting_test.go | 42 ++++++++ 3 files changed, 240 insertions(+), 176 deletions(-) create mode 100644 cmd/goal/formatting.go create mode 100644 cmd/goal/formatting_test.go diff --git a/cmd/goal/application.go b/cmd/goal/application.go index caa8e4a49f..0e5c6e4e81 100644 --- a/cmd/goal/application.go +++ b/cmd/goal/application.go @@ -24,8 +24,6 @@ import ( "os" "strconv" "strings" - "unicode" - "unicode/utf8" "github.com/spf13/cobra" @@ -920,180 +918,6 @@ var deleteAppCmd = &cobra.Command{ }, } -// unicodePrintable scan the input string str, and find if it contains any -// non-printable unicode characters. If so, it returns false, along with the -// printable characters that do appear in the input string. Otherwise, it -// returns true, along with a copy of the original string. The returned string -// printableString is gurenteed to be printable in all cases. -func unicodePrintable(str string) (isPrintable bool, printableString string) { - isPrintable = true - encRuneBuf := make([]byte, 8) - for _, r := range str { - if !unicode.IsPrint(r) { - isPrintable = false - } else { - n := utf8.EncodeRune(encRuneBuf, r) - printableString += string(encRuneBuf[:n]) - } - } - return -} - -func jsonPrintable(str string) bool { - // htmlSafeSet holds the value true if the ASCII character with the given - // array position can be safely represented inside a JSON string, embedded - // inside of HTML