[tor-commits] [goptlib/master] encodeSmethodArgs.
dcf at torproject.org
dcf at torproject.org
Mon Dec 9 02:49:51 UTC 2013
commit 9a9f9cb455d17bf82d02292953b945dcbb4a5029
Author: David Fifield <david at bamsoftware.com>
Date: Sun Dec 8 02:53:38 2013 -0800
encodeSmethodArgs.
---
args.go | 44 ++++++++++++++++++++++++++++++++++++++++++++
args_test.go | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/args.go b/args.go
index a0a3bd5..9eacee5 100644
--- a/args.go
+++ b/args.go
@@ -4,6 +4,8 @@ import (
"bytes"
"errors"
"fmt"
+ "sort"
+ "strings"
)
// Keyâvalue mappings for the representation of client and server options.
@@ -173,3 +175,45 @@ func parseServerTransportOptions(s string) (opts map[string]Args, err error) {
}
return opts, nil
}
+
+// Escape backslashes and all the bytes that are in set.
+func backslashEscape(s string, set []byte) string {
+ var buf bytes.Buffer
+ for _, b := range []byte(s) {
+ if b == '\\' || bytes.IndexByte(set, b) != -1 {
+ buf.WriteByte('\\')
+ }
+ buf.WriteByte(b)
+ }
+ return buf.String()
+}
+
+// Encode a nameâvalue mapping so that it is suitable to go in the ARGS option
+// of an SMETHOD line. The output is sorted by key. The "ARGS:" prefix is not
+// added.
+//
+// "Equal signs and commas [and backslashes] must be escaped with a backslash."
+func encodeSmethodArgs(args Args) string {
+ if args == nil {
+ return ""
+ }
+
+ keys := make([]string, 0, len(args))
+ for key, _ := range args {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+
+ escape := func(s string) string {
+ return backslashEscape(s, []byte{'=', ','})
+ }
+
+ var pairs []string
+ for _, key := range keys {
+ for _, value := range args[key] {
+ pairs = append(pairs, escape(key)+"="+escape(value))
+ }
+ }
+
+ return strings.Join(pairs, ",")
+}
diff --git a/args_test.go b/args_test.go
index ece7a50..d62968c 100644
--- a/args_test.go
+++ b/args_test.go
@@ -299,3 +299,38 @@ func TestParseServerTransportOptions(t *testing.T) {
}
}
}
+
+func TestEncodeSmethodArgs(t *testing.T) {
+ tests := [...]struct {
+ args Args
+ expected string
+ }{
+ {
+ Args{},
+ "",
+ },
+ {
+ Args{"j": []string{"v1", "v2", "v3"}, "k": []string{"v1", "v2", "v3"}},
+ "j=v1,j=v2,j=v3,k=v1,k=v2,k=v3",
+ },
+ {
+ Args{"=,\\": []string{"=", ",", "\\"}},
+ "\\=\\,\\\\=\\=,\\=\\,\\\\=\\,,\\=\\,\\\\=\\\\",
+ },
+ {
+ Args{"secret": []string{"yes"}},
+ "secret=yes",
+ },
+ {
+ Args{"secret": []string{"nou"}, "cache": []string{"/tmp/cache"}},
+ "cache=/tmp/cache,secret=nou",
+ },
+ }
+
+ for _, test := range tests {
+ encoded := encodeSmethodArgs(test.args)
+ if encoded != test.expected {
+ t.Errorf("%q â %q (expected %q)", test.args, encoded, test.expected)
+ }
+ }
+}
More information about the tor-commits
mailing list