You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by jo...@apache.org on 2014/03/27 20:28:40 UTC

[14/14] git commit: [#7134] Added validation for external checkout URLs

[#7134] Added validation for external checkout URLs

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/2fe81357
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/2fe81357
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/2fe81357

Branch: refs/heads/cj/7134
Commit: 2fe81357b581ba60ad94f5eb05091b44e46f4fff
Parents: 4c30636
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Thu Mar 27 19:28:06 2014 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Thu Mar 27 19:28:06 2014 +0000

----------------------------------------------------------------------
 Allura/allura/lib/repository.py                 | 13 +++++++---
 Allura/allura/lib/validators.py                 | 21 +++++++++++++++
 Allura/allura/tests/test_validators.py          | 19 ++++++++++++++
 ForgeSVN/forgesvn/svn_main.py                   | 27 ++++++++++++--------
 .../forgesvn/templates/svn/checkout_url.html    |  1 +
 5 files changed, 68 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/2fe81357/Allura/allura/lib/repository.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/repository.py b/Allura/allura/lib/repository.py
index 0dda832..f155f7f 100644
--- a/Allura/allura/lib/repository.py
+++ b/Allura/allura/lib/repository.py
@@ -20,7 +20,7 @@ from urllib import quote
 
 from pylons import tmpl_context as c, app_globals as g
 from pylons import request
-from tg import expose, redirect, flash
+from tg import expose, redirect, flash, validate
 from tg.decorators import with_trailing_slash, without_trailing_slash
 from bson import ObjectId
 
@@ -33,6 +33,7 @@ from allura import model as M
 from allura.lib import security
 from allura.lib.decorators import require_post
 from allura.lib.security import has_access
+from allura.lib import validators as v
 from allura.app import Application, SitemapEntry, DefaultAdminController, ConfigOption
 
 log = logging.getLogger(__name__)
@@ -266,7 +267,13 @@ class RepoAdminController(DefaultAdminController):
     @without_trailing_slash
     @expose()
     @require_post()
+    @validate({'external_checkout_url': v.NonHttpUrl})
     def set_checkout_url(self, **post_data):
-        self.app.config.options.external_checkout_url = post_data.get('external_checkout_url') or None
-        flash('Repo options updated')
+        external_checkout_url = (post_data.get('external_checkout_url') or '').strip()
+        if 'external_checkout_url' not in c.form_errors:
+            if self.app.config.options.external_checkout_url != external_checkout_url:
+                self.app.config.options.external_checkout_url = external_checkout_url
+                flash("External checkout URL successfully changed")
+        else:
+            flash("Invalid external checkout URL: %s" % c.form_errors['external_checkout_url'], "error")
         redirect(c.project.url() + 'admin/tools')

http://git-wip-us.apache.org/repos/asf/allura/blob/2fe81357/Allura/allura/lib/validators.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/validators.py b/Allura/allura/lib/validators.py
index bfb87a8..805bf31 100644
--- a/Allura/allura/lib/validators.py
+++ b/Allura/allura/lib/validators.py
@@ -44,6 +44,27 @@ class URL(fev.URL):
     ''', re.I | re.VERBOSE)
 
 
+class NonHttpUrl(URL):
+    messages = {
+        'noScheme': 'You must start your URL with a scheme',
+    }
+    add_http = False
+    scheme_re = re.compile(r'^[a-z][a-z0-9.+-]*:', re.I)
+    url_re = re.compile(r'''
+        ^([a-z][a-z0-9.+-]*)://
+        (?:[%:\w]*@)?                              # authenticator
+        (?:                                        # ip or domain
+        (?P<ip>(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|
+        (?P<domain>[a-z0-9][a-z0-9\-]{,62}\.)*     # subdomain
+        (?P<tld>[a-z]{2,63}|xn--[a-z0-9\-]{2,59})  # top level domain
+        )
+        (?::[0-9]{1,5})?                           # port
+        # files/delims/etc
+        (?P<path>/[a-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]*)?
+        $
+    ''', re.I | re.VERBOSE)
+
+
 class Ming(fev.FancyValidator):
 
     def __init__(self, cls, **kw):

http://git-wip-us.apache.org/repos/asf/allura/blob/2fe81357/Allura/allura/tests/test_validators.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_validators.py b/Allura/allura/tests/test_validators.py
index eacd286..e0b4f2c 100644
--- a/Allura/allura/tests/test_validators.py
+++ b/Allura/allura/tests/test_validators.py
@@ -237,6 +237,7 @@ class TestPathValidator(unittest.TestCase):
 
 class TestUrlValidator(unittest.TestCase):
     val = v.URL
+
     def test_valid(self):
         self.assertEqual('http://192.168.0.1', self.val.to_python('192.168.0.1'))
         self.assertEqual('http://url', self.val.to_python('url'))
@@ -250,3 +251,21 @@ class TestUrlValidator(unittest.TestCase):
         with self.assertRaises(fe.Invalid) as cm:
             self.val.to_python('u"rl')
         self.assertEqual(str(cm.exception), 'That is not a valid URL')
+
+
+class TestNonHttpUrlValidator(unittest.TestCase):
+    val = v.NonHttpUrl
+
+    def test_valid(self):
+        self.assertEqual('svn://192.168.0.1', self.val.to_python('svn://192.168.0.1'))
+        self.assertEqual('ssh+git://url', self.val.to_python('ssh+git://url'))
+
+    def test_invalid(self):
+        with self.assertRaises(fe.Invalid) as cm:
+            self.val.to_python('http://u"rl')
+        self.assertEqual(str(cm.exception), 'That is not a valid URL')
+
+    def test_no_scheme(self):
+        with self.assertRaises(fe.Invalid) as cm:
+            self.val.to_python('url')
+        self.assertEqual(str(cm.exception), 'You must start your URL with a scheme')

http://git-wip-us.apache.org/repos/asf/allura/blob/2fe81357/ForgeSVN/forgesvn/svn_main.py
----------------------------------------------------------------------
diff --git a/ForgeSVN/forgesvn/svn_main.py b/ForgeSVN/forgesvn/svn_main.py
index e1cf7f7..7d7a2f5 100644
--- a/ForgeSVN/forgesvn/svn_main.py
+++ b/ForgeSVN/forgesvn/svn_main.py
@@ -35,6 +35,7 @@ from allura.lib.decorators import require_post
 from allura.lib.repository import RepositoryApp, RepoAdminController
 from allura.app import SitemapEntry, ConfigOption
 from allura.lib import helpers as h
+from allura.lib import validators as v
 from allura import model as M
 
 # Local imports
@@ -121,20 +122,26 @@ class SVNRepoAdminController(RepoAdminController):
     @without_trailing_slash
     @expose()
     @require_post()
+    @validate({'external_checkout_url': v.NonHttpUrl})
     def set_checkout_url(self, **post_data):
-        checkout_url = post_data.get('checkout_url')
-        external_checkout_url = post_data.get('external_checkout_url')
-        if checkout_url and svn_path_exists("file://%s%s/%s" %
-                                            (self.app.repo.fs_path,
-                                             self.app.repo.name,
-                                             checkout_url)):
-            self.app.config.options['checkout_url'] = checkout_url
-            flash("Checkout URL successfully changed")
+        checkout_url = (post_data.get('checkout_url') or '').strip()
+        external_checkout_url = (post_data.get('external_checkout_url') or '').strip()
+        if not checkout_url or svn_path_exists("file://%s%s/%s" %
+                                               (self.app.repo.fs_path,
+                                                self.app.repo.name,
+                                                checkout_url)):
+            if self.app.config.options.checkout_url != checkout_url:
+                self.app.config.options.checkout_url = checkout_url
+                flash("Checkout URL successfully changed")
         else:
             flash("%s is not a valid path for this repository" %
                   checkout_url, "error")
-        self.app.config.options.external_checkout_url = external_checkout_url
-        flash("External checkout URL successfully changed")
+        if 'external_checkout_url' not in c.form_errors:
+            if self.app.config.options.external_checkout_url != external_checkout_url:
+                self.app.config.options.external_checkout_url = external_checkout_url
+                flash("External checkout URL successfully changed")
+        else:
+            flash("Invalid external checkout URL: %s" % c.form_errors['external_checkout_url'], "error")
 
 
 class SVNImportController(BaseController):

http://git-wip-us.apache.org/repos/asf/allura/blob/2fe81357/ForgeSVN/forgesvn/templates/svn/checkout_url.html
----------------------------------------------------------------------
diff --git a/ForgeSVN/forgesvn/templates/svn/checkout_url.html b/ForgeSVN/forgesvn/templates/svn/checkout_url.html
index 9931d0c..3790b46 100644
--- a/ForgeSVN/forgesvn/templates/svn/checkout_url.html
+++ b/ForgeSVN/forgesvn/templates/svn/checkout_url.html
@@ -48,6 +48,7 @@
   <div class="grid-13">&nbsp;</div>
   <div class="grid-13">
     <input type="button" onclick="save_checkout_url()" value="Save">
+    <a href="#" class="close">Cancel</a>
   </div>
   {% endif %}
 </form>