mirror of
https://github.com/munki/munki.git
synced 2026-05-08 05:19:31 -05:00
HTML escape and/or JavaScript quote item fields that are substituted into templates to prevent invalid HTML/JavaScript.
This commit is contained in:
@@ -520,7 +520,7 @@ class GenericItem(dict):
|
||||
icon_name += '.png'
|
||||
icon_path = os.path.join(msclib.html_dir(), 'icons', icon_name)
|
||||
if os.path.exists(icon_path):
|
||||
return 'icons/' + icon_name
|
||||
return 'icons/' + quote(icon_name)
|
||||
# didn't find one in the downloaded icons
|
||||
# so create one if needed from a locally installed app
|
||||
for key in ['icon_name', 'display_name', 'name']:
|
||||
@@ -531,7 +531,7 @@ class GenericItem(dict):
|
||||
icon_name += '.png'
|
||||
icon_path = os.path.join(msclib.html_dir(), icon_name)
|
||||
if os.path.exists(icon_path) or convertIconToPNG(name, icon_path, 350):
|
||||
return icon_name
|
||||
return quote(icon_name)
|
||||
else:
|
||||
# use the Generic package icon
|
||||
return 'static/Generic.png'
|
||||
|
||||
@@ -115,6 +115,32 @@ def generate_page(page_name, main_page_template_name, page_dict, **kwargs):
|
||||
write_page(page_name, html)
|
||||
|
||||
|
||||
def escape_quotes(text):
|
||||
"""Escape single and double-quotes for JavaScript"""
|
||||
return text.replace("'", r"\'").replace('"', r'\"')
|
||||
|
||||
|
||||
def escape_html(text):
|
||||
"""Convert some problematic characters to entities"""
|
||||
html_escape_table = {
|
||||
"&": "&",
|
||||
'"': """,
|
||||
"'": "'",
|
||||
">": ">",
|
||||
"<": "<",
|
||||
}
|
||||
return "".join(html_escape_table.get(c, c) for c in text)
|
||||
|
||||
|
||||
def escapeAndQuoteCommonFields(item):
|
||||
'''Adds _escaped and _quoted versions of several commonly-used fields'''
|
||||
item['name_escaped'] = escape_html(item['name'])
|
||||
item['name_quoted'] = escape_html(escape_quotes(item['name']))
|
||||
item['display_name_escaped'] = escape_html(item['display_name'])
|
||||
item['developer_escaped'] = escape_html(item['developer'])
|
||||
item['display_version_escaped'] = escape_html(item['display_version'])
|
||||
|
||||
|
||||
def addGeneralLabels(page):
|
||||
'''adds localized labels for Software, Categories, My Items and Updates to html pages'''
|
||||
page['SoftwareLabel'] = NSLocalizedString(u"Software", u"Software label")
|
||||
@@ -172,7 +198,9 @@ def build_detail_page(item_name):
|
||||
page_name = u'detail-%s.html' % item_name
|
||||
for item in items:
|
||||
if item['name'] == item_name:
|
||||
# make a copy of the item to use to build our page
|
||||
page = MunkiItems.OptionalItem(item)
|
||||
escapeAndQuoteCommonFields(page)
|
||||
addDetailSidebarLabels(page)
|
||||
# make "More in CategoryFoo" list
|
||||
page['hide_more_in_category'] = u'hidden'
|
||||
@@ -191,6 +219,7 @@ def build_detail_page(item_name):
|
||||
shuffle(more_in_category)
|
||||
more_template = get_template('detail_more_items_template.html')
|
||||
for more_item in more_in_category[:4]:
|
||||
more_item['display_name_escaped'] = escape_html(more_item['display_name'])
|
||||
more_item['second_line'] = more_item.get('developer', '')
|
||||
more_in_category_html += more_template.safe_substitute(more_item)
|
||||
page['more_in_category'] = more_in_category_html
|
||||
@@ -214,6 +243,7 @@ def build_detail_page(item_name):
|
||||
more_template = get_template(
|
||||
'detail_more_items_template.html')
|
||||
for more_item in more_by_developer[:4]:
|
||||
escapeAndQuoteCommonFields(more_item)
|
||||
more_item['second_line'] = more_item.get('category', '')
|
||||
more_by_developer_html += more_template.safe_substitute(more_item)
|
||||
page['more_by_developer'] = more_by_developer_html
|
||||
@@ -310,6 +340,8 @@ def build_list_page_items_html(category=None, developer=None, filter=None):
|
||||
if items:
|
||||
item_template = get_template('list_item_template.html')
|
||||
for item in sorted(items, key=itemgetter('display_name_lower')):
|
||||
escapeAndQuoteCommonFields(item)
|
||||
item['category_and_developer_escaped'] = escape_html(item['category_and_developer'])
|
||||
item_html += item_template.safe_substitute(item)
|
||||
# pad with extra empty items so we have a multiple of 3
|
||||
if len(items) % 3:
|
||||
@@ -391,24 +423,27 @@ def build_category_items_html():
|
||||
item_html = u''
|
||||
for category in sorted(category_list):
|
||||
category_data = {}
|
||||
category_data['category_name'] = category
|
||||
category_data['category_name_escaped'] = escape_html(category)
|
||||
category_data['category_link'] = u'category-%s.html' % quote(category)
|
||||
category_items = [item for item in all_items if item.get('category') == category]
|
||||
shuffle(category_items)
|
||||
category_data['item1_icon'] = category_items[0]['icon']
|
||||
category_data['item1_display_name'] = category_items[0]['display_name']
|
||||
category_data['item1_display_name_escaped'] = escape_html(
|
||||
category_items[0]['display_name'])
|
||||
category_data['item1_detail_link'] = category_items[0]['detail_link']
|
||||
if len(category_items) > 1:
|
||||
category_data['item2_display_name'] = category_items[1]['display_name']
|
||||
category_data['item2_display_name_escaped'] = escape_html(
|
||||
category_items[1]['display_name'])
|
||||
category_data['item2_detail_link'] = category_items[1]['detail_link']
|
||||
else:
|
||||
category_data['item2_display_name'] = u''
|
||||
category_data['item2_display_name_escaped'] = u''
|
||||
category_data['item2_detail_link'] = u'#'
|
||||
if len(category_items) > 2:
|
||||
category_data['item3_display_name'] = category_items[2]['display_name']
|
||||
category_data['item3_display_name_escaped'] = escape_html(
|
||||
category_items[2]['display_name'])
|
||||
category_data['item3_detail_link'] = category_items[2]['detail_link']
|
||||
else:
|
||||
category_data['item3_display_name'] = u''
|
||||
category_data['item3_display_name_escaped'] = u''
|
||||
category_data['item3_detail_link'] = u'#'
|
||||
|
||||
item_html += item_template.safe_substitute(category_data)
|
||||
@@ -454,6 +489,7 @@ def build_myitems_rows():
|
||||
item_template = get_template('myitems_row_template.html')
|
||||
myitems_rows = u''
|
||||
for item in sorted(item_list, key=itemgetter('display_name_lower')):
|
||||
escapeAndQuoteCommonFields(item)
|
||||
myitems_rows += item_template.safe_substitute(item)
|
||||
else:
|
||||
status_results_template = get_template('status_results_template.html')
|
||||
@@ -494,6 +530,7 @@ def build_updates_page():
|
||||
|
||||
if item_list:
|
||||
for item in item_list:
|
||||
escapeAndQuoteCommonFields(item)
|
||||
page['update_rows'] += item_template.safe_substitute(item)
|
||||
elif not other_updates:
|
||||
status_results_template = get_template('status_results_template.html')
|
||||
@@ -615,8 +652,9 @@ def build_updatedetail_page(identifier):
|
||||
page_name = u'updatedetail-%s.html' % identifier
|
||||
name, sep, version = identifier.partition('--version-')
|
||||
for item in items:
|
||||
if item['name'] == name and item['version_to_install'] == version:
|
||||
if item['name'] == name and item.get('version_to_install', '') == version:
|
||||
page = MunkiItems.UpdateItem(item)
|
||||
escapeAndQuoteCommonFields(page)
|
||||
addDetailSidebarLabels(page)
|
||||
force_install_after_date = item.get('force_install_after_date')
|
||||
if force_install_after_date:
|
||||
|
||||
+4
-4
@@ -5,9 +5,9 @@
|
||||
</div>
|
||||
</a>
|
||||
<ul class="list">
|
||||
<li class="name"><a href="${category_link}">${category_name}</a></li>
|
||||
<li class="genre"><a href="${item1_detail_link}">${item1_display_name}</a></li>
|
||||
<li class="genre"><a href="${item2_detail_link}">${item2_display_name}</a></li>
|
||||
<li class="genre"><a href="${item3_detail_link}">${item3_display_name}</a></li>
|
||||
<li class="name"><a href="${category_link}">${category_name_escaped}</a></li>
|
||||
<li class="genre"><a href="${item1_detail_link}">${item1_display_name_escaped}</a></li>
|
||||
<li class="genre"><a href="${item2_detail_link}">${item2_display_name_escaped}</a></li>
|
||||
<li class="genre"><a href="${item3_detail_link}">${item3_display_name_escaped}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
<div class="lockup small detailed option application mac-application">
|
||||
<a href="${detail_link}" class="artwork-link">
|
||||
<div class="artwork">
|
||||
<img width="75" height="75" alt="${display_name}" class="artwork" src="${icon}" />
|
||||
<img width="75" height="75" alt="${display_name_escaped}" class="artwork" src="${icon}" />
|
||||
</div>
|
||||
</a>
|
||||
<ul class="list">
|
||||
<li class="name">
|
||||
<a href="${detail_link}">${display_name}</a>
|
||||
<a href="${detail_link}">${display_name_escaped}</a>
|
||||
</li>
|
||||
<li class="genre">${second_line}</li>
|
||||
</ul>
|
||||
|
||||
+8
-8
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>${display_name}</title>
|
||||
<title>${display_name_escaped}</title>
|
||||
|
||||
<link charset="utf-8" rel="stylesheet" type="text/css" href="static/base.css" />
|
||||
<link charset="utf-8" rel="stylesheet" type="text/css" href="static/detail.css" />
|
||||
@@ -19,13 +19,13 @@
|
||||
<div class="product-detail">
|
||||
<div class="lockup product">
|
||||
<div class="artwork">
|
||||
<img width="175" height="175" alt="${display_name}" class="artwork" src="${icon}" />
|
||||
<img width="175" height="175" alt="${display_name_escaped}" class="artwork" src="${icon}" />
|
||||
</div>
|
||||
<div class="msc-button large">
|
||||
<button class="button-area uppercase"
|
||||
onClick="window.AppController.actionButtonClicked_('${name}');">
|
||||
onClick="window.AppController.actionButtonClicked_('${name_quoted}');">
|
||||
<div class="msc-button-inner large ${status}"
|
||||
id="${name}_action_button_text">
|
||||
id="${name_escaped}_action_button_text">
|
||||
${long_action_text}
|
||||
</div>
|
||||
</button>
|
||||
@@ -39,7 +39,7 @@
|
||||
<div class="product-info box-flex">
|
||||
<div class="product-review">
|
||||
<div class="title">
|
||||
<h1>${display_name}</h1>
|
||||
<h1>${display_name_escaped}</h1>
|
||||
</div>
|
||||
<p class="more-text">
|
||||
${description}
|
||||
@@ -63,15 +63,15 @@
|
||||
<li><span class="label">${sizeLabel} </span>${size}</li>
|
||||
<li>
|
||||
<span class="label">${developerLabel} </span>
|
||||
<a href="${developer_link}">${developer}</a>
|
||||
<a href="${developer_link}">${developer_escaped}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<ul class="list">
|
||||
<li>
|
||||
<span class="label">${statusLabel} </span>
|
||||
<span class="${status}" id="${name}_status_text">
|
||||
<span id="${name}_status_text_span">
|
||||
<span class="${status}" id="${name_escaped}_status_text">
|
||||
<span id="${name_escaped}_status_text_span">
|
||||
${status_text}
|
||||
</span>
|
||||
<a class="follow" href="updates.html"></a>
|
||||
|
||||
+7
-7
@@ -1,19 +1,19 @@
|
||||
<tr class="installation" id="${name}_myitems_table_row">
|
||||
<tr class="installation" id="${name_escaped}_myitems_table_row">
|
||||
<td>
|
||||
<a href="${detail_link}" class="artwork-link">
|
||||
<div class="artwork">
|
||||
<img width="75" height="75" alt="${display_name}" class="artwork" src="${icon}" />
|
||||
<img width="75" height="75" alt="${display_name_escaped}" class="artwork" src="${icon}" />
|
||||
</div>
|
||||
</a>
|
||||
<ul class="list info">
|
||||
<li><h2><a title="${display_name}" href="${detail_link}">${display_name}</a></h2></li>
|
||||
<li>${developer}</li>
|
||||
<li><h2><a title="${display_name_escaped}" href="${detail_link}">${display_name_escaped}</a></h2></li>
|
||||
<li>${developer_escaped}</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>${version_to_install}</td>
|
||||
<td>${size}</td>
|
||||
<td class="status">
|
||||
<span class="${status}" id="${name}_status_text">
|
||||
<span class="${status}" id="${name_escaped}_status_text">
|
||||
${status_text}
|
||||
<a class="follow" href="updates.html">
|
||||
</span>
|
||||
@@ -21,9 +21,9 @@
|
||||
<td>
|
||||
<div class="msc-button install-updates">
|
||||
<button class="button-area uppercase"
|
||||
onClick="window.AppController.myItemsActionButtonClicked_('${name}');">
|
||||
onClick="window.AppController.myItemsActionButtonClicked_('${name_quoted}');">
|
||||
<div class="msc-button-inner install-updates ${status}"
|
||||
id="${name}_action_button_text">
|
||||
id="${name_escaped}_action_button_text">
|
||||
${myitem_action_text}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
+6
-6
@@ -1,14 +1,14 @@
|
||||
<tr class='installation ${added_or_deleted}' id="${name}_update_table_row">
|
||||
<tr class='installation ${added_or_deleted}' id="${name_escaped}_update_table_row">
|
||||
<td>
|
||||
<a href="${detail_link}" class="artwork-link">
|
||||
<div class="artwork">
|
||||
<img width="75" height="75" alt="${display_name}" class="artwork" src="${icon}">
|
||||
<img width="75" height="75" alt="${display_name_escaped}" class="artwork" src="${icon}">
|
||||
</div>
|
||||
</a>
|
||||
<ul class="list info">
|
||||
<li><h2><a title="${display_name}" href="${detail_link}">${display_name}</a></h2></li>
|
||||
<li>${developer}</li>
|
||||
<li>${version_label} ${display_version}</li>
|
||||
<li><h2><a title="${display_name_escaped}" href="${detail_link}">${display_name_escaped}</a></h2></li>
|
||||
<li>${developer_escaped}</li>
|
||||
<li>${version_label} ${display_version_escaped}</li>
|
||||
<li class="warning">${restart_action_text}</li>
|
||||
</ul>
|
||||
</td>
|
||||
@@ -20,6 +20,6 @@
|
||||
</td>
|
||||
<td class="${hide_cancel_button}">
|
||||
<button title="${long_action_text}" class="cancel-or-add" aria-label="${long_action_text}"
|
||||
onClick="fadeOutAndRemove('${name}');"></button>
|
||||
onClick="fadeOutAndRemove('${name_quoted}');"></button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
+5
-5
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>${display_name}</title>
|
||||
<title>${display_name_escaped}</title>
|
||||
|
||||
<link charset="utf-8" rel="stylesheet" type="text/css" href="static/base.css" />
|
||||
<link charset="utf-8" rel="stylesheet" type="text/css" href="static/detail.css" />
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="lockup product">
|
||||
<!--<a href="#">-->
|
||||
<div class="artwork">
|
||||
<img width="175" height="175" alt="${display_name}" class="artwork" src="${icon}" />
|
||||
<img width="175" height="175" alt="${display_name_escaped}" class="artwork" src="${icon}" />
|
||||
</div>
|
||||
<!--</a>-->
|
||||
<div class="warning">
|
||||
@@ -32,7 +32,7 @@
|
||||
<div class="product-info box-flex">
|
||||
<div class="product-review">
|
||||
<div class="title">
|
||||
<h1>${display_name}</h1>
|
||||
<h1>${display_name_escaped}</h1>
|
||||
</div>
|
||||
<p class="more-text">
|
||||
${description}
|
||||
@@ -48,9 +48,9 @@
|
||||
<div class="content">
|
||||
<ul class="list">
|
||||
<li><span class="label">${typeLabel} </span>${type}</li>
|
||||
<li><span class="label">${versionLabel} </span>${display_version}</li>
|
||||
<li><span class="label">${versionLabel} </span>${display_version_escaped}</li>
|
||||
<li><span class="label">${sizeLabel} </span>${size}</li>
|
||||
<li><span class="label">${developerLabel} </span>${developer}</li>
|
||||
<li><span class="label">${developerLabel} </span>${developer_escaped}</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<ul class="list">
|
||||
|
||||
Reference in New Issue
Block a user