1919
2020__docformat__ = 'restructuredtext'
2121
22+ # List of schemes that are not rendered as links in rst and markdown.
23+ _disable_url_schemes = [ 'javascript' ]
2224
2325import base64 , cgi , re , os .path , mimetypes , csv , string
2426import calendar
@@ -62,8 +64,8 @@ def _import_markdown2():
6264 try :
6365 import markdown2 , re
6466 class Markdown (markdown2 .Markdown ):
65- # don't restrict protocols in links
66- _safe_protocols = re .compile ('' , re .IGNORECASE )
67+ # don't allow disabled protocols in links
68+ _safe_protocols = re .compile ('(?!' + ':|' . join ([ re . escape ( s ) for s in _disable_url_schemes ]) + ':) ' , re .IGNORECASE )
6769
6870 markdown = lambda s : Markdown (safe_mode = 'escape' , extras = { 'fenced-code-blocks' : True }).convert (s )
6971 except ImportError :
@@ -75,9 +77,19 @@ def _import_markdown():
7577 try :
7678 from markdown import markdown as markdown_impl
7779 from markdown .extensions import Extension as MarkdownExtension
78-
79- # make sure any HTML tags get escaped
80- class EscapeHtml (MarkdownExtension ):
80+ from markdown .treeprocessors import Treeprocessor
81+
82+ class RestrictLinksProcessor (Treeprocessor ):
83+ def run (self , root ):
84+ for el in root .iter ('a' ):
85+ if 'href' in el .attrib :
86+ url = el .attrib ['href' ].lstrip (' \r \n \t \x1a \0 ' ).lower ()
87+ for s in _disable_url_schemes :
88+ if url .startswith (s + ':' ):
89+ el .attrib ['href' ] = '#'
90+
91+ # make sure any HTML tags get escaped and some links restricted
92+ class SafeHtml (MarkdownExtension ):
8193 def extendMarkdown (self , md , md_globals = None ):
8294 if hasattr (md .preprocessors , 'deregister' ):
8395 md .preprocessors .deregister ('html_block' )
@@ -88,15 +100,22 @@ def extendMarkdown(self, md, md_globals=None):
88100 else :
89101 del md .inlinePatterns ['html' ]
90102
91- markdown = lambda s : markdown_impl (s , extensions = [EscapeHtml (), 'fenced_code' ])
103+ if hasattr (md .preprocessors , 'register' ):
104+ md .treeprocessors .register (RestrictLinksProcessor (), 'restrict_links' , 0 )
105+ else :
106+ md .treeprocessors ['restrict_links' ] = RestrictLinksProcessor ()
107+
108+ markdown = lambda s : markdown_impl (s , extensions = [SafeHtml (), 'fenced_code' ])
92109 except ImportError :
93110 markdown = None
94111
95112 return markdown
96113
97114def _import_mistune ():
98115 try :
99- from mistune import markdown
116+ import mistune
117+ mistune ._scheme_blacklist = [ s + ':' for s in _disable_url_schemes ]
118+ markdown = mistune .markdown
100119 except ImportError :
101120 markdown = None
102121
@@ -1499,10 +1518,6 @@ class StringHTMLProperty(HTMLProperty):
14991518 'raw_enabled' : 0 ,
15001519 '_disable_config' : 1 }
15011520
1502- # List of schemes that are not rendered as links in rst.
1503- # Could also be used to disable links for other processors:
1504- # e.g. stext or markdown. If we can figure out how to do it.
1505- disable_schemes = [ 'javascript' ]
15061521 valid_schemes = { }
15071522
15081523 def _hyper_repl (self , match ):
@@ -1570,13 +1585,7 @@ def _hyper_repl_rst(self, match):
15701585 return match .group (0 )
15711586
15721587 def _hyper_repl_markdown (self , match ):
1573- if match .group ('url' ):
1574- s = match .group ('url' )
1575- return '[%s](%s)' % (s , s )
1576- elif match .group ('email' ):
1577- s = match .group ('email' )
1578- return '[%s](mailto:%s)' % (s , s )
1579- elif len (match .group ('id' )) < 10 :
1588+ if match .group ('id' ) and len (match .group ('id' )) < 10 :
15801589 return self ._hyper_repl_item (match ,'[%(item)s](%(cls)s%(id)s)' )
15811590 else :
15821591 # just return the matched text
@@ -1670,7 +1679,7 @@ def rst(self, hyperlink=1):
16701679
16711680 # disable javascript and possibly other url schemes from working
16721681 from docutils .utils .urischemes import schemes
1673- for sch in self . disable_schemes :
1682+ for sch in _disable_url_schemes :
16741683 # I catch KeyError but reraise if scheme didn't exist.
16751684 # Safer to fail if a disabled scheme isn't found. It may
16761685 # be a typo that keeps a bad scheme enabled. But this
0 commit comments