mirror of
https://github.com/django-helpdesk/django-helpdesk.git
synced 2025-05-20 17:30:46 +02:00
* 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:
parent
ce24e50a2b
commit
738a88a5aa
@ -133,6 +133,8 @@ def ticket_from_message(message, queue):
|
|||||||
|
|
||||||
sender_email = parseaddr(sender)[1]
|
sender_email = parseaddr(sender)[1]
|
||||||
|
|
||||||
|
body_plain, body_html = '', ''
|
||||||
|
|
||||||
for ignore in IgnoreEmail.objects.filter(Q(queues=queue) | Q(queues__isnull=True)):
|
for ignore in IgnoreEmail.objects.filter(Q(queues=queue) | Q(queues__isnull=True)):
|
||||||
if ignore.test(sender_email):
|
if ignore.test(sender_email):
|
||||||
return False
|
return False
|
||||||
@ -154,8 +156,10 @@ def ticket_from_message(message, queue):
|
|||||||
name = part.get_param("name")
|
name = part.get_param("name")
|
||||||
|
|
||||||
if part.get_content_maintype() == 'text' and name == None:
|
if part.get_content_maintype() == 'text' and name == None:
|
||||||
body = part.get_payload(decode=True)
|
if part.get_content_subtype() == 'plain':
|
||||||
body = decodeUnknown(part.get_charset(), body)
|
body_plain = decodeUnknown(part.get_charset(), part.get_payload(decode=True))
|
||||||
|
else:
|
||||||
|
body_html = decodeUnknown(part.get_charset(), part.get_payload(decode=True))
|
||||||
else:
|
else:
|
||||||
if not name:
|
if not name:
|
||||||
ext = mimetypes.guess_extension(part.get_content_type())
|
ext = mimetypes.guess_extension(part.get_content_type())
|
||||||
@ -169,6 +173,18 @@ def ticket_from_message(message, queue):
|
|||||||
|
|
||||||
counter += 1
|
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()
|
now = datetime.now()
|
||||||
|
|
||||||
if ticket:
|
if ticket:
|
||||||
|
@ -2,15 +2,6 @@
|
|||||||
|
|
||||||
{% block helpdesk_title %}{% trans "Create Ticket" %}{% endblock %}
|
{% 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 %}
|
{% block helpdesk_body %}
|
||||||
{% blocktrans %}<h2>Submit a Ticket</h2>
|
{% blocktrans %}<h2>Submit a Ticket</h2>
|
||||||
|
|
||||||
|
@ -1,14 +1,5 @@
|
|||||||
{% extends "helpdesk/public_base.html" %}{% load i18n %}
|
{% 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 %}
|
{% block helpdesk_body %}
|
||||||
<h2>{% trans "View a Ticket" %}</h2>
|
<h2>{% trans "View a Ticket" %}</h2>
|
||||||
|
|
||||||
|
@ -1,13 +1,5 @@
|
|||||||
{% extends "helpdesk/public_base.html" %}{% load i18n %}
|
{% extends "helpdesk/public_base.html" %}{% load i18n %}
|
||||||
{% block helpdesk_title %}{% trans "View a Ticket" %}{% endblock %}
|
{% 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 %}
|
{% block helpdesk_body %}
|
||||||
|
|
||||||
@ -34,7 +26,7 @@
|
|||||||
<th colspan='2'>{% trans "Description" %}</th>
|
<th colspan='2'>{% trans "Description" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class='row_odd'>
|
<tr class='row_odd'>
|
||||||
<td colspan='2'>{{ ticket.description }}</td>
|
<td colspan='2'>{{ ticket.description|linebreaksbr }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% if ticket.resolution %}<tr class='row_even'>
|
{% if ticket.resolution %}<tr class='row_even'>
|
||||||
@ -52,7 +44,7 @@
|
|||||||
{% for followup in ticket.followup_set.public_followups %}
|
{% for followup in ticket.followup_set.public_followups %}
|
||||||
<div class='followup'>
|
<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>
|
<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>
|
{% if followup.ticketchange_set.all %}<div class='changes'><ul>
|
||||||
{% for change in followup.ticketchange_set.all %}
|
{% for change in followup.ticketchange_set.all %}
|
||||||
<li>{% blocktrans %}Changed {{ change.field }} from {{ change.old_value }} to {{ change.new_value }}.{% endblocktrans %}</li>
|
<li>{% blocktrans %}Changed {{ change.field }} from {{ change.old_value }} to {{ change.new_value }}.{% endblocktrans %}</li>
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
{% extends "helpdesk/base.html" %}{% load i18n %}
|
{% extends "helpdesk/base.html" %}{% load i18n %}
|
||||||
{% block helpdesk_title %}{% trans "View Ticket Details" %}{% endblock %}
|
{% block helpdesk_title %}{% trans "View Ticket Details" %}{% endblock %}
|
||||||
{% block helpdesk_head %}
|
{% block helpdesk_head %}
|
||||||
<script src="{{ MEDIA_URL }}helpdesk/nicEdit.js" type="text/javascript"></script>
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
nic = new nicEditor({buttonList: ['bold','italic','underline','strikeThrough','undo','redo','subscript','superscript','html']}).panelInstance('commentBox');
|
|
||||||
$("#ShowFurtherEditOptions").click(function() {
|
$("#ShowFurtherEditOptions").click(function() {
|
||||||
$("#FurtherEditOptions").fadeIn();
|
$("#FurtherEditOptions").fadeIn();
|
||||||
$("#ShowFurtherOptPara").hide();
|
$("#ShowFurtherOptPara").hide();
|
||||||
@ -22,7 +20,7 @@
|
|||||||
preset = $('#id_preset').val();
|
preset = $('#id_preset').val();
|
||||||
if (preset != '') {
|
if (preset != '') {
|
||||||
$.get("{% url helpdesk_raw "preset" %}?id=" + preset, function(data) {
|
$.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>
|
<th colspan='2'>{% trans "Description" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class='row_even'>
|
<tr class='row_even'>
|
||||||
<td colspan='2'>{{ ticket.description|safe }}</td>
|
<td colspan='2'>{{ ticket.description|force_escape|linebreaksbr }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% if ticket.resolution %}<tr class='row_odd'>
|
{% 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>
|
<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>
|
||||||
<tr class='row_even'>
|
<tr class='row_even'>
|
||||||
<td colspan='2'>{{ ticket.resolution|safe }}</td>
|
<td colspan='2'>{{ ticket.resolution|force_escape }}</td>
|
||||||
</tr>{% endif %}
|
</tr>{% endif %}
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
@ -90,7 +88,7 @@
|
|||||||
{% for followup in ticket.followup_set.all %}
|
{% for followup in ticket.followup_set.all %}
|
||||||
<div class='followup'>
|
<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>
|
<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 %}
|
{% for change in followup.ticketchange_set.all %}
|
||||||
{% if forloop.first %}<div class='changes'><ul>{% endif %}
|
{% 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>
|
<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>
|
||||||
|
Loading…
Reference in New Issue
Block a user