* Fix an XSS hole: No user-sourced HTML is displayed at all. Descriptions, resolutions and followup comments are treated as text using force_escape and linebreaksbr template filters. (Issue #39)

* Incoming email also handled slightly differently: If an email has both HTML and Plain-text parts, the plain text is used in the ticket description and/or followup comment fields. The HTML portion is attached as 'email_html_body.html' so it can be viewed by the user. If an HTML-only email is received, the body is entered as "View attachment for body". (Issue #39)
This commit is contained in:
Ross Poulton 2009-01-19 09:40:14 +00:00
parent ce24e50a2b
commit 738a88a5aa
5 changed files with 24 additions and 36 deletions

View File

@ -133,6 +133,8 @@ def ticket_from_message(message, queue):
sender_email = parseaddr(sender)[1]
body_plain, body_html = '', ''
for ignore in IgnoreEmail.objects.filter(Q(queues=queue) | Q(queues__isnull=True)):
if ignore.test(sender_email):
return False
@ -154,8 +156,10 @@ def ticket_from_message(message, queue):
name = part.get_param("name")
if part.get_content_maintype() == 'text' and name == None:
body = part.get_payload(decode=True)
body = decodeUnknown(part.get_charset(), body)
if part.get_content_subtype() == 'plain':
body_plain = decodeUnknown(part.get_charset(), part.get_payload(decode=True))
else:
body_html = decodeUnknown(part.get_charset(), part.get_payload(decode=True))
else:
if not name:
ext = mimetypes.guess_extension(part.get_content_type())
@ -169,6 +173,18 @@ def ticket_from_message(message, queue):
counter += 1
if body_plain:
body = body_plain
else:
body = _('No plain-text email body available. Please see attachment email_html_body.html.')
if body_html:
files.append({
'filename': _("email_html_body.html"),
'content': body_html,
'type': 'text/html',
})
now = datetime.now()
if ticket:

View File

@ -2,15 +2,6 @@
{% block helpdesk_title %}{% trans "Create Ticket" %}{% endblock %}
{% block helpdesk_head %}
<script src="{{ MEDIA_URL }}helpdesk/nicEdit.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
nic = new nicEditor({buttonList: ['bold','italic','underline','strikeThrough','undo','redo','subscript','superscript','html']}).panelInstance('id_body');
});
</script>
{% endblock %}
{% block helpdesk_body %}
{% blocktrans %}<h2>Submit a Ticket</h2>

View File

@ -1,14 +1,5 @@
{% extends "helpdesk/public_base.html" %}{% load i18n %}
{% block helpdesk_head %}
<script src="{{ MEDIA_URL }}helpdesk/nicEdit.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
nic = new nicEditor({buttonList: ['bold','italic','underline','strikeThrough','undo','redo','subscript','superscript','html']}).panelInstance('id_body');
});
</script>
{% endblock %}
{% block helpdesk_body %}
<h2>{% trans "View a Ticket" %}</h2>

View File

@ -1,13 +1,5 @@
{% extends "helpdesk/public_base.html" %}{% load i18n %}
{% block helpdesk_title %}{% trans "View a Ticket" %}{% endblock %}
{% block helpdesk_head %}
<script src="{{ MEDIA_URL }}helpdesk/nicEdit.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
nic = new nicEditor({buttonList: ['bold','italic','underline','strikeThrough','undo','redo','subscript','superscript','html']}).panelInstance('commentBox');
});
</script>
{% endblock %}
{% block helpdesk_body %}
@ -34,7 +26,7 @@
<th colspan='2'>{% trans "Description" %}</th>
</tr>
<tr class='row_odd'>
<td colspan='2'>{{ ticket.description }}</td>
<td colspan='2'>{{ ticket.description|linebreaksbr }}</td>
</tr>
{% if ticket.resolution %}<tr class='row_even'>
@ -52,7 +44,7 @@
{% for followup in ticket.followup_set.public_followups %}
<div class='followup'>
<div class='title'>{{ followup.title }} <span class='byline'>{% if followup.user %}by {{ followup.user }}{% endif %} <span title='{{ followup.date|date:"r" }}'>{{ followup.date|timesince }} ago</span></span></div>
{{ followup.comment|num_to_link }}
{{ followup.comment|force_escape|num_to_link|linebreaksbr }}
{% if followup.ticketchange_set.all %}<div class='changes'><ul>
{% for change in followup.ticketchange_set.all %}
<li>{% blocktrans %}Changed {{ change.field }} from {{ change.old_value }} to {{ change.new_value }}.{% endblocktrans %}</li>

View File

@ -1,10 +1,8 @@
{% extends "helpdesk/base.html" %}{% load i18n %}
{% block helpdesk_title %}{% trans "View Ticket Details" %}{% endblock %}
{% block helpdesk_head %}
<script src="{{ MEDIA_URL }}helpdesk/nicEdit.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
nic = new nicEditor({buttonList: ['bold','italic','underline','strikeThrough','undo','redo','subscript','superscript','html']}).panelInstance('commentBox');
$("#ShowFurtherEditOptions").click(function() {
$("#FurtherEditOptions").fadeIn();
$("#ShowFurtherOptPara").hide();
@ -22,7 +20,7 @@
preset = $('#id_preset').val();
if (preset != '') {
$.get("{% url helpdesk_raw "preset" %}?id=" + preset, function(data) {
nic.nicInstances[0].setContent(data);
$("#commentBox").value(data)
});
}
});
@ -72,14 +70,14 @@
<th colspan='2'>{% trans "Description" %}</th>
</tr>
<tr class='row_even'>
<td colspan='2'>{{ ticket.description|safe }}</td>
<td colspan='2'>{{ ticket.description|force_escape|linebreaksbr }}</td>
</tr>
{% if ticket.resolution %}<tr class='row_odd'>
<th colspan='2'>{% trans "Resolution" %}{% ifequal ticket.get_status_display "Resolved" %} <a href='?close'><img src='{{ MEDIA_URL }}helpdesk/buttons/accept.png' alt='{% trans "Accept" %}' title='{% trans "Accept and Close" %}' width='60' height='15' /></a>{% endifequal %}</th>
</tr>
<tr class='row_even'>
<td colspan='2'>{{ ticket.resolution|safe }}</td>
<td colspan='2'>{{ ticket.resolution|force_escape }}</td>
</tr>{% endif %}
</table>
@ -90,7 +88,7 @@
{% for followup in ticket.followup_set.all %}
<div class='followup'>
<div class='title'>{{ followup.title }} <span class='byline'>{% if followup.user %}by {{ followup.user }}{% endif %} <span title='{{ followup.date|date:"r" }}'>{{ followup.date|timesince }} ago</span>{% if not followup.public %} <span class='private'>({% trans "Private" %})</span>{% endif %}</span></div>
{% if followup.comment %}{{ followup.comment|num_to_link|safe }}{% endif %}
{% if followup.comment %}{{ followup.comment|force_escape|num_to_link|linebreaksbr }}{% endif %}
{% for change in followup.ticketchange_set.all %}
{% if forloop.first %}<div class='changes'><ul>{% endif %}
<li>{% blocktrans with change.field as field and change.old_value as old_value and change.new_value as new_value %}Changed {{ field }} from {{ old_value }} to {{ new_value }}.{% endblocktrans %}</li>