diff --git a/cms/djangoapps/contentstore/views/certificates.py b/cms/djangoapps/contentstore/views/certificates.py
index d515489f95..ca453c9f7d 100644
--- a/cms/djangoapps/contentstore/views/certificates.py
+++ b/cms/djangoapps/contentstore/views/certificates.py
@@ -376,7 +376,7 @@ def certificates_list_handler(request, course_key_string):
'certificate_url': certificate_url,
'course_outline_url': course_outline_url,
'upload_asset_url': upload_asset_url,
- 'certificates': json.dumps(certificates),
+ 'certificates': certificates,
'course_modes': course_modes,
'certificate_web_view_url': certificate_web_view_url,
'is_active': is_active,
diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py
index b85900efdc..3e131378b1 100644
--- a/cms/djangoapps/contentstore/views/component.py
+++ b/cms/djangoapps/contentstore/views/component.py
@@ -1,6 +1,5 @@
from __future__ import absolute_import
-import json
import logging
from django.http import HttpResponseBadRequest, Http404
@@ -153,7 +152,7 @@ def container_handler(request, usage_key_string):
'section': section,
'new_unit_category': 'vertical',
'ancestor_xblocks': ancestor_xblocks,
- 'component_templates': json.dumps(component_templates),
+ 'component_templates': component_templates,
'xblock_info': xblock_info,
'draft_preview_link': preview_lms_link,
'published_preview_link': lms_link,
diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py
index 8d3ebe08be..6d4dba3649 100644
--- a/cms/djangoapps/contentstore/views/course.py
+++ b/cms/djangoapps/contentstore/views/course.py
@@ -36,6 +36,7 @@ from opaque_keys.edx.locations import Location
from opaque_keys.edx.keys import CourseKey
from django.views.decorators.csrf import ensure_csrf_cookie
+from openedx.core.lib.js_utils import escape_json_dumps
from contentstore.course_info_model import get_course_updates, update_course_updates, delete_course_update
from contentstore.course_group_config import (
GroupConfiguration,
@@ -317,10 +318,10 @@ def course_search_index_handler(request, course_key_string):
try:
reindex_course_and_check_access(course_key, request.user)
except SearchIndexingError as search_err:
- return HttpResponse(json.dumps({
+ return HttpResponse(escape_json_dumps({
"user_message": search_err.error_list
}), content_type=content_type, status=500)
- return HttpResponse(json.dumps({
+ return HttpResponse(escape_json_dumps({
"user_message": _("Course has been successfully reindexed.")
}), content_type=content_type, status=200)
@@ -554,9 +555,6 @@ def course_index(request, course_key):
'sections': sections,
'course_structure': course_structure,
'initial_state': course_outline_initial_state(locator_to_show, course_structure) if locator_to_show else None,
- 'course_graders': json.dumps(
- CourseGradingModel.fetch(course_key).graders
- ),
'rerun_notification_id': current_action.id if current_action else None,
'course_release_date': course_release_date,
'settings_url': settings_url,
@@ -1056,7 +1054,7 @@ def grading_handler(request, course_key_string, grader_index=None):
return render_to_response('settings_graders.html', {
'context_course': course_module,
'course_locator': course_key,
- 'course_details': json.dumps(course_details, cls=CourseSettingsEncoder),
+ 'course_details': course_details,
'grading_url': reverse_course_url('grading_handler', course_key),
'is_credit_course': is_credit_course(course_key),
})
diff --git a/cms/djangoapps/contentstore/views/entrance_exam.py b/cms/djangoapps/contentstore/views/entrance_exam.py
index 8087b5a02a..aaf311ba4f 100644
--- a/cms/djangoapps/contentstore/views/entrance_exam.py
+++ b/cms/djangoapps/contentstore/views/entrance_exam.py
@@ -10,6 +10,7 @@ from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse, HttpResponseBadRequest
+from openedx.core.lib.js_utils import escape_json_dumps
from contentstore.views.helpers import create_xblock, remove_entrance_exam_graders
from contentstore.views.item import delete_item
from models.settings.course_metadata import CourseMetadata
@@ -185,7 +186,7 @@ def _get_entrance_exam(request, course_key): # pylint: disable=W0613
try:
exam_descriptor = modulestore().get_item(exam_key)
return HttpResponse(
- _serialize_entrance_exam(exam_descriptor),
+ escape_json_dumps({'locator': unicode(exam_descriptor.location)}),
status=200, mimetype='application/json')
except ItemNotFoundError:
return HttpResponse(status=404)
@@ -241,15 +242,6 @@ def _delete_entrance_exam(request, course_key):
return HttpResponse(status=204)
-def _serialize_entrance_exam(entrance_exam_module):
- """
- Internal helper to convert an entrance exam module/object into JSON
- """
- return json.dumps({
- 'locator': unicode(entrance_exam_module.location)
- })
-
-
def add_entrance_exam_milestone(course_id, x_block):
# Add an entrance exam milestone if one does not already exist for given xBlock
# As this is a standalone method for entrance exam, We should check that given xBlock should be an entrance exam.
diff --git a/cms/djangoapps/contentstore/views/error.py b/cms/djangoapps/contentstore/views/error.py
index c67a559175..af4e6c1e27 100644
--- a/cms/djangoapps/contentstore/views/error.py
+++ b/cms/djangoapps/contentstore/views/error.py
@@ -4,7 +4,7 @@ from django.http import (HttpResponse, HttpResponseServerError,
HttpResponseNotFound)
from edxmako.shortcuts import render_to_string, render_to_response
import functools
-import json
+from openedx.core.lib.js_utils import escape_json_dumps
__all__ = ['not_found', 'server_error', 'render_404', 'render_500']
@@ -18,7 +18,7 @@ def jsonable_error(status=500, message="The Studio servers encountered an error"
@functools.wraps(func)
def inner(request, *args, **kwargs):
if request.is_ajax():
- content = json.dumps({"error": message})
+ content = escape_json_dumps({"error": message})
return HttpResponse(content, content_type="application/json",
status=status)
else:
diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py
index cbc1e28cbc..0eddbcb9eb 100644
--- a/cms/djangoapps/contentstore/views/item.py
+++ b/cms/djangoapps/contentstore/views/item.py
@@ -853,7 +853,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
"due_date": get_default_time_display(xblock.due),
"due": xblock.fields['due'].to_json(xblock.due),
"format": xblock.format,
- "course_graders": json.dumps([grader.get('type') for grader in graders]),
+ "course_graders": [grader.get('type') for grader in graders],
"has_changes": has_changes,
"actions": xblock_actions,
"explanatory_message": explanatory_message,
diff --git a/cms/djangoapps/contentstore/views/library.py b/cms/djangoapps/contentstore/views/library.py
index 1323aa4f09..9cf459a8a2 100644
--- a/cms/djangoapps/contentstore/views/library.py
+++ b/cms/djangoapps/contentstore/views/library.py
@@ -191,7 +191,7 @@ def library_blocks_view(library, user, response_format):
return render_to_response('library.html', {
'can_edit': can_edit,
'context_library': library,
- 'component_templates': json.dumps(component_templates),
+ 'component_templates': component_templates,
'xblock_info': xblock_info,
'templates': CONTAINER_TEMPLATES,
})
diff --git a/cms/djangoapps/contentstore/views/tests/test_item.py b/cms/djangoapps/contentstore/views/tests/test_item.py
index c2dfb7bee7..ce923e47d1 100644
--- a/cms/djangoapps/contentstore/views/tests/test_item.py
+++ b/cms/djangoapps/contentstore/views/tests/test_item.py
@@ -1642,7 +1642,7 @@ class TestXBlockInfo(ItemTest):
self.assertEqual(xblock_info['display_name'], 'Week 1')
self.assertTrue(xblock_info['published'])
self.assertIsNone(xblock_info.get('edited_by', None))
- self.assertEqual(xblock_info['course_graders'], '["Homework", "Lab", "Midterm Exam", "Final Exam"]')
+ self.assertEqual(xblock_info['course_graders'], ['Homework', 'Lab', 'Midterm Exam', 'Final Exam'])
self.assertEqual(xblock_info['start'], '2030-01-01T00:00:00Z')
self.assertEqual(xblock_info['graded'], False)
self.assertEqual(xblock_info['due'], None)
diff --git a/cms/static/js/spec/views/pages/course_outline_spec.js b/cms/static/js/spec/views/pages/course_outline_spec.js
index c4d59a50c8..56ee53b2a5 100644
--- a/cms/static/js/spec/views/pages/course_outline_spec.js
+++ b/cms/static/js/spec/views/pages/course_outline_spec.js
@@ -65,7 +65,7 @@ define(["jquery", "common/js/spec_helpers/ajax_helpers", "common/js/components/u
published: true,
edited_on: 'Jul 02, 2014 at 20:56 UTC',
edited_by: 'MockUser',
- course_graders: '["Lab", "Howework"]',
+ course_graders: ["Lab", "Howework"],
has_explicit_staff_lock: false,
child_info: {
category: 'vertical',
diff --git a/cms/static/js/views/modals/course_outline_modals.js b/cms/static/js/views/modals/course_outline_modals.js
index 7dc43d65f0..fb7dc29604 100644
--- a/cms/static/js/views/modals/course_outline_modals.js
+++ b/cms/static/js/views/modals/course_outline_modals.js
@@ -410,7 +410,7 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
getContext: function () {
return {
- graderTypes: JSON.parse(this.model.get('course_graders'))
+ graderTypes: this.model.get('course_graders')
};
}
});
diff --git a/cms/templates/base.html b/cms/templates/base.html
index c0d06ec080..3feec0ad3c 100644
--- a/cms/templates/base.html
+++ b/cms/templates/base.html
@@ -2,8 +2,9 @@
<%namespace name='static' file='static_content.html'/>
<%!
from django.utils.translation import ugettext as _
-from django.template.defaultfilters import escapejs
-import json
+from openedx.core.lib.js_utils import (
+ escape_json_dumps, escape_js_string
+)
%>
@@ -41,7 +42,7 @@ import json
${_("Skip to main content")}
@@ -79,14 +80,14 @@ import json
% if context_course:
require(['js/factories/course'], function(CourseFactory) {
CourseFactory({
- id: "${context_course.id | escapejs}",
+ id: "${escape_js_string(context_course.id) | n}",
name: "${context_course.display_name_with_default | h}",
url_name: "${context_course.location.name | h}",
org: "${context_course.location.org | h}",
num: "${context_course.location.course | h}",
display_course_number: "${_(context_course.display_coursenumber)}",
revision: "${context_course.location.revision | h}",
- self_paced: ${json.dumps(context_course.self_paced)}
+ self_paced: ${escape_json_dumps(context_course.self_paced) | n}
});
});
% endif
diff --git a/cms/templates/certificates.html b/cms/templates/certificates.html
index c39f994864..2b144c80d1 100644
--- a/cms/templates/certificates.html
+++ b/cms/templates/certificates.html
@@ -2,9 +2,9 @@
<%def name="online_help_token()"><% return "certificates" %>%def>
<%namespace name='static' file='static_content.html'/>
<%!
-import json
from contentstore import utils
from django.utils.translation import ugettext as _
+from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${_("Course Certificates")}%block>
@@ -30,7 +30,7 @@ CMS.User.isGlobalStaff = '${is_global_staff}'=='True' ? true : false;
<%block name="requirejs">
require(["js/certificates/factories/certificates_page_factory"], function(CertificatesPageFactory) {
- CertificatesPageFactory(${json.dumps(certificates)}, "${certificate_url}", "${course_outline_url}", ${json.dumps(course_modes)}, ${json.dumps(certificate_web_view_url)}, ${json.dumps(is_active)}, ${json.dumps(certificate_activation_handler_url)} );
+ CertificatesPageFactory(${escape_json_dumps(certificates) | n}, "${certificate_url}", "${course_outline_url}", ${escape_json_dumps(course_modes) | n}, ${escape_json_dumps(certificate_web_view_url) | n}, ${escape_json_dumps(is_active) | n}, ${escape_json_dumps(certificate_activation_handler_url) | n} );
});
%block>
diff --git a/cms/templates/container.html b/cms/templates/container.html
index 75b11c8241..c44ac74b84 100644
--- a/cms/templates/container.html
+++ b/cms/templates/container.html
@@ -8,10 +8,9 @@ else:
%>
%def>
<%!
-import json
-
from contentstore.views.helpers import xblock_studio_url, xblock_type_display_name
from django.utils.translation import ugettext as _
+from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${xblock.display_name_with_default} ${xblock_type_display_name(xblock) | h}%block>
<%block name="bodyclass">is-signedin course container view-container%block>
@@ -33,10 +32,11 @@ from django.utils.translation import ugettext as _
<%block name="requirejs">
require(["js/factories/container"], function(ContainerFactory) {
ContainerFactory(
- ${component_templates | n}, ${json.dumps(xblock_info) | n},
+ ${ escape_json_dumps(component_templates) | n },
+ ${ escape_json_dumps(xblock_info) | n },
"${action | h}",
{
- isUnitPage: ${json.dumps(is_unit_page)},
+ isUnitPage: ${ escape_json_dumps(is_unit_page) | n },
canEdit: true
}
);
diff --git a/cms/templates/course_info.html b/cms/templates/course_info.html
index 14eac181f2..7fa84c264e 100644
--- a/cms/templates/course_info.html
+++ b/cms/templates/course_info.html
@@ -2,9 +2,9 @@
<%def name="online_help_token()"><% return "updates" %>%def>
<%namespace name='static' file='static_content.html'/>
<%!
-import json
from django.utils.translation import ugettext as _
from django.template.defaultfilters import escapejs
+from openedx.core.lib.js_utils import escape_json_dumps
%>
## TODO decode course # from context_course into title.
@@ -26,7 +26,7 @@ from django.template.defaultfilters import escapejs
"${updates_url}",
"${handouts_locator | escapejs}",
"${base_asset_url}",
- ${json.dumps(push_notification_enabled)}
+ ${escape_json_dumps(push_notification_enabled) | n}
);
});
%block>
diff --git a/cms/templates/course_outline.html b/cms/templates/course_outline.html
index 839689d6ef..2a43fdea5a 100644
--- a/cms/templates/course_outline.html
+++ b/cms/templates/course_outline.html
@@ -1,10 +1,10 @@
<%inherit file="base.html" />
<%def name="online_help_token()"><% return "outline" %>%def>
<%!
-import json
import logging
from util.date_utils import get_default_time_display
from django.utils.translation import ugettext as _
+from openedx.core.lib.js_utils import escape_json_dumps
from contentstore.utils import reverse_usage_url
from microsite_configuration import microsite
%>
@@ -15,7 +15,7 @@ from microsite_configuration import microsite
<%block name="requirejs">
require(["js/factories/outline"], function (OutlineFactory) {
- OutlineFactory(${json.dumps(course_structure) | n}, ${json.dumps(initial_state) | n});
+ OutlineFactory(${escape_json_dumps(course_structure) | n}, ${escape_json_dumps(initial_state) | n});
});
%block>
diff --git a/cms/templates/export.html b/cms/templates/export.html
index f8534f73d2..6a8168b4e4 100644
--- a/cms/templates/export.html
+++ b/cms/templates/export.html
@@ -11,7 +11,7 @@ else:
<%!
from django.utils.translation import ugettext as _
- import json
+ from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">
%if library:
@@ -24,11 +24,11 @@ else:
<%block name="requirejs">
% if in_err:
- var hasUnit = ${json.dumps(bool(unit))},
+ var hasUnit = ${escape_json_dumps(bool(unit)) | n},
editUnitUrl = "${edit_unit_url or ""}",
courselikeHomeUrl = "${courselike_home_url or ""}",
- is_library = ${json.dumps(library)}
- errMsg = ${json.dumps(raw_err_msg or "")};
+ is_library = ${escape_json_dumps(library) | n}
+ errMsg = ${escape_json_dumps(raw_err_msg or "") | n};
require(["js/factories/export"], function(ExportFactory) {
ExportFactory(hasUnit, editUnitUrl, courselikeHomeUrl, is_library, errMsg);
diff --git a/cms/templates/group_configurations.html b/cms/templates/group_configurations.html
index 865c8959d6..1fa5cc6131 100644
--- a/cms/templates/group_configurations.html
+++ b/cms/templates/group_configurations.html
@@ -3,9 +3,9 @@
<%def name="experiment_group_configurations_help_token()"><% return "group_configurations" %>%def>
<%namespace name='static' file='static_content.html'/>
<%!
-import json
from contentstore import utils
from django.utils.translation import ugettext as _
+from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${_("Group Configurations")}%block>
@@ -21,7 +21,7 @@ from django.utils.translation import ugettext as _
<%block name="requirejs">
require(["js/factories/group_configurations"], function(GroupConfigurationsFactory) {
- GroupConfigurationsFactory(${json.dumps(should_show_experiment_groups)}, ${json.dumps(experiment_group_configurations)}, ${json.dumps(content_group_configuration)}, "${group_configuration_url}", "${course_outline_url}");
+ GroupConfigurationsFactory(${escape_json_dumps(should_show_experiment_groups) | n}, ${escape_json_dumps(experiment_group_configurations) | n}, ${escape_json_dumps(content_group_configuration) | n}, "${group_configuration_url}", "${course_outline_url}");
});
%block>
diff --git a/cms/templates/import.html b/cms/templates/import.html
index 61fcbb5f25..989c2cbc12 100644
--- a/cms/templates/import.html
+++ b/cms/templates/import.html
@@ -10,7 +10,7 @@ else:
<%namespace name='static' file='static_content.html'/>
<%!
from django.utils.translation import ugettext as _
- import json
+ from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">
%if library:
@@ -239,6 +239,6 @@ else:
<%block name="requirejs">
require(["js/factories/import"], function(ImportFactory) {
- ImportFactory("${import_status_url}", ${json.dumps(library)});
+ ImportFactory("${import_status_url}", ${escape_json_dumps(library) | n});
});
%block>
diff --git a/cms/templates/library.html b/cms/templates/library.html
index 864c69c518..f55c745ec3 100644
--- a/cms/templates/library.html
+++ b/cms/templates/library.html
@@ -1,10 +1,9 @@
<%inherit file="base.html" />
<%def name="online_help_token()"><% return "content_libraries" %>%def>
<%!
-import json
-
from contentstore.views.helpers import xblock_studio_url, xblock_type_display_name
from django.utils.translation import ugettext as _
+from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${context_library.display_name_with_default} ${xblock_type_display_name(context_library)}%block>
<%block name="bodyclass">is-signedin course container view-container view-library%block>
@@ -25,8 +24,8 @@ from django.utils.translation import ugettext as _
<%block name="requirejs">
require(["js/factories/library"], function(LibraryFactory) {
LibraryFactory(
- ${component_templates | n},
- ${json.dumps(xblock_info) | n},
+ ${escape_json_dumps(component_templates) | n},
+ ${escape_json_dumps(xblock_info) | n},
{
isUnitPage: false,
page_size: 10,
diff --git a/cms/templates/manage_users.html b/cms/templates/manage_users.html
index 815d635409..687247c590 100644
--- a/cms/templates/manage_users.html
+++ b/cms/templates/manage_users.html
@@ -1,8 +1,8 @@
<%inherit file="base.html" />
<%!
-import json
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
+from openedx.core.lib.js_utils import escape_json_dumps
%>
<%def name="online_help_token()"><% return "team_course" %>%def>
<%block name="title">${_("Course Team Settings")}%block>
@@ -115,7 +115,7 @@ from django.core.urlresolvers import reverse
require(["js/factories/manage_users"], function(ManageCourseUsersFactory) {
ManageCourseUsersFactory(
"${context_course.display_name | h}",
- ${json.dumps(users)},
+ ${escape_json_dumps(users) | n},
"${reverse('contentstore.views.course_team_handler', kwargs={'course_key_string': unicode(context_course.id), 'email': '@@EMAIL@@'})}",
${ request.user.id },
${str(allow_actions).lower()}
diff --git a/cms/templates/manage_users_lib.html b/cms/templates/manage_users_lib.html
index e4dd12d3cf..b080c619f2 100644
--- a/cms/templates/manage_users_lib.html
+++ b/cms/templates/manage_users_lib.html
@@ -1,8 +1,8 @@
<%inherit file="base.html" />
<%!
-import json
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
+from openedx.core.lib.js_utils import escape_json_dumps
%>
<%def name="online_help_token()"><% return "team_library" %>%def>
<%block name="title">${_("Library User Access")}%block>
@@ -108,7 +108,7 @@ from django.core.urlresolvers import reverse
require(["js/factories/manage_users_lib"], function(ManageLibraryUsersFactory) {
ManageLibraryUsersFactory(
"${context_library.display_name_with_default | h}",
- ${json.dumps(users)},
+ ${escape_json_dumps(users) | n},
"${reverse('contentstore.views.course_team_handler', kwargs={'course_key_string': library_key, 'email': '@@EMAIL@@'})}",
${ request.user.id },
${str(allow_actions).lower()}
diff --git a/cms/templates/settings.html b/cms/templates/settings.html
index b9456eb036..306cd32daa 100644
--- a/cms/templates/settings.html
+++ b/cms/templates/settings.html
@@ -5,10 +5,10 @@
<%namespace name='static' file='static_content.html'/>
<%!
- import json
import urllib
from django.utils.translation import ugettext as _
from contentstore import utils
+ from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="header_extras">
@@ -31,7 +31,7 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url}';
<%block name="requirejs">
require(["js/factories/settings"], function(SettingsFactory) {
- SettingsFactory("${details_url}", ${json.dumps(show_min_grade_warning)});
+ SettingsFactory("${details_url}", ${escape_json_dumps(show_min_grade_warning) | n});
});
%block>
diff --git a/cms/templates/settings_advanced.html b/cms/templates/settings_advanced.html
index 40f347ca30..5bfb09679e 100644
--- a/cms/templates/settings_advanced.html
+++ b/cms/templates/settings_advanced.html
@@ -4,7 +4,7 @@
<%!
from django.utils.translation import ugettext as _
from contentstore import utils
- from openedx.core.lib.json_utils import escape_json_dumps
+ from openedx.core.lib.js_utils import escape_json_dumps
%>
<%block name="title">${_("Advanced Settings")}%block>
<%block name="bodyclass">is-signedin course advanced view-settings%block>
diff --git a/cms/templates/settings_graders.html b/cms/templates/settings_graders.html
index 6deac5c679..580e831c14 100644
--- a/cms/templates/settings_graders.html
+++ b/cms/templates/settings_graders.html
@@ -8,6 +8,8 @@
import json
from contentstore import utils
from django.utils.translation import ugettext as _
+ from openedx.core.lib.js_utils import escape_json_dumps
+ from models.settings.course_details import CourseSettingsEncoder
%>
<%block name="header_extras">
@@ -23,7 +25,7 @@
%block>
<%block name="requirejs">
require(["js/factories/settings_graders"], function(SettingsGradersFactory) {
- SettingsGradersFactory(_.extend(${course_details|n}, {is_credit_course: ${json.dumps(is_credit_course)}}), "${grading_url}");
+ SettingsGradersFactory(_.extend(${escape_json_dumps(course_details, cls=CourseSettingsEncoder) | n}, {is_credit_course: ${escape_json_dumps(is_credit_course) | n}}), "${grading_url}");
});
%block>
diff --git a/cms/templates/studio_xblock_wrapper.html b/cms/templates/studio_xblock_wrapper.html
index f947bf1038..129f5775b2 100644
--- a/cms/templates/studio_xblock_wrapper.html
+++ b/cms/templates/studio_xblock_wrapper.html
@@ -2,7 +2,7 @@
from django.utils.translation import ugettext as _
from contentstore.views.helpers import xblock_studio_url
from contentstore.utils import is_visible_to_specific_content_groups
-import json
+from openedx.core.lib.js_utils import escape_json_dumps
%>
<%
xblock_url = xblock_studio_url(xblock)
@@ -10,7 +10,7 @@ show_inline = xblock.has_children and not xblock_url
section_class = "level-nesting" if show_inline else "level-element"
collapsible_class = "is-collapsible" if xblock.has_children else ""
label = xblock.display_name_with_default or xblock.scope_ids.block_type
-messages = json.dumps(xblock.validate().to_json())
+messages = xblock.validate().to_json()
%>
<%namespace name='static' file='static_content.html'/>
@@ -24,7 +24,7 @@ messages = json.dumps(xblock.validate().to_json())
': ''}
- self.assertNotIn(
- '',
- json.dumps(malicious_json, cls=EscapedEdxJSONEncoder)
- )
-
def test_escape_json_dumps_escapes_unsafe_html(self):
"""
Test escape_json_dumps properly escapes &, <, and >.
@@ -70,3 +60,15 @@ class TestJsonUtils(TestCase):
encoded_json = escape_json_dumps(malicious_json, cls=self.SampleJSONEncoder)
self.assertEquals(expected_custom_encoded_json, encoded_json)
+
+ def test_escape_js_string_escapes_unsafe_html(self):
+ """
+ Test escape_js_string escapes &, <, and >, as well as returns a unicode type
+ """
+ malicious_js_string = ""
+
+ expected_escaped_js_string = unicode(
+ r"\u003C/script\u003E\u003Cscript\u003Ealert(\u0027hello, \u0027)\u003B\u003C/script\u003E"
+ )
+ escaped_js_string = escape_js_string(malicious_js_string)
+ self.assertEquals(expected_escaped_js_string, escaped_js_string)