mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-23 15:54:16 +03:00
defusedxml for security fix.
As per: http://blog.python.org/2013/02/announcing-defusedxml-fixes-for-xml.html
This commit is contained in:
parent
b261515afa
commit
dcee027fa9
|
@ -13,6 +13,7 @@ env:
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install $DJANGO
|
- pip install $DJANGO
|
||||||
|
- pip install defusedxml==0.3
|
||||||
- "if [[ ${TRAVIS_PYTHON_VERSION::1} != '3' ]]; then pip install django-filter==0.5.4 --use-mirrors; fi"
|
- "if [[ ${TRAVIS_PYTHON_VERSION::1} != '3' ]]; then pip install django-filter==0.5.4 --use-mirrors; fi"
|
||||||
- "if [[ ${TRAVIS_PYTHON_VERSION::1} == '3' ]]; then pip install https://github.com/alex/django-filter/tarball/master; fi"
|
- "if [[ ${TRAVIS_PYTHON_VERSION::1} == '3' ]]; then pip install https://github.com/alex/django-filter/tarball/master; fi"
|
||||||
- export PYTHONPATH=.
|
- export PYTHONPATH=.
|
||||||
|
|
|
@ -31,9 +31,10 @@ There is also a sandbox API you can use for testing purposes, [available here][s
|
||||||
|
|
||||||
**Optional:**
|
**Optional:**
|
||||||
|
|
||||||
* [Markdown] - Markdown support for the self describing API.
|
* [Markdown][markdown] - Markdown support for the self describing API.
|
||||||
* [PyYAML] - YAML content type support.
|
* [PyYAML][pyyaml] - YAML content type support.
|
||||||
* [django-filter] - Filtering support.
|
* [defusedxml][defusedxml] - XML content-type support.
|
||||||
|
* [django-filter][django-filter] - Filtering support.
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
|
@ -115,4 +116,5 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
[urlobject]: https://github.com/zacharyvoase/urlobject
|
[urlobject]: https://github.com/zacharyvoase/urlobject
|
||||||
[markdown]: http://pypi.python.org/pypi/Markdown/
|
[markdown]: http://pypi.python.org/pypi/Markdown/
|
||||||
[pyyaml]: http://pypi.python.org/pypi/PyYAML
|
[pyyaml]: http://pypi.python.org/pypi/PyYAML
|
||||||
|
[defusedxml]: https://pypi.python.org/pypi/defusedxml
|
||||||
[django-filter]: http://pypi.python.org/pypi/django-filter
|
[django-filter]: http://pypi.python.org/pypi/django-filter
|
||||||
|
|
|
@ -34,6 +34,7 @@ The following packages are optional:
|
||||||
|
|
||||||
* [Markdown][markdown] (2.1.0+) - Markdown support for the browseable API.
|
* [Markdown][markdown] (2.1.0+) - Markdown support for the browseable API.
|
||||||
* [PyYAML][yaml] (3.10+) - YAML content-type support.
|
* [PyYAML][yaml] (3.10+) - YAML content-type support.
|
||||||
|
* [defusedxml][defusedxml] (0.3+) - XML content-type support.
|
||||||
* [django-filter][django-filter] (0.5.4+) - Filtering support.
|
* [django-filter][django-filter] (0.5.4+) - Filtering support.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
@ -173,6 +174,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
[urlobject]: https://github.com/zacharyvoase/urlobject
|
[urlobject]: https://github.com/zacharyvoase/urlobject
|
||||||
[markdown]: http://pypi.python.org/pypi/Markdown/
|
[markdown]: http://pypi.python.org/pypi/Markdown/
|
||||||
[yaml]: http://pypi.python.org/pypi/PyYAML
|
[yaml]: http://pypi.python.org/pypi/PyYAML
|
||||||
|
[defusedxml]: https://pypi.python.org/pypi/defusedxml
|
||||||
[django-filter]: http://pypi.python.org/pypi/django-filter
|
[django-filter]: http://pypi.python.org/pypi/django-filter
|
||||||
[0.4]: https://github.com/tomchristie/django-rest-framework/tree/0.4.X
|
[0.4]: https://github.com/tomchristie/django-rest-framework/tree/0.4.X
|
||||||
[image]: img/quickstart.png
|
[image]: img/quickstart.png
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
markdown>=2.1.0
|
markdown>=2.1.0
|
||||||
PyYAML>=3.10
|
PyYAML>=3.10
|
||||||
|
defusedxml>=0.3
|
||||||
django-filter>=0.5.4
|
django-filter>=0.5.4
|
||||||
|
|
|
@ -421,17 +421,8 @@ except ImportError:
|
||||||
yaml = None
|
yaml = None
|
||||||
|
|
||||||
|
|
||||||
# xml.etree.parse only throws ParseError for python >= 2.7
|
# XML is optional
|
||||||
try:
|
try:
|
||||||
from xml.etree import ParseError as ETParseError
|
import defusedxml.ElementTree as etree
|
||||||
except ImportError: # python < 2.7
|
except ImportError:
|
||||||
ETParseError = None
|
etree = None
|
||||||
|
|
||||||
|
|
||||||
# XMLParser only takes an encoding arg from >= 2.7
|
|
||||||
def ET_XMLParser(encoding=None):
|
|
||||||
from xml.etree import ElementTree as ET
|
|
||||||
try:
|
|
||||||
return ET.XMLParser(encoding=encoding)
|
|
||||||
except TypeError:
|
|
||||||
return ET.XMLParser()
|
|
||||||
|
|
|
@ -9,11 +9,9 @@ from django.conf import settings
|
||||||
from django.http import QueryDict
|
from django.http import QueryDict
|
||||||
from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
|
from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
|
||||||
from django.http.multipartparser import MultiPartParserError
|
from django.http.multipartparser import MultiPartParserError
|
||||||
from rest_framework.compat import yaml, ETParseError, ET_XMLParser
|
from rest_framework.compat import yaml, etree
|
||||||
from rest_framework.exceptions import ParseError
|
from rest_framework.exceptions import ParseError
|
||||||
from rest_framework.compat import six
|
from rest_framework.compat import six
|
||||||
from xml.etree import ElementTree as ET
|
|
||||||
from xml.parsers.expat import ExpatError
|
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
import decimal
|
import decimal
|
||||||
|
@ -80,6 +78,8 @@ class YAMLParser(BaseParser):
|
||||||
`data` will be an object which is the parsed content of the response.
|
`data` will be an object which is the parsed content of the response.
|
||||||
`files` will always be `None`.
|
`files` will always be `None`.
|
||||||
"""
|
"""
|
||||||
|
assert yaml, 'YAMLParser requires pyyaml to be installed'
|
||||||
|
|
||||||
parser_context = parser_context or {}
|
parser_context = parser_context or {}
|
||||||
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
|
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
|
||||||
|
|
||||||
|
@ -146,12 +146,14 @@ class XMLParser(BaseParser):
|
||||||
media_type = 'application/xml'
|
media_type = 'application/xml'
|
||||||
|
|
||||||
def parse(self, stream, media_type=None, parser_context=None):
|
def parse(self, stream, media_type=None, parser_context=None):
|
||||||
|
assert etree, 'XMLParser requires defusedxml to be installed'
|
||||||
|
|
||||||
parser_context = parser_context or {}
|
parser_context = parser_context or {}
|
||||||
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
|
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
|
||||||
parser = ET_XMLParser(encoding=encoding)
|
parser = etree.DefusedXMLParser(encoding=encoding)
|
||||||
try:
|
try:
|
||||||
tree = ET.parse(stream, parser=parser)
|
tree = etree.parse(stream, parser=parser)
|
||||||
except (ExpatError, ETParseError, ValueError) as exc:
|
except (etree.ParseError, ValueError) as exc:
|
||||||
raise ParseError('XML parse error - %s' % six.u(exc))
|
raise ParseError('XML parse error - %s' % six.u(exc))
|
||||||
data = self._xml_convert(tree.getroot())
|
data = self._xml_convert(tree.getroot())
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ from __future__ import unicode_literals
|
||||||
from rest_framework.compat import StringIO
|
from rest_framework.compat import StringIO
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
from django.utils import unittest
|
||||||
|
from rest_framework.compat import etree
|
||||||
from rest_framework.parsers import FormParser
|
from rest_framework.parsers import FormParser
|
||||||
from rest_framework.parsers import XMLParser
|
from rest_framework.parsers import XMLParser
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -69,11 +71,13 @@ class TestXMLParser(TestCase):
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@unittest.skipUnless(etree, 'defusedxml not installed')
|
||||||
def test_parse(self):
|
def test_parse(self):
|
||||||
parser = XMLParser()
|
parser = XMLParser()
|
||||||
data = parser.parse(self._input)
|
data = parser.parse(self._input)
|
||||||
self.assertEqual(data, self._data)
|
self.assertEqual(data, self._data)
|
||||||
|
|
||||||
|
@unittest.skipUnless(etree, 'defusedxml not installed')
|
||||||
def test_complex_data_parse(self):
|
def test_complex_data_parse(self):
|
||||||
parser = XMLParser()
|
parser = XMLParser()
|
||||||
data = parser.parse(self._complex_data_input)
|
data = parser.parse(self._complex_data_input)
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
import pickle
|
from decimal import Decimal
|
||||||
import re
|
|
||||||
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
|
from django.utils import unittest
|
||||||
from rest_framework import status, permissions
|
from rest_framework import status, permissions
|
||||||
from rest_framework.compat import yaml, patterns, url, include
|
from rest_framework.compat import yaml, etree, patterns, url, include
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
|
from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
|
||||||
XMLRenderer, JSONPRenderer, BrowsableAPIRenderer
|
XMLRenderer, JSONPRenderer, BrowsableAPIRenderer
|
||||||
from rest_framework.parsers import YAMLParser, XMLParser
|
from rest_framework.parsers import YAMLParser, XMLParser
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
|
|
||||||
from rest_framework.compat import StringIO
|
from rest_framework.compat import StringIO
|
||||||
from rest_framework.compat import six
|
from rest_framework.compat import six
|
||||||
import datetime
|
import datetime
|
||||||
from decimal import Decimal
|
import pickle
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
DUMMYSTATUS = status.HTTP_200_OK
|
DUMMYSTATUS = status.HTTP_200_OK
|
||||||
|
@ -410,6 +408,7 @@ class XMLRendererTestCase(TestCase):
|
||||||
self.assertXMLContains(content, '<sub_name>first</sub_name>')
|
self.assertXMLContains(content, '<sub_name>first</sub_name>')
|
||||||
self.assertXMLContains(content, '<sub_name>second</sub_name>')
|
self.assertXMLContains(content, '<sub_name>second</sub_name>')
|
||||||
|
|
||||||
|
@unittest.skipUnless(etree, 'defusedxml not installed')
|
||||||
def test_render_and_parse_complex_data(self):
|
def test_render_and_parse_complex_data(self):
|
||||||
"""
|
"""
|
||||||
Test XML rendering.
|
Test XML rendering.
|
||||||
|
|
7
tox.ini
7
tox.ini
|
@ -9,11 +9,13 @@ commands = {envpython} rest_framework/runtests/runtests.py
|
||||||
basepython = python3.3
|
basepython = python3.3
|
||||||
deps = https://www.djangoproject.com/download/1.5c1/tarball/
|
deps = https://www.djangoproject.com/download/1.5c1/tarball/
|
||||||
https://github.com/alex/django-filter/archive/master.tar.gz
|
https://github.com/alex/django-filter/archive/master.tar.gz
|
||||||
|
defusedxml==0.3
|
||||||
|
|
||||||
[testenv:py3.2-django1.5]
|
[testenv:py3.2-django1.5]
|
||||||
basepython = python3.2
|
basepython = python3.2
|
||||||
deps = https://www.djangoproject.com/download/1.5c1/tarball/
|
deps = https://www.djangoproject.com/download/1.5c1/tarball/
|
||||||
https://github.com/alex/django-filter/archive/master.tar.gz
|
https://github.com/alex/django-filter/archive/master.tar.gz
|
||||||
|
defusedxml==0.3
|
||||||
|
|
||||||
[testenv:py2.7-django1.5]
|
[testenv:py2.7-django1.5]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
|
@ -24,23 +26,28 @@ deps = https://www.djangoproject.com/download/1.5c1/tarball/
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
deps = https://www.djangoproject.com/download/1.5c1/tarball/
|
deps = https://www.djangoproject.com/download/1.5c1/tarball/
|
||||||
django-filter==0.5.4
|
django-filter==0.5.4
|
||||||
|
defusedxml==0.3
|
||||||
|
|
||||||
[testenv:py2.7-django1.4]
|
[testenv:py2.7-django1.4]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps = django==1.4.3
|
deps = django==1.4.3
|
||||||
django-filter==0.5.4
|
django-filter==0.5.4
|
||||||
|
defusedxml==0.3
|
||||||
|
|
||||||
[testenv:py2.6-django1.4]
|
[testenv:py2.6-django1.4]
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
deps = django==1.4.3
|
deps = django==1.4.3
|
||||||
django-filter==0.5.4
|
django-filter==0.5.4
|
||||||
|
defusedxml==0.3
|
||||||
|
|
||||||
[testenv:py2.7-django1.3]
|
[testenv:py2.7-django1.3]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps = django==1.3.5
|
deps = django==1.3.5
|
||||||
django-filter==0.5.4
|
django-filter==0.5.4
|
||||||
|
defusedxml==0.3
|
||||||
|
|
||||||
[testenv:py2.6-django1.3]
|
[testenv:py2.6-django1.3]
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
deps = django==1.3.5
|
deps = django==1.3.5
|
||||||
django-filter==0.5.4
|
django-filter==0.5.4
|
||||||
|
defusedxml==0.3
|
||||||
|
|
Loading…
Reference in New Issue
Block a user