commit 9a9f9cb455d17bf82d02292953b945dcbb4a5029
Author: David Fifield <[email protected]>
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)
+               }
+       }
+}



_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to