mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 21:43:21 +00:00
bugdown: Add option to support "file:///" as hyperlink.
This contains contributions from Tim Abbott and Igor Tokarev. Fixes #380.
This commit is contained in:
@@ -719,7 +719,7 @@ def sanitize_url(url):
|
|||||||
if not scheme:
|
if not scheme:
|
||||||
return sanitize_url('http://' + url)
|
return sanitize_url('http://' + url)
|
||||||
|
|
||||||
locless_schemes = ['mailto', 'news']
|
locless_schemes = ['mailto', 'news', 'file']
|
||||||
if netloc == '' and scheme not in locless_schemes:
|
if netloc == '' and scheme not in locless_schemes:
|
||||||
# This fails regardless of anything else.
|
# This fails regardless of anything else.
|
||||||
# Return immediately to save additional proccessing
|
# Return immediately to save additional proccessing
|
||||||
@@ -729,7 +729,7 @@ def sanitize_url(url):
|
|||||||
# appears to have a netloc. Additionally there are plenty of other
|
# appears to have a netloc. Additionally there are plenty of other
|
||||||
# schemes that do weird things like launch external programs. To be
|
# schemes that do weird things like launch external programs. To be
|
||||||
# on the safe side, we whitelist the scheme.
|
# on the safe side, we whitelist the scheme.
|
||||||
if scheme not in ('http', 'https', 'ftp', 'mailto'):
|
if scheme not in ('http', 'https', 'ftp', 'mailto', 'file'):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Upstream code scans path, parameters, and query for colon characters
|
# Upstream code scans path, parameters, and query for colon characters
|
||||||
@@ -1079,12 +1079,14 @@ class Bugdown(markdown.Extension):
|
|||||||
%s # zero-to-6 sets of paired parens
|
%s # zero-to-6 sets of paired parens
|
||||||
)?) # Path is optional
|
)?) # Path is optional
|
||||||
| (?:[\w.-]+\@[\w.-]+\.[\w]+) # Email is separate, since it can't have a path
|
| (?:[\w.-]+\@[\w.-]+\.[\w]+) # Email is separate, since it can't have a path
|
||||||
|
%s # File path start with file:///, enable by setting ENABLE_FILE_LINKS=True
|
||||||
)
|
)
|
||||||
(?= # URL must be followed by (not included in group)
|
(?= # URL must be followed by (not included in group)
|
||||||
[!:;\?\),\.\'\"\>]* # Optional punctuation characters
|
[!:;\?\),\.\'\"\>]* # Optional punctuation characters
|
||||||
(?:\Z|\s) # followed by whitespace or end of string
|
(?:\Z|\s) # followed by whitespace or end of string
|
||||||
)
|
)
|
||||||
""" % (tlds, nested_paren_chunk)
|
""" % (tlds, nested_paren_chunk,
|
||||||
|
r"| (?:file://(/[^/ ]*)+/?)" if settings.ENABLE_FILE_LINKS else r"")
|
||||||
md.inlinePatterns.add('autolink', AutoLink(link_regex), '>link')
|
md.inlinePatterns.add('autolink', AutoLink(link_regex), '>link')
|
||||||
|
|
||||||
md.preprocessors.add('hanging_ulists',
|
md.preprocessors.add('hanging_ulists',
|
||||||
|
|||||||
@@ -925,7 +925,10 @@ class Message(ModelReprMixin, models.Model):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def content_has_link(content):
|
def content_has_link(content):
|
||||||
# type: (text_type) -> bool
|
# type: (text_type) -> bool
|
||||||
return 'http://' in content or 'https://' in content or '/user_uploads' in content
|
return ('http://' in content or
|
||||||
|
'https://' in content or
|
||||||
|
'/user_uploads' in content or
|
||||||
|
(settings.ENABLE_FILE_LINKS and 'file:///' in content))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_status_message(content, rendered_content):
|
def is_status_message(content, rendered_content):
|
||||||
|
|||||||
@@ -211,6 +211,22 @@ class BugdownTest(TestCase):
|
|||||||
converted = bugdown_convert(inline_url)
|
converted = bugdown_convert(inline_url)
|
||||||
self.assertEqual(match, converted)
|
self.assertEqual(match, converted)
|
||||||
|
|
||||||
|
def test_inline_file(self):
|
||||||
|
# type: () -> None
|
||||||
|
msg = 'Check out this file file:///Volumes/myserver/Users/Shared/pi.py'
|
||||||
|
converted = bugdown_convert(msg)
|
||||||
|
self.assertEqual(converted, '<p>Check out this file <a href="file:///Volumes/myserver/Users/Shared/pi.py" target="_blank" title="file:///Volumes/myserver/Users/Shared/pi.py">file:///Volumes/myserver/Users/Shared/pi.py</a></p>')
|
||||||
|
|
||||||
|
with self.settings(ENABLE_FILE_LINKS=False):
|
||||||
|
realm = Realm.objects.create(
|
||||||
|
domain='file_links_test.example.com',
|
||||||
|
string_id='file_links_test')
|
||||||
|
bugdown.make_md_engine(
|
||||||
|
realm.domain,
|
||||||
|
{'realm_filters': [[], u'file_links_test.example.com'], 'realm': [u'file_links_test.example.com', 'Realm name']})
|
||||||
|
converted = bugdown.convert(msg, realm_domain=realm.domain)
|
||||||
|
self.assertEqual(converted, '<p>Check out this file file:///Volumes/myserver/Users/Shared/pi.py</p>')
|
||||||
|
|
||||||
def test_inline_youtube(self):
|
def test_inline_youtube(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
msg = 'Check out the debate: http://www.youtube.com/watch?v=hx1mjT73xYE'
|
msg = 'Check out the debate: http://www.youtube.com/watch?v=hx1mjT73xYE'
|
||||||
|
|||||||
@@ -140,6 +140,10 @@ ERROR_REPORTING = True
|
|||||||
# a link to an image is referenced in a message.
|
# a link to an image is referenced in a message.
|
||||||
INLINE_IMAGE_PREVIEW = True
|
INLINE_IMAGE_PREVIEW = True
|
||||||
|
|
||||||
|
# Controls whether or not Zulip will parse links starting with
|
||||||
|
# "file:///" as a hyperlink (useful if you have e.g. an NFS share).
|
||||||
|
ENABLE_FILE_LINKS = False
|
||||||
|
|
||||||
# By default, files uploaded by users and user avatars are stored
|
# By default, files uploaded by users and user avatars are stored
|
||||||
# directly on the Zulip server. If file storage in Amazon S3 is
|
# directly on the Zulip server. If file storage in Amazon S3 is
|
||||||
# desired, you can configure that as follows:
|
# desired, you can configure that as follows:
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ DEFAULT_SETTINGS = {'TWITTER_CONSUMER_KEY': '',
|
|||||||
'FIRST_TIME_TOS_TEMPLATE': None,
|
'FIRST_TIME_TOS_TEMPLATE': None,
|
||||||
'USING_PGROONGA': False,
|
'USING_PGROONGA': False,
|
||||||
'POST_MIGRATION_CACHE_FLUSHING': False,
|
'POST_MIGRATION_CACHE_FLUSHING': False,
|
||||||
|
'ENABLE_FILE_LINKS': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
for setting_name, setting_val in six.iteritems(DEFAULT_SETTINGS):
|
for setting_name, setting_val in six.iteritems(DEFAULT_SETTINGS):
|
||||||
|
|||||||
@@ -91,6 +91,9 @@ CACHES['database'] = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Enable file:/// hyperlink support by default in tests
|
||||||
|
ENABLE_FILE_LINKS = True
|
||||||
|
|
||||||
LOGGING['loggers']['zulip.requests']['level'] = 'CRITICAL'
|
LOGGING['loggers']['zulip.requests']['level'] = 'CRITICAL'
|
||||||
LOGGING['loggers']['zulip.management']['level'] = 'CRITICAL'
|
LOGGING['loggers']['zulip.management']['level'] = 'CRITICAL'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user