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(