Commit 7cdfe2ea by Kevin Falcone

Merge pull request #9350 from edx/jibshet/escape-studio-courses

HTML-escape uses of course display name.
parents 91ea3260 c13f2961
...@@ -36,7 +36,8 @@ from xmodule.modulestore.exceptions import ItemNotFoundError ...@@ -36,7 +36,8 @@ from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.inheritance import own_metadata from xmodule.modulestore.inheritance import own_metadata
from opaque_keys.edx.keys import UsageKey, CourseKey from opaque_keys.edx.keys import UsageKey, CourseKey
from opaque_keys.edx.locations import AssetLocation, CourseLocator from opaque_keys.edx.locations import AssetLocation, CourseLocator
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, LibraryFactory, check_mongo_calls
from xmodule.modulestore.tests.utils import XssTestMixin
from xmodule.modulestore.xml_exporter import export_course_to_xml from xmodule.modulestore.xml_exporter import export_course_to_xml
from xmodule.modulestore.xml_importer import import_course_from_xml, perform_xlint from xmodule.modulestore.xml_importer import import_course_from_xml, perform_xlint
...@@ -1115,7 +1116,7 @@ class MiscCourseTests(ContentStoreTestCase): ...@@ -1115,7 +1116,7 @@ class MiscCourseTests(ContentStoreTestCase):
@ddt.ddt @ddt.ddt
class ContentStoreTest(ContentStoreTestCase): class ContentStoreTest(ContentStoreTestCase, XssTestMixin):
""" """
Tests for the CMS ContentStore application. Tests for the CMS ContentStore application.
""" """
...@@ -1405,6 +1406,22 @@ class ContentStoreTest(ContentStoreTestCase): ...@@ -1405,6 +1406,22 @@ class ContentStoreTest(ContentStoreTestCase):
html=True html=True
) )
def test_course_index_view_xss(self):
"""Test that the index page correctly escapes course names with script
tags."""
CourseFactory.create(
display_name='<script>alert("course XSS")</script>'
)
LibraryFactory.create(display_name='<script>alert("library XSS")</script>')
resp = self.client.get_html('/home/')
for xss in ('course', 'library'):
html = '<script>alert("{name} XSS")</script>'.format(
name=xss
)
self.assert_xss(resp, html)
def test_course_overview_view_with_course(self): def test_course_overview_view_with_course(self):
"""Test viewing the course overview page with an existing course""" """Test viewing the course overview page with an existing course"""
course = CourseFactory.create() course = CourseFactory.create()
......
...@@ -40,7 +40,7 @@ from django.template.defaultfilters import escapejs ...@@ -40,7 +40,7 @@ from django.template.defaultfilters import escapejs
<h2 class="page-header-super course-original"> <h2 class="page-header-super course-original">
<span class="sr">${_("You are creating a re-run from:")}</span> <span class="sr">${_("You are creating a re-run from:")}</span>
<span class="course-original-title-id">${source_course_key.org | h} ${source_course_key.course | h} ${source_course_key.run | h}</span> <span class="course-original-title-id">${source_course_key.org | h} ${source_course_key.course | h} ${source_course_key.run | h}</span>
<span class="course-original-title">${display_name}</span> <span class="course-original-title">${display_name | h}</span>
</h2> </h2>
</header> </header>
</div> </div>
...@@ -73,7 +73,7 @@ from django.template.defaultfilters import escapejs ...@@ -73,7 +73,7 @@ from django.template.defaultfilters import escapejs
<ol class="list-input"> <ol class="list-input">
<li class="field text required" id="field-course-name"> <li class="field text required" id="field-course-name">
<label for="rerun-course-name">${_("Course Name")}</label> <label for="rerun-course-name">${_("Course Name")}</label>
<input class="rerun-course-name" id="rerun-course-name" type="text" name="rerun-course-name" aria-required="true" value="${display_name}" placeholder="${_('e.g. Introduction to Computer Science')}" /> <input class="rerun-course-name" id="rerun-course-name" type="text" name="rerun-course-name" aria-required="true" value="${display_name | h}" placeholder="${_('e.g. Introduction to Computer Science')}" />
<span class="tip"> <span class="tip">
${_("The public display name for the new course. (This name is often the same as the original course name.)")} ${_("The public display name for the new course. (This name is often the same as the original course name.)")}
</span> </span>
......
...@@ -168,7 +168,7 @@ ...@@ -168,7 +168,7 @@
<li class="wrapper-course has-status" data-course-key="${course_info['course_key'] | h}"> <li class="wrapper-course has-status" data-course-key="${course_info['course_key'] | h}">
<div class="course-item course-rerun is-processing"> <div class="course-item course-rerun is-processing">
<div class="course-details" href="#"> <div class="course-details" href="#">
<h3 class="course-title">${course_info['display_name']}</h3> <h3 class="course-title">${course_info['display_name'] | h}</h3>
<div class="course-metadata"> <div class="course-metadata">
<span class="course-org metadata-item"> <span class="course-org metadata-item">
...@@ -210,7 +210,7 @@ ...@@ -210,7 +210,7 @@
<li class="wrapper-course has-status" data-course-key="${course_info['course_key'] | h}"> <li class="wrapper-course has-status" data-course-key="${course_info['course_key'] | h}">
<div class="course-item course-rerun has-error"> <div class="course-item course-rerun has-error">
<div class="course-details" href="#"> <div class="course-details" href="#">
<h3 class="course-title">${course_info['display_name']}</h3> <h3 class="course-title">${course_info['display_name'] | h}</h3>
<div class="course-metadata"> <div class="course-metadata">
<span class="course-org metadata-item"> <span class="course-org metadata-item">
...@@ -267,7 +267,7 @@ ...@@ -267,7 +267,7 @@
%for course_info in sorted(courses, key=lambda s: s['display_name'].lower() if s['display_name'] is not None else ''): %for course_info in sorted(courses, key=lambda s: s['display_name'].lower() if s['display_name'] is not None else ''):
<li class="course-item" data-course-key="${course_info['course_key'] | h}"> <li class="course-item" data-course-key="${course_info['course_key'] | h}">
<a class="course-link" href="${course_info['url']}"> <a class="course-link" href="${course_info['url']}">
<h3 class="course-title">${course_info['display_name']}</h3> <h3 class="course-title">${course_info['display_name'] | h}</h3>
<div class="course-metadata"> <div class="course-metadata">
<span class="course-org metadata-item"> <span class="course-org metadata-item">
...@@ -419,7 +419,7 @@ ...@@ -419,7 +419,7 @@
%for library_info in sorted(libraries, key=lambda s: s['display_name'].lower() if s['display_name'] is not None else ''): %for library_info in sorted(libraries, key=lambda s: s['display_name'].lower() if s['display_name'] is not None else ''):
<li class="course-item"> <li class="course-item">
<a class="library-link" href="${library_info['url']}"> <a class="library-link" href="${library_info['url']}">
<h3 class="course-title">${library_info['display_name']}</h3> <h3 class="course-title">${library_info['display_name'] | h}</h3>
<div class="course-metadata"> <div class="course-metadata">
<span class="course-org metadata-item"> <span class="course-org metadata-item">
......
...@@ -46,7 +46,7 @@ from django.utils.translation import ugettext as _ ...@@ -46,7 +46,7 @@ from django.utils.translation import ugettext as _
<small class="subtitle">${_("Content Library")}</small> <small class="subtitle">${_("Content Library")}</small>
<div class="wrapper-xblock-field incontext-editor is-editable" <div class="wrapper-xblock-field incontext-editor is-editable"
data-field="display_name" data-field-display-name="${_("Display Name")}"> data-field="display_name" data-field-display-name="${_("Display Name")}">
<h1 class="page-header-title xblock-field-value incontext-editor-value"><span class="title-value">${context_library.display_name_with_default | h}</span></h1> <h1 class="page-header-title xblock-field-value incontext-editor-value"><span class="title-value">${context_library.display_name_with_default}</span></h1>
</div> </div>
</div> </div>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
Helper classes and methods for running modulestore tests without Django. Helper classes and methods for running modulestore tests without Django.
""" """
from importlib import import_module from importlib import import_module
from markupsafe import escape
from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.keys import UsageKey
from unittest import TestCase from unittest import TestCase
from xblock.fields import XBlockMixin from xblock.fields import XBlockMixin
...@@ -174,3 +175,25 @@ class ProceduralCourseTestMixin(object): ...@@ -174,3 +175,25 @@ class ProceduralCourseTestMixin(object):
with self.store.bulk_operations(self.course.id, emit_signals=emit_signals): with self.store.bulk_operations(self.course.id, emit_signals=emit_signals):
descend(self.course, ['chapter', 'sequential', 'vertical', 'problem']) descend(self.course, ['chapter', 'sequential', 'vertical', 'problem'])
class XssTestMixin(object):
"""
Mixin for testing XSS vulnerabilities.
"""
def assert_xss(self, response, xss_content):
"""Assert that `xss_content` is not present in the content of
`response`, and that its escaped version is present. Uses the
same `markupsafe.escape` function as Mako templates.
Args:
response (Response): The HTTP response
xss_content (str): The Javascript code to check for.
Returns:
None
"""
self.assertContains(response, escape(xss_content))
self.assertNotContains(response, xss_content)
...@@ -11,11 +11,12 @@ from survey.models import SurveyForm ...@@ -11,11 +11,12 @@ from survey.models import SurveyForm
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.utils import XssTestMixin
from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tests.helpers import LoginEnrollmentTestCase
@attr('shard_1') @attr('shard_1')
class SurveyViewsTests(LoginEnrollmentTestCase, ModuleStoreTestCase): class SurveyViewsTests(LoginEnrollmentTestCase, ModuleStoreTestCase, XssTestMixin):
""" """
All tests for the views.py file All tests for the views.py file
""" """
...@@ -39,6 +40,7 @@ class SurveyViewsTests(LoginEnrollmentTestCase, ModuleStoreTestCase): ...@@ -39,6 +40,7 @@ class SurveyViewsTests(LoginEnrollmentTestCase, ModuleStoreTestCase):
}) })
self.course = CourseFactory.create( self.course = CourseFactory.create(
display_name='<script>alert("XSS")</script>',
course_survey_required=True, course_survey_required=True,
course_survey_name=self.test_survey_name course_survey_name=self.test_survey_name
) )
...@@ -172,3 +174,13 @@ class SurveyViewsTests(LoginEnrollmentTestCase, ModuleStoreTestCase): ...@@ -172,3 +174,13 @@ class SurveyViewsTests(LoginEnrollmentTestCase, ModuleStoreTestCase):
resp, resp,
reverse('info', kwargs={'course_id': unicode(self.course_without_survey.id)}) reverse('info', kwargs={'course_id': unicode(self.course_without_survey.id)})
) )
def test_survey_xss(self):
"""Test that course display names are correctly HTML-escaped."""
response = self.client.get(
reverse(
'course_survey',
kwargs={'course_id': unicode(self.course.id)}
)
)
self.assert_xss(response, '<script>alert("XSS")</script>')
...@@ -15,6 +15,7 @@ from courseware.tests.helpers import LoginEnrollmentTestCase ...@@ -15,6 +15,7 @@ from courseware.tests.helpers import LoginEnrollmentTestCase
from student.tests.factories import AdminFactory from student.tests.factories import AdminFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.utils import XssTestMixin
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from shoppingcart.models import PaidCourseRegistration, Order, CourseRegCodeItem from shoppingcart.models import PaidCourseRegistration, Order, CourseRegCodeItem
from course_modes.models import CourseMode from course_modes.models import CourseMode
...@@ -23,7 +24,7 @@ from student.models import CourseEnrollment ...@@ -23,7 +24,7 @@ from student.models import CourseEnrollment
@ddt.ddt @ddt.ddt
class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase): class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase, XssTestMixin):
""" """
Tests for the instructor dashboard (not legacy). Tests for the instructor dashboard (not legacy).
""" """
...@@ -34,7 +35,8 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -34,7 +35,8 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase):
""" """
super(TestInstructorDashboard, self).setUp() super(TestInstructorDashboard, self).setUp()
self.course = CourseFactory.create( self.course = CourseFactory.create(
grading_policy={"GRADE_CUTOFFS": {"A": 0.75, "B": 0.63, "C": 0.57, "D": 0.5}} grading_policy={"GRADE_CUTOFFS": {"A": 0.75, "B": 0.63, "C": 0.57, "D": 0.5}},
display_name='<script>alert("XSS")</script>'
) )
self.course_mode = CourseMode(course_id=self.course.id, self.course_mode = CourseMode(course_id=self.course.id,
...@@ -87,6 +89,13 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -87,6 +89,13 @@ class TestInstructorDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase):
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertTrue('${amount}'.format(amount=total_amount) in response.content) self.assertTrue('${amount}'.format(amount=total_amount) in response.content)
def test_course_name_xss(self):
"""Test that the instructor dashboard correctly escapes course names
with script tags.
"""
response = self.client.get(self.url)
self.assert_xss(response, '<script>alert("XSS")</script>')
@override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs']) @override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs'])
def test_override_currency_settings_in_the_html_response(self): def test_override_currency_settings_in_the_html_response(self):
""" """
......
...@@ -26,6 +26,7 @@ import ddt ...@@ -26,6 +26,7 @@ import ddt
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.utils import XssTestMixin
from student.roles import CourseSalesAdminRole from student.roles import CourseSalesAdminRole
from util.date_utils import get_default_time_display from util.date_utils import get_default_time_display
from util.testing import UrlResetMixin from util.testing import UrlResetMixin
...@@ -65,7 +66,7 @@ postpay_mock = Mock() ...@@ -65,7 +66,7 @@ postpay_mock = Mock()
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True}) @patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True})
@ddt.ddt @ddt.ddt
class ShoppingCartViewsTests(ModuleStoreTestCase): class ShoppingCartViewsTests(ModuleStoreTestCase, XssTestMixin):
def setUp(self): def setUp(self):
super(ShoppingCartViewsTests, self).setUp() super(ShoppingCartViewsTests, self).setUp()
...@@ -98,7 +99,12 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -98,7 +99,12 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
verified_course = CourseFactory.create(org='org', number='test', display_name='Test Course') verified_course = CourseFactory.create(org='org', number='test', display_name='Test Course')
self.verified_course_key = verified_course.id self.verified_course_key = verified_course.id
xss_course = CourseFactory.create(org='xssorg', number='test', display_name='<script>alert("XSS")</script>')
self.xss_course_key = xss_course.id
self.cart = Order.get_cart_for_user(self.user) self.cart = Order.get_cart_for_user(self.user)
self.addCleanup(patcher.stop) self.addCleanup(patcher.stop)
self.now = datetime.now(pytz.UTC) self.now = datetime.now(pytz.UTC)
...@@ -884,6 +890,31 @@ class ShoppingCartViewsTests(ModuleStoreTestCase): ...@@ -884,6 +890,31 @@ class ShoppingCartViewsTests(ModuleStoreTestCase):
'course_key': unicode(self.verified_course_key) 'course_key': unicode(self.verified_course_key)
}) })
def test_show_receipt_xss(self):
CertificateItem.add_to_order(self.cart, self.xss_course_key, self.cost, 'honor')
self.cart.purchase()
self.login_user()
url = reverse('shoppingcart.views.show_receipt', args=[self.cart.id])
resp = self.client.get(url)
self.assert_xss(resp, '<script>alert("XSS")</script>')
@patch('shoppingcart.views.render_to_response', render_mock)
def test_reg_code_xss(self):
self.add_reg_code(self.xss_course_key)
# One courses in user shopping cart
self.add_course_to_user_cart(self.xss_course_key)
self.assertEquals(self.cart.orderitem_set.count(), 1)
post_response = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.reg_code})
self.assertEqual(post_response.status_code, 200)
redeem_url = reverse('register_code_redemption', args=[self.reg_code])
redeem_response = self.client.get(redeem_url)
self.assert_xss(redeem_response, '<script>alert("XSS")</script>')
def test_show_receipt_json_multiple_items(self): def test_show_receipt_json_multiple_items(self):
# Two different item types # Two different item types
PaidCourseRegistration.add_to_order(self.cart, self.course_key) PaidCourseRegistration.add_to_order(self.cart, self.course_key)
......
...@@ -51,6 +51,7 @@ from verify_student.models import ( ...@@ -51,6 +51,7 @@ from verify_student.models import (
) )
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from xmodule.modulestore.tests.utils import XssTestMixin
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.factories import check_mongo_calls from xmodule.modulestore.tests.factories import check_mongo_calls
...@@ -81,7 +82,7 @@ class StartView(TestCase): ...@@ -81,7 +82,7 @@ class StartView(TestCase):
@ddt.ddt @ddt.ddt
class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase): class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
""" """
Tests for the payment and verification flow views. Tests for the payment and verification flow views.
""" """
...@@ -258,6 +259,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase): ...@@ -258,6 +259,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase):
response = self._get_page('verify_student_verify_now', course.id) response = self._get_page('verify_student_verify_now', course.id)
self._assert_messaging(response, PayAndVerifyView.VERIFY_NOW_MSG) self._assert_messaging(response, PayAndVerifyView.VERIFY_NOW_MSG)
self.assert_xss(response, '<script>alert("XSS")</script>')
# Expect that *all* steps are displayed, # Expect that *all* steps are displayed,
# but we start after the payment step (because it's already completed). # but we start after the payment step (because it's already completed).
...@@ -339,6 +341,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase): ...@@ -339,6 +341,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase):
self._assert_messaging(response, PayAndVerifyView.PAYMENT_CONFIRMATION_MSG) self._assert_messaging(response, PayAndVerifyView.PAYMENT_CONFIRMATION_MSG)
self.assert_xss(response, '<script>alert("XSS")</script>')
# Expect that *all* steps are displayed, # Expect that *all* steps are displayed,
# but we start at the payment confirmation step # but we start at the payment confirmation step
self._assert_steps_displayed( self._assert_steps_displayed(
...@@ -371,6 +375,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase): ...@@ -371,6 +375,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase):
self._assert_messaging(response, PayAndVerifyView.FIRST_TIME_VERIFY_MSG) self._assert_messaging(response, PayAndVerifyView.FIRST_TIME_VERIFY_MSG)
self.assert_xss(response, '<script>alert("XSS")</script>')
# Expect that *all* steps are displayed, # Expect that *all* steps are displayed,
# but we start on the first verify step # but we start on the first verify step
self._assert_steps_displayed( self._assert_steps_displayed(
...@@ -456,6 +462,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase): ...@@ -456,6 +462,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase):
PayAndVerifyView.WEBCAM_REQ, PayAndVerifyView.WEBCAM_REQ,
]) ])
self._assert_upgrade_session_flag(True) self._assert_upgrade_session_flag(True)
self.assert_xss(response, '<script>alert("XSS")</script>')
def test_upgrade_already_verified(self): def test_upgrade_already_verified(self):
course = self._create_course("verified") course = self._create_course("verified")
...@@ -724,7 +731,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase): ...@@ -724,7 +731,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase):
def _create_course(self, *course_modes, **kwargs): def _create_course(self, *course_modes, **kwargs):
"""Create a new course with the specified course modes. """ """Create a new course with the specified course modes. """
course = CourseFactory.create() course = CourseFactory.create(display_name='<script>alert("XSS")</script>')
if kwargs.get('course_start'): if kwargs.get('course_start'):
course.start = kwargs.get('course_start') course.start = kwargs.get('course_start')
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
<li class="field text is-not-editable" id="field-course-display-name"> <li class="field text is-not-editable" id="field-course-display-name">
<label for="course-display-name">${_("Course Display Name:")}</label> <label for="course-display-name">${_("Course Display Name:")}</label>
<b>${ section_data['course_display_name'] }</b> <b>${ section_data['course_display_name'] | h}</b>
</li> </li>
<li class="field text is-not-editable" id="field-course-started"> <li class="field text is-not-editable" id="field-course-started">
......
...@@ -4,6 +4,7 @@ from django.utils.translation import ugettext as _ ...@@ -4,6 +4,7 @@ from django.utils.translation import ugettext as _
from django.utils.translation import ungettext from django.utils.translation import ungettext
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from courseware.courses import course_image_url, get_course_about_section, get_course_by_id from courseware.courses import course_image_url, get_course_about_section, get_course_by_id
from markupsafe import escape
from microsite_configuration import microsite from microsite_configuration import microsite
%> %>
...@@ -35,7 +36,7 @@ from microsite_configuration import microsite ...@@ -35,7 +36,7 @@ from microsite_configuration import microsite
${_(u"You have successfully been enrolled for {course_names}. " ${_(u"You have successfully been enrolled for {course_names}. "
u"The following receipt has been emailed to {receipient_emails}").format( u"The following receipt has been emailed to {receipient_emails}").format(
course_names=u"<b>{course_names}</b>".format( course_names=u"<b>{course_names}</b>".format(
course_names=appended_course_names course_names=escape(appended_course_names)
), ),
receipient_emails=u"<strong>{receipient_emails}</strong>".format( receipient_emails=u"<strong>{receipient_emails}</strong>".format(
receipient_emails=appended_recipient_emails receipient_emails=appended_recipient_emails
...@@ -50,7 +51,7 @@ from microsite_configuration import microsite ...@@ -50,7 +51,7 @@ from microsite_configuration import microsite
).format( ).format(
number=total_registration_codes, number=total_registration_codes,
course_names=u"<b>{course_names}</b>".format( course_names=u"<b>{course_names}</b>".format(
course_names=appended_course_names course_names=escape(appended_course_names)
) )
)} )}
${_("The following receipt has been emailed to {receipient_emails}").format( ${_("The following receipt has been emailed to {receipient_emails}").format(
...@@ -297,7 +298,7 @@ from microsite_configuration import microsite ...@@ -297,7 +298,7 @@ from microsite_configuration import microsite
<h3 class="course-title-info" id="course-title"> <h3 class="course-title-info" id="course-title">
<span class="course-registration-title">${_('Registration for:')}</span> <span class="course-registration-title">${_('Registration for:')}</span>
<span class="course-display-name">${ course.display_name }</span> <span class="course-display-name">${ course.display_name | h }</span>
</h3> </h3>
<p class="course-meta-info" aria-describedby="course-title"> <p class="course-meta-info" aria-describedby="course-title">
<span class="course-dates-title"> <span class="course-dates-title">
......
...@@ -33,7 +33,7 @@ from courseware.courses import course_image_url, get_course_about_section ...@@ -33,7 +33,7 @@ from courseware.courses import course_image_url, get_course_about_section
</div> </div>
<div class="course-title"> <div class="course-title">
<h1> <h1>
${_("{course_name}").format(course_name=course.display_name)} ${_("{course_name}").format(course_name=course.display_name) | h}
<span class="course-dates"> <span class="course-dates">
${_("{start_date} - {end_date}").format( ${_("{start_date} - {end_date}").format(
start_date=course.start_datetime_text(), start_date=course.start_datetime_text(),
...@@ -55,7 +55,7 @@ from courseware.courses import course_image_url, get_course_about_section ...@@ -55,7 +55,7 @@ from courseware.courses import course_image_url, get_course_about_section
)} )}
% elif redemption_success: % elif redemption_success:
${_("You have successfully enrolled in {course_name}." ${_("You have successfully enrolled in {course_name}."
" This course has now been added to your dashboard.").format(course_name=course.display_name)} " This course has now been added to your dashboard.").format(course_name=course.display_name) | h}
% elif registered_for_course: % elif registered_for_course:
${_("You're already enrolled for this course." ${_("You're already enrolled for this course."
" Visit your {link_start}dashboard{link_end} to see the course." " Visit your {link_start}dashboard{link_end} to see the course."
...@@ -72,7 +72,7 @@ from courseware.courses import course_image_url, get_course_about_section ...@@ -72,7 +72,7 @@ from courseware.courses import course_image_url, get_course_about_section
% else: % else:
${_("You're about to activate an enrollment code for {course_name} by {site_name}. " ${_("You're about to activate an enrollment code for {course_name} by {site_name}. "
"This code can only be used one time, so you should only activate this code if you're its intended" "This code can only be used one time, so you should only activate this code if you're its intended"
" recipient.").format(course_name=course.display_name, site_name=site_name)} " recipient.").format(course_name=course.display_name, site_name=site_name) | h}
% endif % endif
</p> </p>
</div> </div>
......
...@@ -33,7 +33,7 @@ from courseware.courses import course_image_url, get_course_about_section ...@@ -33,7 +33,7 @@ from courseware.courses import course_image_url, get_course_about_section
</div> </div>
<div class="course-title"> <div class="course-title">
<h1> <h1>
${course.display_name} ${course.display_name | h}
<span class="course-dates"> <span class="course-dates">
${course.start_datetime_text()} ${course.start_datetime_text()}
- -
...@@ -60,7 +60,7 @@ from courseware.courses import course_image_url, get_course_about_section ...@@ -60,7 +60,7 @@ from courseware.courses import course_image_url, get_course_about_section
"This course has now been added to your dashboard." "This course has now been added to your dashboard."
).format( ).format(
course_name=course.display_name, course_name=course.display_name,
)} ) | h}
% elif registered_for_course: % elif registered_for_course:
${_( ${_(
"You're already enrolled for this course. " "You're already enrolled for this course. "
...@@ -80,7 +80,7 @@ from courseware.courses import course_image_url, get_course_about_section ...@@ -80,7 +80,7 @@ from courseware.courses import course_image_url, get_course_about_section
).format( ).format(
course_name=course.display_name, course_name=course.display_name,
site_name=site_name, site_name=site_name,
)} ) | h}
% endif % endif
</p> </p>
</div> </div>
......
...@@ -24,7 +24,7 @@ from django.utils import html ...@@ -24,7 +24,7 @@ from django.utils import html
<div class="header-survey"> <div class="header-survey">
<h4 class="course-info"> <h4 class="course-info">
<span class="course-org">${course.display_org_with_default}</span><span class="course-number"> ${course.display_number_with_default}</span> <span class="course-org">${course.display_org_with_default}</span><span class="course-number"> ${course.display_number_with_default}</span>
<span class="course-name">${course.display_name}</span> <span class="course-name">${course.display_name | h}</span>
</h4> </h4>
<h3 class="title">${_("Pre-Course Survey")}</h3> <h3 class="title">${_("Pre-Course Survey")}</h3>
</div> </div>
......
...@@ -10,13 +10,13 @@ from verify_student.views import PayAndVerifyView ...@@ -10,13 +10,13 @@ from verify_student.views import PayAndVerifyView
<%block name="pagetitle"> <%block name="pagetitle">
% if message_key == PayAndVerifyView.UPGRADE_MSG: % if message_key == PayAndVerifyView.UPGRADE_MSG:
${_("Upgrade Your Enrollment For {course_name}.").format(course_name=course.display_name)} ${_("Upgrade Your Enrollment For {course_name}.").format(course_name=course.display_name) | h}
% elif message_key == PayAndVerifyView.PAYMENT_CONFIRMATION_MSG: % elif message_key == PayAndVerifyView.PAYMENT_CONFIRMATION_MSG:
${_("Receipt For {course_name}").format(course_name=course.display_name)} ${_("Receipt For {course_name}").format(course_name=course.display_name) | h}
% elif message_key in [PayAndVerifyView.VERIFY_NOW_MSG, PayAndVerifyView.VERIFY_LATER_MSG]: % elif message_key in [PayAndVerifyView.VERIFY_NOW_MSG, PayAndVerifyView.VERIFY_LATER_MSG]:
${_("Verify For {course_name}").format(course_name=course.display_name)} ${_("Verify For {course_name}").format(course_name=course.display_name) | h}
% else: % else:
${_("Enroll In {course_name}").format(course_name=course.display_name)} ${_("Enroll In {course_name}").format(course_name=course.display_name) | h}
% endif % endif
</%block> </%block>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment