Skip to content

Commit 5b49469

Browse files
Marcus SorensenMarcus Sorensen
andauthored
Do value encoding in EncodeValues, add tests (#52)
Co-authored-by: Marcus Sorensen <[email protected]>
1 parent 275fbdc commit 5b49469

File tree

5 files changed

+231
-13
lines changed

5 files changed

+231
-13
lines changed

cloudstack/cloudstack.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -465,16 +465,15 @@ func (cs *CloudStackClient) newRawRequest(api string, post bool, params url.Valu
465465
params.Set("response", "json")
466466

467467
// Generate signature for API call
468-
// * Serialize parameters, URL encoding only values and sort them by key, done by encodeValues
468+
// * Serialize parameters, URL encoding only values and sort them by key, done by EncodeValues
469469
// * Convert the entire argument string to lowercase
470470
// * Replace all instances of '+' to '%20'
471471
// * Calculate HMAC SHA1 of argument string with CloudStack secret
472472
// * URL encode the string and convert to base64
473-
s := encodeValues(params)
473+
s := EncodeValues(params)
474474
s2 := strings.ToLower(s)
475-
s3 := strings.Replace(s2, "+", "%20", -1)
476475
mac := hmac.New(sha1.New, []byte(cs.secret))
477-
mac.Write([]byte(s3))
476+
mac.Write([]byte(s2))
478477
signature := base64.StdEncoding.EncodeToString(mac.Sum(nil))
479478

480479
var err error
@@ -523,7 +522,7 @@ func (cs *CloudStackClient) newRawRequest(api string, post bool, params url.Valu
523522

524523
// Custom version of net/url Encode that only URL escapes values
525524
// Unmodified portions here remain under BSD license of The Go Authors: https://go.googlesource.com/go/+/master/LICENSE
526-
func encodeValues(v url.Values) string {
525+
func EncodeValues(v url.Values) string {
527526
if v == nil {
528527
return ""
529528
}
@@ -541,7 +540,12 @@ func encodeValues(v url.Values) string {
541540
buf.WriteByte('&')
542541
}
543542
buf.WriteString(prefix)
544-
buf.WriteString(url.QueryEscape(v))
543+
escaped := url.QueryEscape(v)
544+
// we need to ensure + (representing a space) is encoded as %20
545+
escaped = strings.Replace(escaped, "+", "%20", -1)
546+
// we need to ensure * is not escaped
547+
escaped = strings.Replace(escaped, "%2A", "*", -1)
548+
buf.WriteString(escaped)
545549
}
546550
}
547551
return buf.String()

generate/generate.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -532,16 +532,15 @@ func (as *allServices) GeneralCode() ([]byte, error) {
532532
pn(" params.Set(\"response\", \"json\")")
533533
pn("")
534534
pn(" // Generate signature for API call")
535-
pn(" // * Serialize parameters, URL encoding only values and sort them by key, done by encodeValues")
535+
pn(" // * Serialize parameters, URL encoding only values and sort them by key, done by EncodeValues")
536536
pn(" // * Convert the entire argument string to lowercase")
537537
pn(" // * Replace all instances of '+' to '%%20'")
538538
pn(" // * Calculate HMAC SHA1 of argument string with CloudStack secret")
539539
pn(" // * URL encode the string and convert to base64")
540-
pn(" s := encodeValues(params)")
540+
pn(" s := EncodeValues(params)")
541541
pn(" s2 := strings.ToLower(s)")
542-
pn(" s3 := strings.Replace(s2, \"+\", \"%%20\", -1)")
543542
pn(" mac := hmac.New(sha1.New, []byte(cs.secret))")
544-
pn(" mac.Write([]byte(s3))")
543+
pn(" mac.Write([]byte(s2))")
545544
pn(" signature := base64.StdEncoding.EncodeToString(mac.Sum(nil))")
546545
pn("")
547546
pn(" var err error")
@@ -590,7 +589,7 @@ func (as *allServices) GeneralCode() ([]byte, error) {
590589
pn("")
591590
pn("// Custom version of net/url Encode that only URL escapes values")
592591
pn("// Unmodified portions here remain under BSD license of The Go Authors: https://go.googlesource.com/go/+/master/LICENSE")
593-
pn("func encodeValues(v url.Values) string {")
592+
pn("func EncodeValues(v url.Values) string {")
594593
pn(" if v == nil {")
595594
pn(" return \"\"")
596595
pn(" }")
@@ -608,7 +607,12 @@ func (as *allServices) GeneralCode() ([]byte, error) {
608607
pn(" buf.WriteByte('&')")
609608
pn(" }")
610609
pn(" buf.WriteString(prefix)")
611-
pn(" buf.WriteString(url.QueryEscape(v))")
610+
pn(" escaped := url.QueryEscape(v)")
611+
pn(" // we need to ensure + (representing a space) is encoded as %%20")
612+
pn(" escaped = strings.Replace(escaped, \"+\", \"%%20\", -1)")
613+
pn(" // we need to ensure * is not escaped")
614+
pn(" escaped = strings.Replace(escaped, \"%%2A\", \"*\", -1)")
615+
pn(" buf.WriteString(escaped)")
612616
pn(" }")
613617
pn(" }")
614618
pn(" return buf.String()")

go.mod

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,20 @@ module github.com/apache/cloudstack-go/v2
22

33
go 1.17
44

5-
require github.com/golang/mock v1.6.0
5+
require (
6+
github.com/golang/mock v1.6.0
7+
github.com/onsi/ginkgo/v2 v2.9.1
8+
github.com/onsi/gomega v1.27.4
9+
)
10+
11+
require (
12+
github.com/go-logr/logr v1.2.3 // indirect
13+
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
14+
github.com/google/go-cmp v0.5.9 // indirect
15+
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
16+
golang.org/x/net v0.8.0 // indirect
17+
golang.org/x/sys v0.6.0 // indirect
18+
golang.org/x/text v0.8.0 // indirect
19+
golang.org/x/tools v0.7.0 // indirect
20+
gopkg.in/yaml.v3 v3.0.1 // indirect
21+
)

0 commit comments

Comments
 (0)