test_xml.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. from xml.dom import minidom
  4. from django.core import serializers
  5. from django.core.serializers.xml_serializer import DTDForbidden
  6. from django.test import TestCase, TransactionTestCase
  7. from django.utils import six
  8. from .tests import SerializersTestBase, SerializersTransactionTestBase
  9. class XmlSerializerTestCase(SerializersTestBase, TestCase):
  10. serializer_name = "xml"
  11. pkless_str = """<?xml version="1.0" encoding="utf-8"?>
  12. <django-objects version="1.0">
  13. <object model="serializers.category">
  14. <field type="CharField" name="name">Reference</field>
  15. </object>
  16. <object model="serializers.category">
  17. <field type="CharField" name="name">Non-fiction</field>
  18. </object>
  19. </django-objects>"""
  20. mapping_ordering_str = """<?xml version="1.0" encoding="utf-8"?>
  21. <django-objects version="1.0">
  22. <object model="serializers.article" pk="%(article_pk)s">
  23. <field name="author" rel="ManyToOneRel" to="serializers.author">%(author_pk)s</field>
  24. <field name="headline" type="CharField">Poker has no place on ESPN</field>
  25. <field name="pub_date" type="DateTimeField">2006-06-16T11:00:00</field>
  26. <field name="categories" rel="ManyToManyRel" to="serializers.category"><object pk="%(first_category_pk)s"></object><object pk="%(second_category_pk)s"></object></field>
  27. <field name="meta_data" rel="ManyToManyRel" to="serializers.categorymetadata"></field>
  28. </object>
  29. </django-objects>""" # NOQA
  30. @staticmethod
  31. def _comparison_value(value):
  32. # The XML serializer handles everything as strings, so comparisons
  33. # need to be performed on the stringified value
  34. return six.text_type(value)
  35. @staticmethod
  36. def _validate_output(serial_str):
  37. try:
  38. minidom.parseString(serial_str)
  39. except Exception:
  40. return False
  41. else:
  42. return True
  43. @staticmethod
  44. def _get_pk_values(serial_str):
  45. ret_list = []
  46. dom = minidom.parseString(serial_str)
  47. fields = dom.getElementsByTagName("object")
  48. for field in fields:
  49. ret_list.append(field.getAttribute("pk"))
  50. return ret_list
  51. @staticmethod
  52. def _get_field_values(serial_str, field_name):
  53. ret_list = []
  54. dom = minidom.parseString(serial_str)
  55. fields = dom.getElementsByTagName("field")
  56. for field in fields:
  57. if field.getAttribute("name") == field_name:
  58. temp = []
  59. for child in field.childNodes:
  60. temp.append(child.nodeValue)
  61. ret_list.append("".join(temp))
  62. return ret_list
  63. def test_control_char_failure(self):
  64. """
  65. Serializing control characters with XML should fail as those characters
  66. are not supported in the XML 1.0 standard (except HT, LF, CR).
  67. """
  68. self.a1.headline = "This contains \u0001 control \u0011 chars"
  69. msg = "Article.headline (pk:%s) contains unserializable characters" % self.a1.pk
  70. with self.assertRaisesMessage(ValueError, msg):
  71. serializers.serialize(self.serializer_name, [self.a1])
  72. self.a1.headline = "HT \u0009, LF \u000A, and CR \u000D are allowed"
  73. self.assertIn(
  74. "HT \t, LF \n, and CR \r are allowed",
  75. serializers.serialize(self.serializer_name, [self.a1])
  76. )
  77. def test_no_dtd(self):
  78. """
  79. The XML deserializer shouldn't allow a DTD.
  80. This is the most straightforward way to prevent all entity definitions
  81. and avoid both external entities and entity-expansion attacks.
  82. """
  83. xml = '<?xml version="1.0" standalone="no"?><!DOCTYPE example SYSTEM "http://example.com/example.dtd">'
  84. with self.assertRaises(DTDForbidden):
  85. next(serializers.deserialize('xml', xml))
  86. class XmlSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase):
  87. serializer_name = "xml"
  88. fwd_ref_str = """<?xml version="1.0" encoding="utf-8"?>
  89. <django-objects version="1.0">
  90. <object pk="1" model="serializers.article">
  91. <field to="serializers.author" name="author" rel="ManyToOneRel">1</field>
  92. <field type="CharField" name="headline">Forward references pose no problem</field>
  93. <field type="DateTimeField" name="pub_date">2006-06-16T15:00:00</field>
  94. <field to="serializers.category" name="categories" rel="ManyToManyRel">
  95. <object pk="1"></object>
  96. </field>
  97. <field to="serializers.categorymetadata" name="meta_data" rel="ManyToManyRel"></field>
  98. </object>
  99. <object pk="1" model="serializers.author">
  100. <field type="CharField" name="name">Agnes</field>
  101. </object>
  102. <object pk="1" model="serializers.category">
  103. <field type="CharField" name="name">Reference</field></object>
  104. </django-objects>"""