From 8a15c4e0cae4d23eca2856e5e35643117fdbe133 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 1 Oct 2020 17:01:50 +0100 Subject: [PATCH] MDL-69798 XML question export: excape special chars in idnumbers --- question/format/xml/format.php | 6 ++- .../fixtures/html_chars_in_idnumbers.xml | 43 +++++++++++++++++++ .../tests/qformat_xml_import_export_test.php | 38 ++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 question/format/xml/tests/fixtures/html_chars_in_idnumbers.xml diff --git a/question/format/xml/format.php b/question/format/xml/format.php index d2323d00afd..be6aad3d1b1 100644 --- a/question/format/xml/format.php +++ b/question/format/xml/format.php @@ -1194,6 +1194,8 @@ class qformat_xml extends qformat_default { // Check question type. $questiontype = $this->get_qtype($question->qtype); + $idnumber = htmlspecialchars($question->idnumber); + // Categories are a special case. if ($question->qtype == 'category') { $categorypath = $this->writetext($question->category); @@ -1206,7 +1208,7 @@ class qformat_xml extends qformat_default { $expout .= " \n"; $expout .= " {$categoryinfo}"; $expout .= " \n"; - $expout .= " {$question->idnumber}\n"; + $expout .= " {$idnumber}\n"; $expout .= " \n"; return $expout; } @@ -1230,7 +1232,7 @@ class qformat_xml extends qformat_default { } $expout .= " {$question->penalty}\n"; $expout .= " {$question->hidden}\n"; - $expout .= " {$question->idnumber}\n"; + $expout .= " {$idnumber}\n"; // The rest of the output depends on question type. switch($question->qtype) { diff --git a/question/format/xml/tests/fixtures/html_chars_in_idnumbers.xml b/question/format/xml/tests/fixtures/html_chars_in_idnumbers.xml new file mode 100644 index 00000000000..cc1d37676e9 --- /dev/null +++ b/question/format/xml/tests/fixtures/html_chars_in_idnumbers.xml @@ -0,0 +1,43 @@ + + + + + + $course$/Alpha + + + This is Alpha category for test + + The inequalities < & > + + + + + + Alpha Question + + + Testing Alpha Question

]]>
+
+ + + + 1.0000000 + 1.0000000 + 0 + T & F + + true + + + + + + false + + + + +
+ +
diff --git a/question/format/xml/tests/qformat_xml_import_export_test.php b/question/format/xml/tests/qformat_xml_import_export_test.php index 4926bea1040..ebd9fcdc4e6 100644 --- a/question/format/xml/tests/qformat_xml_import_export_test.php +++ b/question/format/xml/tests/qformat_xml_import_export_test.php @@ -426,6 +426,44 @@ class qformat_xml_import_export_test extends advanced_testcase { $this->assert_same_xml($expectedxml, $qformat->exportprocess()); } + /** + * Simple check for exporting a category. + */ + public function test_export_category_with_special_chars() { + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $this->resetAfterTest(true); + $course = $this->getDataGenerator()->create_course(); + $this->setAdminUser(); + // Note while this loads $qformat with all the 'right' data from the xml file, + // the call to setCategory, followed by exportprocess will actually only export data + // from the database (created by the generator). + $qformat = $this->create_qformat('export_category.xml', $course); + + $category = $generator->create_question_category([ + 'name' => 'Alpha', + 'contextid' => '2', + 'info' => 'This is Alpha category for test', + 'infoformat' => '0', + 'idnumber' => 'The inequalities < & >', + 'stamp' => make_unique_id_code(), + 'parent' => '0', + 'sortorder' => '999']); + $generator->create_question('truefalse', null, [ + 'category' => $category->id, + 'name' => 'Alpha Question', + 'questiontext' => ['format' => '1', 'text' => '

Testing Alpha Question

'], + 'generalfeedback' => ['format' => '1', 'text' => ''], + 'idnumber' => 'T & F', + 'correctanswer' => '1', + 'feedbacktrue' => ['format' => '1', 'text' => ''], + 'feedbackfalse' => ['format' => '1', 'text' => ''], + 'penalty' => '1']); + $qformat->setCategory($category); + + $expectedxml = file_get_contents(__DIR__ . '/fixtures/html_chars_in_idnumbers.xml'); + $this->assert_same_xml($expectedxml, $qformat->exportprocess()); + } + /** * Test that bad multianswer questions are not imported. */