From 6855216387594566f37672a0962b6e7d18b192d9 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Thu, 5 Apr 2018 10:04:12 -0700 Subject: [PATCH] force QueryEscape to escape spaces as %20 instead of as + for ovftool. --- post-processor/vsphere/post-processor.go | 13 ++++++-- post-processor/vsphere/post-processor_test.go | 31 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/post-processor/vsphere/post-processor.go b/post-processor/vsphere/post-processor.go index b9702fe82..fcf209ea7 100644 --- a/post-processor/vsphere/post-processor.go +++ b/post-processor/vsphere/post-processor.go @@ -110,9 +110,9 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac return nil, false, fmt.Errorf("VMX, OVF or OVA file not found") } - password := url.QueryEscape(p.config.Password) + password := escapeWithSpaces(p.config.Password) ovftool_uri := fmt.Sprintf("vi://%s:%s@%s/%s/host/%s", - url.QueryEscape(p.config.Username), + escapeWithSpaces(p.config.Username), password, p.config.Host, p.config.Datacenter, @@ -146,7 +146,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac } func (p *PostProcessor) filterLog(s string) string { - password := url.QueryEscape(p.config.Password) + password := escapeWithSpaces(p.config.Password) return strings.Replace(s, password, "", -1) } @@ -186,3 +186,10 @@ func (p *PostProcessor) BuildArgs(source, ovftool_uri string) ([]string, error) return args, nil } + +// Encode everything except for + signs +func escapeWithSpaces(stringToEscape string) string { + escapedString := url.QueryEscape(stringToEscape) + escapedString = strings.Replace(escapedString, "+", `%20`, -1) + return escapedString +} diff --git a/post-processor/vsphere/post-processor_test.go b/post-processor/vsphere/post-processor_test.go index 61b58789b..65b99f9a7 100644 --- a/post-processor/vsphere/post-processor_test.go +++ b/post-processor/vsphere/post-processor_test.go @@ -40,3 +40,34 @@ func TestArgs(t *testing.T) { t.Logf("ovftool %s", strings.Join(args, " ")) } + +func TestEscaping(t *testing.T) { + type escapeCases struct { + Input string + Expected string + } + + cases := []escapeCases{ + {`this has spaces`, `this%20has%20spaces`}, + {`exclaimation_!`, `exclaimation_%21`}, + {`hash_#_dollar_$`, `hash_%23_dollar_%24`}, + {`ampersand_&awesome`, `ampersand_%26awesome`}, + {`single_quote_'_and_another_'`, `single_quote_%27_and_another_%27`}, + {`open_paren_(_close_paren_)`, `open_paren_%28_close_paren_%29`}, + {`asterisk_*_plus_+`, `asterisk_%2A_plus_%2B`}, + {`comma_,slash_/`, `comma_%2Cslash_%2F`}, + {`colon_:semicolon_;`, `colon_%3Asemicolon_%3B`}, + {`equal_=question_?`, `equal_%3Dquestion_%3F`}, + {`at_@`, `at_%40`}, + {`open_bracket_[closed_bracket]`, `open_bracket_%5Bclosed_bracket%5D`}, + {`user:password with $paces@host/name.foo`, `user%3Apassword%20with%20%24paces%40host%2Fname.foo`}, + } + for _, escapeCase := range cases { + received := escapeWithSpaces(escapeCase.Input) + + if escapeCase.Expected != received { + t.Errorf("Error escaping URL; expected %s got %s", escapeCase.Expected, received) + } + } + +}