1 # -*- coding: iso-8859-1 -*-
3 MoinMoin - ImageMap Parser
5 This parser is used to create clickable image maps.
10 picsrc[;width=".."][;height=".."][;alt=".."][;title=".."]
11 link_area1;shape="rect|circle|poly";coords="..";alt=".."[;title=".."]
12 link_area2;shape="rect|circle|poly";coords="..";alt=".."[;title=".."]
15 For a detailed explanation of the syntax see:
16 http://moinmoin.wikiwikiweb.de/ParserMarket/ImageMap
18 Please note: Image maps are not accessible by blind people. Do also have a
19 look at the best-practise-examples for using image maps
20 on http://moinmoin.wikiwikiweb.de/ParserMarket/ImageMap.
25 picture.jpg;width="345";height="312";alt="Clickable Organizational Chart"
26 FrontPage;shape="rect";coords="11,10,59,29";alt="Area1"
27 http://www.xyz.com/;shape="circle";coords="42,36,96";alt="Area2"
28 FrontPage/SubPage;shape="poly";coords="48,311,105,248,96,210";alt="Area3"
29 Another Site in This Wiki;shape="rect";coords="88,10,59,29";alt="Area4"
30 InterWiki:RemotePage;shape="rect";coords="181,120,59,29";alt="Area5"
33 ImageMap Parser is partly based on ImageLink Macro
35 @copyright: 2001 by Jeff Kunce,
36 2004 by Marcin Zalewski,
37 2004-2006 by Reimar Bauer,
38 2006 by Thomas Waldmann
39 @license: GNU GPL, see COPYING for details.
42 @copyright: 2006,2007 by Oliver Siemoneit
43 @license: GNU GPL, see COPYING for details.
48 * Made code PEP8 compatible.
49 * Parameter checking and stripping added to prevent inserting of malicious
50 code in html page via parser call.
53 * Fixed ouput abstraction violations: on other formatters than html-formatter
54 just the specified image is output via formatter.image and map information
56 * In case of missing alt texts: "alt" ist set to alt="" (for the whole map)
57 and to alt="area_url" (for the different clickable areas).
58 * Now also "title" supported to generate tooltips for the map areas.
59 * Interwiki links can also be specified in "wiki:MoinMoin/Page" syntax now.
62 * Allow setting any HTML attribute that is allowed by the HTML4.01 spec,
63 except for javascript event handlers.
68 from MoinMoin import wikiutil, config
69 from MoinMoin.action import AttachFile
71 # Define the valid attributes for map and area elements. These are directly
72 # taken from the HTML4.01 spec at http://www.w3.org/TR/html401/ The lists below
73 # mimic the structure used in the HTML spec.
74 html_core_attrs = ['id', 'class', 'style', 'title']
75 html_i18n = ['lang', 'dir']
76 html_events = [] # event attributes left out for security reasons.
77 html_attrs = html_core_attrs + html_i18n + html_events
78 html_map_attrs = html_attrs + ['name']
79 html_area_attrs = html_attrs + ['shape', 'coords', 'href', 'nohref', 'alt', 'tabindex', 'accesskey']
84 def _is_InterWiki(text):
87 def _is_allowed_Para(para, allowed_paras):
90 for p in allowed_paras:
91 if para.startswith(p):
95 def _strip_Para(para):
96 _para = wikiutil.escape(para)
97 if para.count('"') < 2:
99 shortend_para = _para[0:_para.find('"')+1]
100 cut_para = _para[_para.find('"')+1:len(_para)]
101 shortend_para += cut_para[0:cut_para.find('"')+1]
107 def __init__(self, raw, request, **kw):
109 self.request = request
111 def format(self, formatter):
112 request = self.request
114 row = self.raw.split('\n')
116 # Produce <img ...> html-code stuff
117 paras = row[0].split(';')
118 image = wikiutil.escape(paras[0])
119 mapname = '%s_%s' % ([image, image[:15]][(len(image) > 14)], str(random.randint(1, 999999)))
123 elif _is_InterWiki(image):
124 if image.startswith('wiki:'):
126 wikitag, wikiurl, wikitail, err = wikiutil.resolve_wiki(request, image)
127 imgurl = wikiutil.join_wiki(wikiurl, wikitail)
129 pagename, attname = AttachFile.absoluteName(image, formatter.page.page_name)
130 imgurl = AttachFile.getAttachUrl(pagename, attname, request)
131 attachment_fname = AttachFile.getFilename(request, pagename, attname)
133 if not os.path.exists(attachment_fname):
134 linktext = _('Upload new attachment "%(filename)s"')
135 output = wikiutil.link_tag(request,
136 ('%s?action=AttachFile&rename=%s' % (
137 wikiutil.quoteWikinameURL(pagename),
138 wikiutil.url_quote_plus(attname))),
139 text=linktext % {'filename': attname},
141 request.write(output)
145 <img src="%s"''' % imgurl
151 # Prevent attacks like: pic.png;height="10" onmouseover="ExecuteBadCode()";alt="..";
152 # and: pic.png;height="10" onmouseover="ExecuteBadCode()";alt="..";
153 # and: pic.png;height="10" onmouseover="ExecuteBadCode()";alt="..";
155 if _is_allowed_Para(p, html_map_attrs):
157 # Prepare dict for formatter.image if formatter.rawHTML call fails
158 key, value = p.split('=', 1)
159 kw[str(key.lower())] = value.strip('"')
161 # If there is no alt provided, create one
166 html += ' usemap="#%s"> ' % mapname
169 # Produce <map ..> html-code stuff
171 <map name="%s">''' % mapname
175 paras[0] = wikiutil.escape(paras[0])
177 if _is_URL(paras[0]):
179 elif _is_InterWiki(paras[0]):
180 if paras[0].startswith('wiki:'):
181 paras[0] = paras[0][5:]
182 wikitag, wikiurl, wikitail, err = wikiutil.resolve_wiki(request, paras[0])
183 area_url = wikiutil.join_wiki(wikiurl, wikitail)
185 area_url = wikiutil.quoteWikinameURL(paras[0])
189 <area href="%s"''' % area_url
192 # Prevent attacks like: FrontPage;shape="rect" onmouseover="ExecuteBadCode()";coords="..";
193 # and: FrontPage;shape="rect" onmouseover="ExecuteBadCode()";coords="..";
194 # and: FrontPage;shape="rect" onmouseover="ExecuteBadCode()";coords="..";
196 if _is_allowed_Para(i, html_area_attrs):
198 # If there is no alt provided at all, set alt to area_url
199 if p.lower().find('alt="') == -1:
200 html += ' alt="%s"' % area_url
207 # If current formatter is a HTML formatter, output image map with formatter.rawHTML().
208 # Otherwise just output image with formatter.image()
210 request.write(formatter.rawHTML(html))
212 request.write(formatter.image(**kw))