# -*- coding: utf-8 -*- from __future__ import unicode_literals from xml.dom import minidom from django.core import serializers from django.core.serializers.xml_serializer import DTDForbidden from django.test import TestCase, TransactionTestCase from django.utils import six from .tests import SerializersTestBase, SerializersTransactionTestBase class XmlSerializerTestCase(SerializersTestBase, TestCase): serializer_name = "xml" pkless_str = """ Reference Non-fiction """ mapping_ordering_str = """ %(author_pk)s Poker has no place on ESPN 2006-06-16T11:00:00 """ # NOQA @staticmethod def _comparison_value(value): # The XML serializer handles everything as strings, so comparisons # need to be performed on the stringified value return six.text_type(value) @staticmethod def _validate_output(serial_str): try: minidom.parseString(serial_str) except Exception: return False else: return True @staticmethod def _get_pk_values(serial_str): ret_list = [] dom = minidom.parseString(serial_str) fields = dom.getElementsByTagName("object") for field in fields: ret_list.append(field.getAttribute("pk")) return ret_list @staticmethod def _get_field_values(serial_str, field_name): ret_list = [] dom = minidom.parseString(serial_str) fields = dom.getElementsByTagName("field") for field in fields: if field.getAttribute("name") == field_name: temp = [] for child in field.childNodes: temp.append(child.nodeValue) ret_list.append("".join(temp)) return ret_list def test_control_char_failure(self): """ Serializing control characters with XML should fail as those characters are not supported in the XML 1.0 standard (except HT, LF, CR). """ self.a1.headline = "This contains \u0001 control \u0011 chars" msg = "Article.headline (pk:%s) contains unserializable characters" % self.a1.pk with self.assertRaisesMessage(ValueError, msg): serializers.serialize(self.serializer_name, [self.a1]) self.a1.headline = "HT \u0009, LF \u000A, and CR \u000D are allowed" self.assertIn( "HT \t, LF \n, and CR \r are allowed", serializers.serialize(self.serializer_name, [self.a1]) ) def test_no_dtd(self): """ The XML deserializer shouldn't allow a DTD. This is the most straightforward way to prevent all entity definitions and avoid both external entities and entity-expansion attacks. """ xml = '' with self.assertRaises(DTDForbidden): next(serializers.deserialize('xml', xml)) class XmlSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase): serializer_name = "xml" fwd_ref_str = """ 1 Forward references pose no problem 2006-06-16T15:00:00 Agnes Reference """