From cf4f3d17edf84c7cc35b351cf139607cd46a0d71 Mon Sep 17 00:00:00 2001
From: mhuin <mhuin@redhat.com>
Date: Tue, 6 Dec 2016 13:15:57 +0100
Subject: [PATCH] url-proof scripts passed to run_script

Groovy scripts may contain characters that need to be escaped prior
to being passed to Jenkins' REST API; for example "&&" in condition
testing. Not doing so will result in a script execution failure on
the server.

Change-Id: Ied6c2a48392cadbadb84865dad47ceed99e694a1
---
 jenkins/__init__.py  |  2 +-
 tests/test_script.py | 11 +++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/jenkins/__init__.py b/jenkins/__init__.py
index 235dd05..3680aeb 100755
--- a/jenkins/__init__.py
+++ b/jenkins/__init__.py
@@ -1064,7 +1064,7 @@ class Jenkins(object):
             Plugin:maven-plugin, Plugin:pam-auth]'
         '''
         return self.jenkins_open(Request(self._build_url(SCRIPT_TEXT),
-                                         "script=".encode('utf-8') + script.encode('utf-8')))
+                                         "script=".encode('utf-8') + quote(script).encode('utf-8')))
 
     def install_plugin(self, name, include_dependencies=True):
         '''Install a plugin and its dependencies from the Jenkins public
diff --git a/tests/test_script.py b/tests/test_script.py
index cc0c521..616c5ff 100644
--- a/tests/test_script.py
+++ b/tests/test_script.py
@@ -1,4 +1,5 @@
 from mock import patch
+from six.moves.urllib.parse import quote
 
 import jenkins
 from tests.base import JenkinsTestBase
@@ -15,6 +16,16 @@ class JenkinsScriptTest(JenkinsTestBase):
             self.make_url('scriptText'))
         self._check_requests(jenkins_mock.call_args_list)
 
+    @patch.object(jenkins.Jenkins, 'jenkins_open')
+    def test_run_script_urlproof(self, jenkins_mock):
+        self.j.run_script(u'if (a == b && c ==d) { println(\"Yes\")}')
+
+        self.assertEqual(
+            jenkins_mock.call_args[0][0].get_full_url(),
+            self.make_url('scriptText'))
+        self.assertIn(quote('&&'), jenkins_mock.call_args[0][0].data.decode('utf8'))
+        self._check_requests(jenkins_mock.call_args_list)
+
     @patch.object(jenkins.Jenkins, 'jenkins_open')
     def test_install_plugin(self, jenkins_mock):
         '''Installation of plugins is done with the run_script method