diff --git a/pagure/lib/git.py b/pagure/lib/git.py index e0ac3d4..03fd140 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -472,7 +472,7 @@ def update_custom_field_from_json(session, repo, issue, json_data): def update_ticket_from_git( - session, reponame, namespace, username, issue_uid, json_data): + session, reponame, namespace, username, issue_uid, json_data): """ Update the specified issue (identified by its unique identifier) with the data present in the json blob provided. diff --git a/pagure/templates/issue.html b/pagure/templates/issue.html index 38dd952..e37534b 100644 --- a/pagure/templates/issue.html +++ b/pagure/templates/issue.html @@ -324,7 +324,16 @@

- {{ knowns_keys[field.name].value if field.name in knowns_keys }} + {% if field.name in knowns_keys %} + {% if field.key_type == 'link' %} + {% for link in knowns_keys[field.name].value.split(',') %} + {{ link }} +
+ {% endfor %} + {% else %} + {{ knowns_keys[field.name].value }} + {% endif %} + {% endif %}

diff --git a/pagure/templates/settings.html b/pagure/templates/settings.html index fe31308..c9bc445 100644 --- a/pagure/templates/settings.html +++ b/pagure/templates/settings.html @@ -708,6 +708,9 @@ + @@ -948,6 +951,7 @@ $('#new_custom_field').click(function(e) { \ \ ' diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py index 82f1a49..8447598 100644 --- a/pagure/ui/issues.py +++ b/pagure/ui/issues.py @@ -25,6 +25,7 @@ from sqlalchemy.exc import SQLAlchemyError import kitchen.text.converters as ktc import mimetypes +import re import pagure.doc_utils import pagure.exceptions @@ -35,8 +36,55 @@ from pagure import (APP, SESSION, LOG, __get_file_in_tree, login_required, authenticated) +ip_middle_octet = u"(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5]))" +ip_last_octet = u"(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))" + +""" +regex based on https://github.com/kvesteri/validators/blob/master/validators/url.py +""" +urlregex = re.compile( + u"^" + # protocol identifier + u"(?:(?:https?|ftp)://)" + # user:pass authentication + u"(?:\S+(?::\S*)?@)?" + u"(?:" + u"(?P" + # IP address exclusion + # private & local networks + u"(?:(?:10|127)" + ip_middle_octet + u"{2}" + ip_last_octet + u")|" + u"(?:(?:169\.254|192\.168)" + ip_middle_octet + ip_last_octet + u")|" + u"(?:172\.(?:1[6-9]|2\d|3[0-1])" + ip_middle_octet + ip_last_octet + u"))" + u"|" + # IP address dotted notation octets + # excludes loopback network 0.0.0.0 + # excludes reserved space >= 224.0.0.0 + # excludes network & broadcast addresses + # (first & last IP address of each class) + u"(?P" + u"(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])" + u"" + ip_middle_octet + u"{2}" + u"" + ip_last_octet + u")" + u"|" + # host name + u"(?:(?:[a-z\u00a1-\uffff0-9]-?)*[a-z\u00a1-\uffff0-9]+)" + # domain name + u"(?:\.(?:[a-z\u00a1-\uffff0-9]-?)*[a-z\u00a1-\uffff0-9]+)*" + # TLD identifier + u"(?:\.(?:[a-z\u00a1-\uffff]{2,}))" + u")" + # port number + u"(?::\d{2,5})?" + # resource path + u"(?:/\S*)?" + u"$", + re.UNICODE | re.IGNORECASE +) +urlpattern = re.compile(urlregex) + # URLs + @APP.route( '//issue//update/', methods=['GET', 'POST']) @@ -269,10 +317,21 @@ def update_issue(repo, issueid, username=None, namespace=None): # Update the custom keys/fields for key in repo.issue_keys: value = flask.request.form.get(key.name) - messages.add( - pagure.lib.set_custom_key_value( - SESSION, issue, key, value) - ) + if value: + if key.key_type == 'link': + links = value.split(',') + for link in links: + link = link.replace(' ', '') + if not urlpattern.match(link): + flask.abort( + 400, + 'Meta-data "link" field ' + '(%s) has invalid url (%s) ' % + (key.name, link)) + messages.add( + pagure.lib.set_custom_key_value( + SESSION, issue, key, value) + ) # Update ticket this one depends on messages.union(set(pagure.lib.update_dependency_issue(