From 18e3771ac7c74986a4f06221a72781ace54b1169 Mon Sep 17 00:00:00 2001
From: Bill Hoffman <bill.hoffman@kitware.com>
Date: Thu, 29 Jan 2015 14:42:44 -0500
Subject: ctest_submit: Escape URL components in CDASH_UPLOAD mode

Call curl_easy_escape on arguments sent to CDash upload.
---
 Source/CTest/cmCTestCurl.cxx          | 19 +++++++++++++++----
 Source/CTest/cmCTestCurl.h            |  2 ++
 Source/CTest/cmCTestSubmitHandler.cxx | 25 ++++++++++++++-----------
 3 files changed, 31 insertions(+), 15 deletions(-)

diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx
index b0d26cc..b4c0137 100644
--- a/Source/CTest/cmCTestCurl.cxx
+++ b/Source/CTest/cmCTestCurl.cxx
@@ -25,6 +25,21 @@ cmCTestCurl::cmCTestCurl(cmCTest* ctest)
   this->VerifyPeerOff = false;
   this->VerifyHostOff = false;
   this->TimeOutSeconds = 0;
+  this->Curl = curl_easy_init();
+}
+
+cmCTestCurl::~cmCTestCurl()
+{
+  ::curl_easy_cleanup(this->Curl);
+  ::curl_global_cleanup();
+}
+
+std::string cmCTestCurl::Escape(std::string const& source)
+{
+  char* data1 = curl_easy_escape(this->Curl, source.c_str(), 0);
+  std::string ret = data1;
+  curl_free(data1);
+  return ret;
 }
 
 namespace
@@ -73,7 +88,6 @@ void cmCTestCurl::SetCurlOptions(std::vector<std::string> const& args)
 
 bool cmCTestCurl::InitCurl()
 {
-  this->Curl = curl_easy_init();
   if(!this->Curl)
     {
     return false;
@@ -160,7 +174,6 @@ bool cmCTestCurl::UploadFile(std::string const& local_file,
   // Now run off and do what you've been told!
   ::curl_easy_perform(this->Curl);
   ::fclose(ftpfile);
-  ::curl_global_cleanup();
 
   if ( responseData.size() > 0 )
     {
@@ -213,8 +226,6 @@ bool cmCTestCurl::HttpRequest(std::string const& url,
 
   CURLcode res = ::curl_easy_perform(this->Curl);
 
-  ::curl_easy_cleanup(this->Curl);
-  ::curl_global_cleanup();
   if ( responseData.size() > 0 )
     {
     response = std::string(responseData.begin(), responseData.end());
diff --git a/Source/CTest/cmCTestCurl.h b/Source/CTest/cmCTestCurl.h
index 5bb8b41..0737bb6 100644
--- a/Source/CTest/cmCTestCurl.h
+++ b/Source/CTest/cmCTestCurl.h
@@ -22,6 +22,7 @@ class cmCTestCurl
 {
 public:
   cmCTestCurl(cmCTest*);
+  ~cmCTestCurl();
   bool UploadFile(std::string const& url,
                   std::string const& file,
                   std::string const& fields,
@@ -34,6 +35,7 @@ public:
   void SetCurlOptions(std::vector<std::string> const& args);
   void SetUseHttp10On() { this->UseHttp10 = true;}
   void SetTimeOutSeconds(int s) { this->TimeOutSeconds = s;}
+  std::string Escape(std::string const& source);
 protected:
   void SetProxyType();
   bool InitCurl();
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 3d9545f..5b52df7 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -1128,21 +1128,24 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
   // TODO: Encode values for a URL instead of trusting caller.
   std::ostringstream str;
   str << "project="
-      << this->CTest->GetCTestConfiguration("ProjectName") << "&";
+      << curl.Escape(this->CTest->GetCTestConfiguration("ProjectName")) << "&";
   if(subproject)
     {
-    str << "subproject=" << subproject << "&";
+    str << "subproject=" << curl.Escape(subproject) << "&";
     }
-  str << "stamp=" << this->CTest->GetCurrentTag() << "-"
-      << this->CTest->GetTestModelString() << "&"
-      << "model=" << this->CTest->GetTestModelString() << "&"
-      << "build=" << this->CTest->GetCTestConfiguration("BuildName") << "&"
-      << "site=" << this->CTest->GetCTestConfiguration("Site") << "&"
-      << "track=" << this->CTest->GetTestModelString() << "&"
+  str << "stamp=" << curl.Escape(this->CTest->GetCurrentTag()) << "-"
+      << curl.Escape(this->CTest->GetTestModelString()) << "&"
+      << "model=" << curl.Escape(this->CTest->GetTestModelString()) << "&"
+      << "build="
+      << curl.Escape(this->CTest->GetCTestConfiguration("BuildName")) << "&"
+      << "site="
+      << curl.Escape(this->CTest->GetCTestConfiguration("Site")) << "&"
+      << "track="
+      << curl.Escape(this->CTest->GetTestModelString()) << "&"
       << "starttime=" << (int)cmSystemTools::GetTime() << "&"
       << "endtime=" << (int)cmSystemTools::GetTime() << "&"
       << "datafilesmd5[0]=" << md5sum << "&"
-      << "type=" << typeString;
+      << "type=" << curl.Escape(typeString);
   std::string fields = str.str();
   cmCTestLog(this->CTest, DEBUG, "fields: " << fields << "\nurl:"
              << url << "\nfile: " << file << "\n");
@@ -1192,9 +1195,9 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
 
   std::string upload_as = cmSystemTools::GetFilenameName(file);
   std::ostringstream fstr;
-  fstr << "type=" << typeString << "&"
+  fstr << "type=" << curl.Escape(typeString) << "&"
        << "md5=" << md5sum << "&"
-       << "filename=" << upload_as << "&"
+       << "filename=" << curl.Escape(upload_as) << "&"
        << "buildid=" << json["buildid"].asString();
   if(!curl.UploadFile(file, url, fstr.str(), response))
     {
-- 
cgit v0.12