Ver código fonte

[libs] Adding django-cors-headers 2.5.3

Last one with Python 2 compat.
Romain Rigaux 4 anos atrás
pai
commit
8cb6c7bb26
27 arquivos alterados com 2431 adições e 0 exclusões
  1. 212 0
      desktop/core/ext-py/django-cors-headers-2.5.3/HISTORY.rst
  2. 1 0
      desktop/core/ext-py/django-cors-headers-2.5.3/LICENSE
  3. 5 0
      desktop/core/ext-py/django-cors-headers-2.5.3/MANIFEST.in
  4. 612 0
      desktop/core/ext-py/django-cors-headers-2.5.3/PKG-INFO
  5. 367 0
      desktop/core/ext-py/django-cors-headers-2.5.3/README.rst
  6. 3 0
      desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/__init__.py
  7. 118 0
      desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/checks.py
  8. 58 0
      desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/conf.py
  9. 20 0
      desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/defaults.py
  10. 178 0
      desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/middleware.py
  11. 11 0
      desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/models.py
  12. 8 0
      desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/signals.py
  13. 5 0
      desktop/core/ext-py/django-cors-headers-2.5.3/pytest.ini
  14. 37 0
      desktop/core/ext-py/django-cors-headers-2.5.3/requirements.txt
  15. 17 0
      desktop/core/ext-py/django-cors-headers-2.5.3/runtests.py
  16. 28 0
      desktop/core/ext-py/django-cors-headers-2.5.3/setup.cfg
  17. 63 0
      desktop/core/ext-py/django-cors-headers-2.5.3/setup.py
  18. 0 0
      desktop/core/ext-py/django-cors-headers-2.5.3/tests/__init__.py
  19. 30 0
      desktop/core/ext-py/django-cors-headers-2.5.3/tests/settings.py
  20. 99 0
      desktop/core/ext-py/django-cors-headers-2.5.3/tests/test_checks.py
  21. 13 0
      desktop/core/ext-py/django-cors-headers-2.5.3/tests/test_conf.py
  22. 453 0
      desktop/core/ext-py/django-cors-headers-2.5.3/tests/test_middleware.py
  23. 0 0
      desktop/core/ext-py/django-cors-headers-2.5.3/tests/testapp/__init__.py
  24. 7 0
      desktop/core/ext-py/django-cors-headers-2.5.3/tests/testapp/models.py
  25. 28 0
      desktop/core/ext-py/django-cors-headers-2.5.3/tests/urls.py
  26. 32 0
      desktop/core/ext-py/django-cors-headers-2.5.3/tests/utils.py
  27. 26 0
      desktop/core/ext-py/django-cors-headers-2.5.3/tox.ini

+ 212 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/HISTORY.rst

@@ -0,0 +1,212 @@
+History
+=======
+
+Pending
+-------
+
+.. Insert new release notes below this line
+
+2.5.3 (2019-04-28)
+------------------
+
+* Tested on Django 2.2. No changes were needed for compatibility.
+* Tested on Python 3.7. No changes were needed for compatibility.
+
+2.5.2 (2019-03-15)
+------------------
+
+* Improve inclusion of tests in ``sdist`` to ignore ``.pyc`` files.
+
+2.5.1 (2019-03-13)
+------------------
+
+* Include test infrastructure in ``sdist`` to allow consumers to use it.
+
+2.5.0 (2019-03-05)
+------------------
+
+* Drop Django 1.8, 1.9, and 1.10 support. Only Django 1.11+ is supported now.
+
+2.4.1 (2019-02-28)
+------------------
+
+* Fix ``DeprecationWarning`` from importing ``collections.abc.Sequence`` on
+  Python 3.7.
+
+2.4.0 (2018-07-18)
+------------------
+
+* Always add 'Origin' to the 'Vary' header for responses to enabled URL's,
+  to prevent caching of responses intended for one origin being served for
+  another.
+
+2.3.0 (2018-06-27)
+------------------
+
+* Match ``CORS_URLS_REGEX`` to ``request.path_info`` instead of
+  ``request.path``, so the patterns can work without knowing the site's path
+  prefix at configuration time.
+
+2.2.1 (2018-06-27)
+------------------
+
+* Add ``Content-Length`` header to CORS preflight requests. This fixes issues
+  with some HTTP proxies and servers, e.g. AWS Elastic Beanstalk.
+
+2.2.0 (2018-02-28)
+------------------
+
+* Django 2.0 compatibility. Again there were no changes to the actual library
+  code, so previous versions probably work.
+* Ensured that ``request._cors_enabled`` is always a ``bool()`` - previously it
+  could be set to a regex match object.
+
+2.1.0 (2017-05-28)
+------------------
+
+* Django 1.11 compatibility. There were no changes to the actual library code,
+  so previous versions probably work, though they weren't properly tested on
+  1.11.
+
+2.0.2 (2017-02-06)
+------------------
+
+* Fix when the check for ``CORS_MODEL`` is done to allow it to properly add
+  the headers and respond to ``OPTIONS`` requests.
+
+2.0.1 (2017-01-29)
+------------------
+
+* Add support for specifying 'null' in ``CORS_ORIGIN_WHITELIST``.
+
+2.0.0 (2017-01-07)
+------------------
+
+* Remove previously undocumented ``CorsModel`` as it was causing migration
+  issues. For backwards compatibility, any users previously using ``CorsModel``
+  should create a model in their own app that inherits from the new
+  ``AbstractCorsModel``, and to keep using the same data, set the model's
+  ``db_table`` to 'corsheaders_corsmodel'. Users not using ``CorsModel``
+  will find they have an unused table that they can drop.
+* Make sure that ``Access-Control-Allow-Credentials`` is in the response if the
+  client asks for it.
+
+1.3.1 (2016-11-09)
+------------------
+
+* Fix a bug with the single check if CORS enabled added in 1.3.0: on Django
+  < 1.10 shortcut responses could be generated by middleware above
+  ``CorsMiddleware``, before it processed the request, failing with an
+  ``AttributeError`` for ``request._cors_enabled``. Also clarified the docs
+  that ``CorsMiddleware`` should be kept as high as possible in your middleware
+  stack, above any middleware that can generate such responses.
+
+1.3.0 (2016-11-06)
+------------------
+
+* Add checks to validate the types of the settings.
+* Add the 'Do Not Track' header ``'DNT'`` to the default for
+  ``CORS_ALLOW_HEADERS``.
+* Add 'Origin' to the 'Vary' header of outgoing requests when not allowing all
+  origins, as per the CORS spec. Note this changes the way HTTP caching works
+  with your CORS-enabled responses.
+* Check whether CORS should be enabled on a request only once. This has had a
+  minor change on the conditions where any custom signals will be called -
+  signals will now always be called *before* ``HTTP_REFERER`` gets replaced,
+  whereas before they could be called before and after. Also this attaches the
+  attribute ``_cors_enabled`` to ``request`` - please take care that other
+  code you're running does not remove it.
+
+1.2.2 (2016-10-05)
+------------------
+
+* Add ``CorsModel.__str__`` for human-readable text
+* Add a signal that allows you to add code for more intricate control over when
+  CORS headers are added.
+
+1.2.1 (2016-09-30)
+------------------
+
+* Made settings dynamically respond to changes, and which allows you to import
+  the defaults for headers and methods in order to extend them.
+
+1.2.0 (2016-09-28)
+------------------
+
+* Drop Python 2.6 support.
+* Drop Django 1.3-1.7 support, as they are no longer supported.
+* Confirmed Django 1.9 support (no changes outside of tests were necessary).
+* Added Django 1.10 support.
+* Package as a universal wheel.
+
+1.1.0 (2014-12-15)
+------------------
+
+* django-cors-header now supports Django 1.8 with its new application loading
+  system! Thanks @jpadilla for making this possible and sorry for the delay in
+  making a release.
+
+1.0.0 (2014-12-13)
+------------------
+
+django-cors-headers is all grown-up :) Since it's been used in production for
+many many deployments, I think it's time we mark this as a stable release.
+
+* Switching this middleware versioning over to semantic versioning
+* #46 add user-agent and accept-encoding default headers
+* #45 pep-8 this big boy up
+
+0.13 (2014-08-14)
+-----------------
+
+* Add support for Python 3
+* Updated tests
+* Improved docuemntation
+* Small bugfixes
+
+0.12 (2013-09-24)
+-----------------
+
+* Added an option to selectively enable CORS only for specific URLs
+
+0.11 (2013-09-24)
+
+* Added the ability to specify a regex for whitelisting many origin hostnames
+  at once
+
+0.10 (2013-09-05)
+-----------------
+
+* Introduced port distinction for origin checking
+* Use ``urlparse`` for Python 3 support
+* Added testcases to project
+
+0.06 (2013-02-18)
+-----------------
+
+* Add support for exposed response headers
+
+0.05 (2013-01-26)
+-----------------
+
+* Fixed middleware to ensure correct response for CORS preflight requests
+
+0.04 (2013-01-25)
+-----------------
+
+* Add ``Access-Control-Allow-Credentials`` control to simple requests
+
+0.03 (2013-01-22)
+-----------------
+
+* Bugfix to repair mismatched default variable names
+
+0.02 (2013-01-19)
+-----------------
+
+* Refactor/pull defaults into separate file
+
+0.01 (2013-01-19)
+-----------------
+
+* Initial release

+ 1 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/LICENSE

@@ -0,0 +1 @@
+Copyright 2017 Otto Yiu and other contributors
http://ottoyiu.com

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 5 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/MANIFEST.in

@@ -0,0 +1,5 @@
+include HISTORY.rst README.rst
+include LICENSE
+include runtests.py tox.ini pytest.ini requirements.txt
+graft tests
+global-exclude *.py[cod] __pycache__

+ 612 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/PKG-INFO

@@ -0,0 +1,612 @@
+Metadata-Version: 1.2
+Name: django-cors-headers
+Version: 2.5.3
+Summary: django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS).
+Home-page: https://github.com/ottoyiu/django-cors-headers
+Author: Otto Yiu
+Author-email: otto@live.ca
+License: MIT License
+Description: django-cors-headers
+        ===================
+        
+        A Django App that adds CORS (Cross-Origin Resource Sharing) headers to
+        responses.
+        
+        Although JSON-P is useful, it is strictly limited to GET requests. CORS
+        builds on top of ``XmlHttpRequest`` to allow developers to make cross-domain
+        requests, similar to same-domain requests. Read more about it here:
+        http://www.html5rocks.com/en/tutorials/cors/
+        
+        .. image:: https://travis-ci.org/ottoyiu/django-cors-headers.svg?branch=master
+           :target: https://travis-ci.org/ottoyiu/django-cors-headers
+        
+        
+        Requirements
+        ------------
+        
+        Tested with all combinations of:
+        
+        * Python: 2.7, 3.5, 3.6, 3.7
+        * Django: 1.11, 2.0, 2.1, 2.2
+        
+        Setup
+        -----
+        
+        Install from **pip**:
+        
+        .. code-block:: sh
+        
+            pip install django-cors-headers
+        
+        and then add it to your installed apps:
+        
+        .. code-block:: python
+        
+            INSTALLED_APPS = (
+                ...
+                'corsheaders',
+                ...
+            )
+        
+        You will also need to add a middleware class to listen in on responses:
+        
+        .. code-block:: python
+        
+            MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
+                ...
+                'corsheaders.middleware.CorsMiddleware',
+                'django.middleware.common.CommonMiddleware',
+                ...
+            ]
+        
+        ``CorsMiddleware`` should be placed as high as possible, especially before any
+        middleware that can generate responses such as Django's ``CommonMiddleware`` or
+        Whitenoise's ``WhiteNoiseMiddleware``. If it is not before, it will not be able
+        to add the CORS headers to these responses.
+        
+        Also if you are using ``CORS_REPLACE_HTTPS_REFERER`` it should be placed before
+        Django's ``CsrfViewMiddleware`` (see more below).
+        
+        About
+        -----
+        
+        **django-cors-headers** was created in January 2013 by Otto Yiu. It went
+        unmaintained from August 2015 and was forked in January 2016 to the package
+        `django-cors-middleware <https://github.com/zestedesavoir/django-cors-middleware>`_
+        by Laville Augustin at Zeste de Savoir.
+        In September 2016, Adam Johnson, Ed Morley, and others gained maintenance
+        responsibility for **django-cors-headers**
+        (`Issue 110 <https://github.com/ottoyiu/django-cors-headers/issues/110>`_) from
+        Otto Yiu.
+        Basically all of the changes in the forked **django-cors-middleware** were
+        merged back, or re-implemented in a different way, so it should be possible to
+        switch back. If there's a feature that hasn't been merged, please open an issue
+        about it.
+        
+        **django-cors-headers** has had `40+
+        contributors <https://github.com/ottoyiu/django-cors-headers/graphs/contributors>`_
+        in its time; thanks to every one of them.
+        
+        Configuration
+        -------------
+        
+        Configure the middleware's behaviour in your Django settings. You must add the
+        hosts that are allowed to do cross-site requests to
+        ``CORS_ORIGIN_WHITELIST``, or set ``CORS_ORIGIN_ALLOW_ALL`` to ``True``
+        to allow all hosts.
+        
+        ``CORS_ORIGIN_ALLOW_ALL``
+        ~~~~~~~~~~~~~~~~~~~~~~~~~
+        If ``True``, the whitelist will not be used and all origins will be accepted.
+        Defaults to ``False``.
+        
+        ``CORS_ORIGIN_WHITELIST``
+        ~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        A list of origin hostnames that are authorized to make cross-site HTTP
+        requests. The value ``'null'`` can also appear in this list, and will match the
+        ``Origin: null`` header that is used in `"privacy-sensitive contexts"
+        <https://tools.ietf.org/html/rfc6454#section-6>`_, such as when the client is
+        running from a ``file://`` domain. Defaults to ``[]``.
+        
+        Example:
+        
+        .. code-block:: python
+        
+            CORS_ORIGIN_WHITELIST = (
+                'google.com',
+                'hostname.example.com',
+                'localhost:8000',
+                '127.0.0.1:9000'
+            )
+        
+        
+        ``CORS_ORIGIN_REGEX_WHITELIST``
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        A list of regexes that match origin regex list of origin hostnames that are
+        authorized to make cross-site HTTP requests. Defaults to ``[]``. Useful when
+        ``CORS_ORIGIN_WHITELIST`` is impractical, such as when you have a large
+        number of subdomains.
+        
+        Example:
+        
+        .. code-block:: python
+        
+            CORS_ORIGIN_REGEX_WHITELIST = (r'^(https?://)?(\w+\.)?google\.com$', )
+        
+        --------------
+        
+        The following are optional settings, for which the defaults probably suffice.
+        
+        ``CORS_URLS_REGEX``
+        ~~~~~~~~~~~~~~~~~~~
+        
+        A regex which restricts the URL's for which the CORS headers will be sent.
+        Defaults to ``r'^.*$'``, i.e. match all URL's. Useful when you only need CORS
+        on a part of your site, e.g. an API at ``/api/``.
+        
+        Example:
+        
+        .. code-block:: python
+        
+            CORS_URLS_REGEX = r'^/api/.*$'
+        
+        ``CORS_ALLOW_METHODS``
+        ~~~~~~~~~~~~~~~~~~~~~~
+        
+        A list of HTTP verbs that are allowed for the actual request. Defaults to:
+        
+        .. code-block:: python
+        
+            CORS_ALLOW_METHODS = (
+                'DELETE',
+                'GET',
+                'OPTIONS',
+                'PATCH',
+                'POST',
+                'PUT',
+            )
+        
+        The default can be imported as ``corsheaders.defaults.default_methods`` so you
+        can just extend it with your custom methods. This allows you to keep up to date
+        with any future changes. For example:
+        
+        .. code-block:: python
+        
+            from corsheaders.defaults import default_methods
+        
+            CORS_ALLOW_METHODS = default_methods + (
+                'POKE',
+            )
+        
+        ``CORS_ALLOW_HEADERS``
+        ~~~~~~~~~~~~~~~~~~~~~~
+        
+        The list of non-standard HTTP headers that can be used when making the actual
+        request. Defaults to:
+        
+        .. code-block:: python
+        
+            CORS_ALLOW_HEADERS = (
+                'accept',
+                'accept-encoding',
+                'authorization',
+                'content-type',
+                'dnt',
+                'origin',
+                'user-agent',
+                'x-csrftoken',
+                'x-requested-with',
+            )
+        
+        The default can be imported as ``corsheaders.defaults.default_headers`` so you
+        can extend it with your custom headers. This allows you to keep up to date with
+        any future changes. For example:
+        
+        .. code-block:: python
+        
+            from corsheaders.defaults import default_headers
+        
+            CORS_ALLOW_HEADERS = default_headers + (
+                'my-custom-header',
+            )
+        
+        ``CORS_EXPOSE_HEADERS``
+        ~~~~~~~~~~~~~~~~~~~~~~~
+        
+        The list of HTTP headers that are to be exposed to the browser. Defaults to
+        ``[]``.
+        
+        
+        ``CORS_PREFLIGHT_MAX_AGE``
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        The number of seconds a client/browser can cache the preflight response. If
+        this is 0 (or any falsey value), no max age header will be sent. Defaults to
+        ``86400`` (one day).
+        
+        
+        **Note:** A preflight request is an extra request that is made when making a
+        "not-so-simple" request (e.g. ``Content-Type`` is not
+        ``application/x-www-form-urlencoded``) to determine what requests the server
+        actually accepts. Read more about it in the `HTML 5 Rocks CORS tutorial
+        <https://www.html5rocks.com/en/tutorials/cors/>`_.
+        
+        ``CORS_ALLOW_CREDENTIALS``
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        If ``True``, cookies will be allowed to be included in cross-site HTTP
+        requests. Defaults to ``False``.
+        
+        Note: in Django 2.1 the `SESSION_COOKIE_SAMESITE`_ setting was added, set to
+        ``'Lax'`` by default, which will prevent Django's session cookie being sent
+        cross-domain. Change it to ``None`` to bypass this security restriction.
+        
+        .. _SESSION_COOKIE_SAMESITE: https://docs.djangoproject.com/en/2.1/ref/settings/#std:setting-SESSION_COOKIE_SAMESITE
+        
+        ``CORS_MODEL``
+        ~~~~~~~~~~~~~~
+        
+        If set, this should be the path to a model to look up allowed origins, in the
+        form ``app.modelname``. Defaults to ``None``.
+        
+        The model should inherit from ``corsheaders.models.AbstractCorsModel`` and specify
+        the allowed origin in the ``CharField`` called ``cors``.
+        
+        CSRF Integration
+        ----------------
+        
+        Most sites will need to take advantage of the `Cross-Site Request Forgery
+        protection <https://docs.djangoproject.com/en/dev/ref/csrf/>`_ that Django
+        offers. CORS and CSRF are separate, and Django has no way of using your CORS
+        configuration to exempt sites from the ``Referer`` checking that it does on
+        secure requests. The way to do that is with its `CSRF_TRUSTED_ORIGINS setting
+        <https://docs.djangoproject.com/en/dev/ref/settings/#csrf-trusted-origins>`_.
+        For example:
+        
+        .. code-block:: python
+        
+            CORS_ORIGIN_WHITELIST = (
+                'read.only.com',
+                'change.allowed.com',
+            )
+        
+            CSRF_TRUSTED_ORIGINS = (
+                'change.allowed.com',
+            )
+        
+        ``CORS_REPLACE_HTTPS_REFERER``
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        
+        ``CSRF_TRUSTED_ORIGINS`` was introduced in Django 1.9, so users of earlier
+        versions will need an alternate solution. If ``CORS_REPLACE_HTTPS_REFERER`` is
+        ``True``, ``CorsMiddleware`` will change the ``Referer`` header to something
+        that will pass Django's CSRF checks whenever the CORS checks pass. Defaults to
+        ``False``.
+        
+        Note that unlike ``CSRF_TRUSTED_ORIGINS``, this setting does not allow you to
+        distinguish between domains that are trusted to *read* resources by CORS and
+        domains that are trusted to *change* resources by avoiding CSRF protection.
+        
+        With this feature enabled you should also add
+        ``corsheaders.middleware.CorsPostCsrfMiddleware`` after
+        ``django.middleware.csrf.CsrfViewMiddleware`` in your ``MIDDLEWARE_CLASSES`` to
+        undo the ``Referer`` replacement:
+        
+        .. code-block:: python
+        
+            MIDDLEWARE_CLASSES = [
+                ...
+                'corsheaders.middleware.CorsMiddleware',
+                ...
+                'django.middleware.csrf.CsrfViewMiddleware',
+                'corsheaders.middleware.CorsPostCsrfMiddleware',
+                ...
+            ]
+        
+        Signals
+        -------
+        
+        If you have a use case that requires more than just the above configuration,
+        you can attach code to check if a given request should be allowed. For example,
+        this can be used to read the list of origins you allow from a model. Attach any
+        number of handlers to the ``check_request_enabled``
+        `Django signal <https://docs.djangoproject.com/en/1.10/ref/signals/>`_, which
+        provides the ``request`` argument (use ``**kwargs`` in your handler to protect
+        against any future arguments being added). If any handler attached to the
+        signal returns a truthy value, the request will be allowed.
+        
+        For example you might define a handler like this:
+        
+        .. code-block:: python
+        
+            # myapp/handlers.py
+            from corsheaders.signals import check_request_enabled
+        
+            from .models import MySite
+        
+            def cors_allow_mysites(sender, request, **kwargs):
+                return MySite.objects.filter(host=request.host).exists()
+        
+            check_request_enabled.connect(cors_allow_mysites)
+        
+        Then connect it at app ready time using a `Django AppConfig
+        <https://docs.djangoproject.com/en/1.10/ref/applications/>`_:
+        
+        .. code-block:: python
+        
+            # myapp/__init__.py
+        
+            default_app_config = 'myapp.apps.MyAppConfig'
+        
+        .. code-block:: python
+        
+            # myapp/apps.py
+        
+            from django.apps import AppConfig
+        
+            class MyAppConfig(AppConfig):
+                name = 'myapp'
+        
+                def ready(self):
+                    # Makes sure all signal handlers are connected
+                    from . import handlers  # noqa
+        
+        
+        A common use case for the signal is to allow *all* origins to access a subset
+        of URL's, whilst allowing a normal set of origins to access *all* URL's. This
+        isn't possible using just the normal configuration, but it can be achieved with
+        a signal handler.
+        
+        First set ``CORS_ORIGIN_WHITELIST`` to the list of trusted origins that are
+        allowed to access every URL, and then add a handler to
+        ``check_request_enabled`` to allow CORS regardless of the origin for the
+        unrestricted URL's. For example:
+        
+        .. code-block:: python
+        
+            # myapp/handlers.py
+            from corsheaders.signals import check_request_enabled
+        
+            def cors_allow_api_to_everyone(sender, request, **kwargs):
+                return request.path.startswith('/api/')
+        
+            check_request_enabled.connect(cors_allow_api_to_everyone)
+        
+        
+        History
+        =======
+        
+        Pending
+        -------
+        
+        .. Insert new release notes below this line
+        
+        2.5.3 (2019-04-28)
+        ------------------
+        
+        * Tested on Django 2.2. No changes were needed for compatibility.
+        * Tested on Python 3.7. No changes were needed for compatibility.
+        
+        2.5.2 (2019-03-15)
+        ------------------
+        
+        * Improve inclusion of tests in ``sdist`` to ignore ``.pyc`` files.
+        
+        2.5.1 (2019-03-13)
+        ------------------
+        
+        * Include test infrastructure in ``sdist`` to allow consumers to use it.
+        
+        2.5.0 (2019-03-05)
+        ------------------
+        
+        * Drop Django 1.8, 1.9, and 1.10 support. Only Django 1.11+ is supported now.
+        
+        2.4.1 (2019-02-28)
+        ------------------
+        
+        * Fix ``DeprecationWarning`` from importing ``collections.abc.Sequence`` on
+          Python 3.7.
+        
+        2.4.0 (2018-07-18)
+        ------------------
+        
+        * Always add 'Origin' to the 'Vary' header for responses to enabled URL's,
+          to prevent caching of responses intended for one origin being served for
+          another.
+        
+        2.3.0 (2018-06-27)
+        ------------------
+        
+        * Match ``CORS_URLS_REGEX`` to ``request.path_info`` instead of
+          ``request.path``, so the patterns can work without knowing the site's path
+          prefix at configuration time.
+        
+        2.2.1 (2018-06-27)
+        ------------------
+        
+        * Add ``Content-Length`` header to CORS preflight requests. This fixes issues
+          with some HTTP proxies and servers, e.g. AWS Elastic Beanstalk.
+        
+        2.2.0 (2018-02-28)
+        ------------------
+        
+        * Django 2.0 compatibility. Again there were no changes to the actual library
+          code, so previous versions probably work.
+        * Ensured that ``request._cors_enabled`` is always a ``bool()`` - previously it
+          could be set to a regex match object.
+        
+        2.1.0 (2017-05-28)
+        ------------------
+        
+        * Django 1.11 compatibility. There were no changes to the actual library code,
+          so previous versions probably work, though they weren't properly tested on
+          1.11.
+        
+        2.0.2 (2017-02-06)
+        ------------------
+        
+        * Fix when the check for ``CORS_MODEL`` is done to allow it to properly add
+          the headers and respond to ``OPTIONS`` requests.
+        
+        2.0.1 (2017-01-29)
+        ------------------
+        
+        * Add support for specifying 'null' in ``CORS_ORIGIN_WHITELIST``.
+        
+        2.0.0 (2017-01-07)
+        ------------------
+        
+        * Remove previously undocumented ``CorsModel`` as it was causing migration
+          issues. For backwards compatibility, any users previously using ``CorsModel``
+          should create a model in their own app that inherits from the new
+          ``AbstractCorsModel``, and to keep using the same data, set the model's
+          ``db_table`` to 'corsheaders_corsmodel'. Users not using ``CorsModel``
+          will find they have an unused table that they can drop.
+        * Make sure that ``Access-Control-Allow-Credentials`` is in the response if the
+          client asks for it.
+        
+        1.3.1 (2016-11-09)
+        ------------------
+        
+        * Fix a bug with the single check if CORS enabled added in 1.3.0: on Django
+          < 1.10 shortcut responses could be generated by middleware above
+          ``CorsMiddleware``, before it processed the request, failing with an
+          ``AttributeError`` for ``request._cors_enabled``. Also clarified the docs
+          that ``CorsMiddleware`` should be kept as high as possible in your middleware
+          stack, above any middleware that can generate such responses.
+        
+        1.3.0 (2016-11-06)
+        ------------------
+        
+        * Add checks to validate the types of the settings.
+        * Add the 'Do Not Track' header ``'DNT'`` to the default for
+          ``CORS_ALLOW_HEADERS``.
+        * Add 'Origin' to the 'Vary' header of outgoing requests when not allowing all
+          origins, as per the CORS spec. Note this changes the way HTTP caching works
+          with your CORS-enabled responses.
+        * Check whether CORS should be enabled on a request only once. This has had a
+          minor change on the conditions where any custom signals will be called -
+          signals will now always be called *before* ``HTTP_REFERER`` gets replaced,
+          whereas before they could be called before and after. Also this attaches the
+          attribute ``_cors_enabled`` to ``request`` - please take care that other
+          code you're running does not remove it.
+        
+        1.2.2 (2016-10-05)
+        ------------------
+        
+        * Add ``CorsModel.__str__`` for human-readable text
+        * Add a signal that allows you to add code for more intricate control over when
+          CORS headers are added.
+        
+        1.2.1 (2016-09-30)
+        ------------------
+        
+        * Made settings dynamically respond to changes, and which allows you to import
+          the defaults for headers and methods in order to extend them.
+        
+        1.2.0 (2016-09-28)
+        ------------------
+        
+        * Drop Python 2.6 support.
+        * Drop Django 1.3-1.7 support, as they are no longer supported.
+        * Confirmed Django 1.9 support (no changes outside of tests were necessary).
+        * Added Django 1.10 support.
+        * Package as a universal wheel.
+        
+        1.1.0 (2014-12-15)
+        ------------------
+        
+        * django-cors-header now supports Django 1.8 with its new application loading
+          system! Thanks @jpadilla for making this possible and sorry for the delay in
+          making a release.
+        
+        1.0.0 (2014-12-13)
+        ------------------
+        
+        django-cors-headers is all grown-up :) Since it's been used in production for
+        many many deployments, I think it's time we mark this as a stable release.
+        
+        * Switching this middleware versioning over to semantic versioning
+        * #46 add user-agent and accept-encoding default headers
+        * #45 pep-8 this big boy up
+        
+        0.13 (2014-08-14)
+        -----------------
+        
+        * Add support for Python 3
+        * Updated tests
+        * Improved docuemntation
+        * Small bugfixes
+        
+        0.12 (2013-09-24)
+        -----------------
+        
+        * Added an option to selectively enable CORS only for specific URLs
+        
+        0.11 (2013-09-24)
+        
+        * Added the ability to specify a regex for whitelisting many origin hostnames
+          at once
+        
+        0.10 (2013-09-05)
+        -----------------
+        
+        * Introduced port distinction for origin checking
+        * Use ``urlparse`` for Python 3 support
+        * Added testcases to project
+        
+        0.06 (2013-02-18)
+        -----------------
+        
+        * Add support for exposed response headers
+        
+        0.05 (2013-01-26)
+        -----------------
+        
+        * Fixed middleware to ensure correct response for CORS preflight requests
+        
+        0.04 (2013-01-25)
+        -----------------
+        
+        * Add ``Access-Control-Allow-Credentials`` control to simple requests
+        
+        0.03 (2013-01-22)
+        -----------------
+        
+        * Bugfix to repair mismatched default variable names
+        
+        0.02 (2013-01-19)
+        -----------------
+        
+        * Refactor/pull defaults into separate file
+        
+        0.01 (2013-01-19)
+        -----------------
+        
+        * Initial release
+        
+Keywords: django,cors,middleware,rest,api
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Web Environment
+Classifier: Framework :: Django
+Classifier: Framework :: Django :: 1.11
+Classifier: Framework :: Django :: 2.0
+Classifier: Framework :: Django :: 2.1
+Classifier: Framework :: Django :: 2.2
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*

+ 367 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/README.rst

@@ -0,0 +1,367 @@
+django-cors-headers
+===================
+
+A Django App that adds CORS (Cross-Origin Resource Sharing) headers to
+responses.
+
+Although JSON-P is useful, it is strictly limited to GET requests. CORS
+builds on top of ``XmlHttpRequest`` to allow developers to make cross-domain
+requests, similar to same-domain requests. Read more about it here:
+http://www.html5rocks.com/en/tutorials/cors/
+
+.. image:: https://travis-ci.org/ottoyiu/django-cors-headers.svg?branch=master
+   :target: https://travis-ci.org/ottoyiu/django-cors-headers
+
+
+Requirements
+------------
+
+Tested with all combinations of:
+
+* Python: 2.7, 3.5, 3.6, 3.7
+* Django: 1.11, 2.0, 2.1, 2.2
+
+Setup
+-----
+
+Install from **pip**:
+
+.. code-block:: sh
+
+    pip install django-cors-headers
+
+and then add it to your installed apps:
+
+.. code-block:: python
+
+    INSTALLED_APPS = (
+        ...
+        'corsheaders',
+        ...
+    )
+
+You will also need to add a middleware class to listen in on responses:
+
+.. code-block:: python
+
+    MIDDLEWARE = [  # Or MIDDLEWARE_CLASSES on Django < 1.10
+        ...
+        'corsheaders.middleware.CorsMiddleware',
+        'django.middleware.common.CommonMiddleware',
+        ...
+    ]
+
+``CorsMiddleware`` should be placed as high as possible, especially before any
+middleware that can generate responses such as Django's ``CommonMiddleware`` or
+Whitenoise's ``WhiteNoiseMiddleware``. If it is not before, it will not be able
+to add the CORS headers to these responses.
+
+Also if you are using ``CORS_REPLACE_HTTPS_REFERER`` it should be placed before
+Django's ``CsrfViewMiddleware`` (see more below).
+
+About
+-----
+
+**django-cors-headers** was created in January 2013 by Otto Yiu. It went
+unmaintained from August 2015 and was forked in January 2016 to the package
+`django-cors-middleware <https://github.com/zestedesavoir/django-cors-middleware>`_
+by Laville Augustin at Zeste de Savoir.
+In September 2016, Adam Johnson, Ed Morley, and others gained maintenance
+responsibility for **django-cors-headers**
+(`Issue 110 <https://github.com/ottoyiu/django-cors-headers/issues/110>`_) from
+Otto Yiu.
+Basically all of the changes in the forked **django-cors-middleware** were
+merged back, or re-implemented in a different way, so it should be possible to
+switch back. If there's a feature that hasn't been merged, please open an issue
+about it.
+
+**django-cors-headers** has had `40+
+contributors <https://github.com/ottoyiu/django-cors-headers/graphs/contributors>`_
+in its time; thanks to every one of them.
+
+Configuration
+-------------
+
+Configure the middleware's behaviour in your Django settings. You must add the
+hosts that are allowed to do cross-site requests to
+``CORS_ORIGIN_WHITELIST``, or set ``CORS_ORIGIN_ALLOW_ALL`` to ``True``
+to allow all hosts.
+
+``CORS_ORIGIN_ALLOW_ALL``
+~~~~~~~~~~~~~~~~~~~~~~~~~
+If ``True``, the whitelist will not be used and all origins will be accepted.
+Defaults to ``False``.
+
+``CORS_ORIGIN_WHITELIST``
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A list of origin hostnames that are authorized to make cross-site HTTP
+requests. The value ``'null'`` can also appear in this list, and will match the
+``Origin: null`` header that is used in `"privacy-sensitive contexts"
+<https://tools.ietf.org/html/rfc6454#section-6>`_, such as when the client is
+running from a ``file://`` domain. Defaults to ``[]``.
+
+Example:
+
+.. code-block:: python
+
+    CORS_ORIGIN_WHITELIST = (
+        'google.com',
+        'hostname.example.com',
+        'localhost:8000',
+        '127.0.0.1:9000'
+    )
+
+
+``CORS_ORIGIN_REGEX_WHITELIST``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A list of regexes that match origin regex list of origin hostnames that are
+authorized to make cross-site HTTP requests. Defaults to ``[]``. Useful when
+``CORS_ORIGIN_WHITELIST`` is impractical, such as when you have a large
+number of subdomains.
+
+Example:
+
+.. code-block:: python
+
+    CORS_ORIGIN_REGEX_WHITELIST = (r'^(https?://)?(\w+\.)?google\.com$', )
+
+--------------
+
+The following are optional settings, for which the defaults probably suffice.
+
+``CORS_URLS_REGEX``
+~~~~~~~~~~~~~~~~~~~
+
+A regex which restricts the URL's for which the CORS headers will be sent.
+Defaults to ``r'^.*$'``, i.e. match all URL's. Useful when you only need CORS
+on a part of your site, e.g. an API at ``/api/``.
+
+Example:
+
+.. code-block:: python
+
+    CORS_URLS_REGEX = r'^/api/.*$'
+
+``CORS_ALLOW_METHODS``
+~~~~~~~~~~~~~~~~~~~~~~
+
+A list of HTTP verbs that are allowed for the actual request. Defaults to:
+
+.. code-block:: python
+
+    CORS_ALLOW_METHODS = (
+        'DELETE',
+        'GET',
+        'OPTIONS',
+        'PATCH',
+        'POST',
+        'PUT',
+    )
+
+The default can be imported as ``corsheaders.defaults.default_methods`` so you
+can just extend it with your custom methods. This allows you to keep up to date
+with any future changes. For example:
+
+.. code-block:: python
+
+    from corsheaders.defaults import default_methods
+
+    CORS_ALLOW_METHODS = default_methods + (
+        'POKE',
+    )
+
+``CORS_ALLOW_HEADERS``
+~~~~~~~~~~~~~~~~~~~~~~
+
+The list of non-standard HTTP headers that can be used when making the actual
+request. Defaults to:
+
+.. code-block:: python
+
+    CORS_ALLOW_HEADERS = (
+        'accept',
+        'accept-encoding',
+        'authorization',
+        'content-type',
+        'dnt',
+        'origin',
+        'user-agent',
+        'x-csrftoken',
+        'x-requested-with',
+    )
+
+The default can be imported as ``corsheaders.defaults.default_headers`` so you
+can extend it with your custom headers. This allows you to keep up to date with
+any future changes. For example:
+
+.. code-block:: python
+
+    from corsheaders.defaults import default_headers
+
+    CORS_ALLOW_HEADERS = default_headers + (
+        'my-custom-header',
+    )
+
+``CORS_EXPOSE_HEADERS``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The list of HTTP headers that are to be exposed to the browser. Defaults to
+``[]``.
+
+
+``CORS_PREFLIGHT_MAX_AGE``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The number of seconds a client/browser can cache the preflight response. If
+this is 0 (or any falsey value), no max age header will be sent. Defaults to
+``86400`` (one day).
+
+
+**Note:** A preflight request is an extra request that is made when making a
+"not-so-simple" request (e.g. ``Content-Type`` is not
+``application/x-www-form-urlencoded``) to determine what requests the server
+actually accepts. Read more about it in the `HTML 5 Rocks CORS tutorial
+<https://www.html5rocks.com/en/tutorials/cors/>`_.
+
+``CORS_ALLOW_CREDENTIALS``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If ``True``, cookies will be allowed to be included in cross-site HTTP
+requests. Defaults to ``False``.
+
+Note: in Django 2.1 the `SESSION_COOKIE_SAMESITE`_ setting was added, set to
+``'Lax'`` by default, which will prevent Django's session cookie being sent
+cross-domain. Change it to ``None`` to bypass this security restriction.
+
+.. _SESSION_COOKIE_SAMESITE: https://docs.djangoproject.com/en/2.1/ref/settings/#std:setting-SESSION_COOKIE_SAMESITE
+
+``CORS_MODEL``
+~~~~~~~~~~~~~~
+
+If set, this should be the path to a model to look up allowed origins, in the
+form ``app.modelname``. Defaults to ``None``.
+
+The model should inherit from ``corsheaders.models.AbstractCorsModel`` and specify
+the allowed origin in the ``CharField`` called ``cors``.
+
+CSRF Integration
+----------------
+
+Most sites will need to take advantage of the `Cross-Site Request Forgery
+protection <https://docs.djangoproject.com/en/dev/ref/csrf/>`_ that Django
+offers. CORS and CSRF are separate, and Django has no way of using your CORS
+configuration to exempt sites from the ``Referer`` checking that it does on
+secure requests. The way to do that is with its `CSRF_TRUSTED_ORIGINS setting
+<https://docs.djangoproject.com/en/dev/ref/settings/#csrf-trusted-origins>`_.
+For example:
+
+.. code-block:: python
+
+    CORS_ORIGIN_WHITELIST = (
+        'read.only.com',
+        'change.allowed.com',
+    )
+
+    CSRF_TRUSTED_ORIGINS = (
+        'change.allowed.com',
+    )
+
+``CORS_REPLACE_HTTPS_REFERER``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``CSRF_TRUSTED_ORIGINS`` was introduced in Django 1.9, so users of earlier
+versions will need an alternate solution. If ``CORS_REPLACE_HTTPS_REFERER`` is
+``True``, ``CorsMiddleware`` will change the ``Referer`` header to something
+that will pass Django's CSRF checks whenever the CORS checks pass. Defaults to
+``False``.
+
+Note that unlike ``CSRF_TRUSTED_ORIGINS``, this setting does not allow you to
+distinguish between domains that are trusted to *read* resources by CORS and
+domains that are trusted to *change* resources by avoiding CSRF protection.
+
+With this feature enabled you should also add
+``corsheaders.middleware.CorsPostCsrfMiddleware`` after
+``django.middleware.csrf.CsrfViewMiddleware`` in your ``MIDDLEWARE_CLASSES`` to
+undo the ``Referer`` replacement:
+
+.. code-block:: python
+
+    MIDDLEWARE_CLASSES = [
+        ...
+        'corsheaders.middleware.CorsMiddleware',
+        ...
+        'django.middleware.csrf.CsrfViewMiddleware',
+        'corsheaders.middleware.CorsPostCsrfMiddleware',
+        ...
+    ]
+
+Signals
+-------
+
+If you have a use case that requires more than just the above configuration,
+you can attach code to check if a given request should be allowed. For example,
+this can be used to read the list of origins you allow from a model. Attach any
+number of handlers to the ``check_request_enabled``
+`Django signal <https://docs.djangoproject.com/en/1.10/ref/signals/>`_, which
+provides the ``request`` argument (use ``**kwargs`` in your handler to protect
+against any future arguments being added). If any handler attached to the
+signal returns a truthy value, the request will be allowed.
+
+For example you might define a handler like this:
+
+.. code-block:: python
+
+    # myapp/handlers.py
+    from corsheaders.signals import check_request_enabled
+
+    from .models import MySite
+
+    def cors_allow_mysites(sender, request, **kwargs):
+        return MySite.objects.filter(host=request.host).exists()
+
+    check_request_enabled.connect(cors_allow_mysites)
+
+Then connect it at app ready time using a `Django AppConfig
+<https://docs.djangoproject.com/en/1.10/ref/applications/>`_:
+
+.. code-block:: python
+
+    # myapp/__init__.py
+
+    default_app_config = 'myapp.apps.MyAppConfig'
+
+.. code-block:: python
+
+    # myapp/apps.py
+
+    from django.apps import AppConfig
+
+    class MyAppConfig(AppConfig):
+        name = 'myapp'
+
+        def ready(self):
+            # Makes sure all signal handlers are connected
+            from . import handlers  # noqa
+
+
+A common use case for the signal is to allow *all* origins to access a subset
+of URL's, whilst allowing a normal set of origins to access *all* URL's. This
+isn't possible using just the normal configuration, but it can be achieved with
+a signal handler.
+
+First set ``CORS_ORIGIN_WHITELIST`` to the list of trusted origins that are
+allowed to access every URL, and then add a handler to
+``check_request_enabled`` to allow CORS regardless of the origin for the
+unrestricted URL's. For example:
+
+.. code-block:: python
+
+    # myapp/handlers.py
+    from corsheaders.signals import check_request_enabled
+
+    def cors_allow_api_to_everyone(sender, request, **kwargs):
+        return request.path.startswith('/api/')
+
+    check_request_enabled.connect(cors_allow_api_to_everyone)

+ 3 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/__init__.py

@@ -0,0 +1,3 @@
+from .checks import check_settings  # noqa: F401
+
+__version__ = '2.5.3'

+ 118 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/checks.py

@@ -0,0 +1,118 @@
+from __future__ import absolute_import
+
+import re
+from numbers import Integral
+
+from django.core import checks
+from django.utils import six
+
+from .conf import conf
+
+try:
+    from collections.abc import Sequence  # Python 3.3+
+except ImportError:  # pragma: no cover
+    from collections import Sequence
+
+re_type = type(re.compile(''))
+
+
+@checks.register
+def check_settings(app_configs, **kwargs):
+    errors = []
+
+    if not is_sequence(conf.CORS_ALLOW_HEADERS, six.string_types):
+        errors.append(
+            checks.Error(
+                "CORS_ALLOW_HEADERS should be a sequence of strings.",
+                id="corsheaders.E001"
+            )
+        )
+
+    if not is_sequence(conf.CORS_ALLOW_METHODS, six.string_types):
+        errors.append(
+            checks.Error(
+                "CORS_ALLOW_METHODS should be a sequence of strings.",
+                id="corsheaders.E002"
+            )
+        )
+
+    if not isinstance(conf.CORS_ALLOW_CREDENTIALS, bool):
+        errors.append(
+            checks.Error(
+                "CORS_ALLOW_CREDENTIALS should be a bool.",
+                id="corsheaders.E003"
+            )
+        )
+
+    if not isinstance(conf.CORS_PREFLIGHT_MAX_AGE, Integral) or conf.CORS_PREFLIGHT_MAX_AGE < 0:
+        errors.append(
+            checks.Error(
+                "CORS_PREFLIGHT_MAX_AGE should be an integer greater than or equal to zero.",
+                id="corsheaders.E004"
+            )
+        )
+
+    if not isinstance(conf.CORS_ORIGIN_ALLOW_ALL, bool):
+        errors.append(
+            checks.Error(
+                "CORS_ORIGIN_ALLOW_ALL should be a bool.",
+                id="corsheaders.E005"
+            )
+        )
+
+    if not is_sequence(conf.CORS_ORIGIN_WHITELIST, six.string_types):
+        errors.append(
+            checks.Error(
+                "CORS_ORIGIN_WHITELIST should be a sequence of strings.",
+                id="corsheaders.E006"
+            )
+        )
+
+    if not is_sequence(conf.CORS_ORIGIN_REGEX_WHITELIST, six.string_types + (re_type,)):
+        errors.append(
+            checks.Error(
+                "CORS_ORIGIN_REGEX_WHITELIST should be a sequence of strings and/or compiled regexes.",
+                id="corsheaders.E007"
+            )
+        )
+
+    if not is_sequence(conf.CORS_EXPOSE_HEADERS, six.string_types):
+        errors.append(
+            checks.Error(
+                "CORS_EXPOSE_HEADERS should be a sequence.",
+                id="corsheaders.E008"
+            )
+        )
+
+    if not isinstance(conf.CORS_URLS_REGEX, six.string_types + (re_type,)):
+        errors.append(
+            checks.Error(
+                "CORS_URLS_REGEX should be a string or regex.",
+                id="corsheaders.E009"
+            )
+        )
+
+    if conf.CORS_MODEL is not None and not isinstance(conf.CORS_MODEL, six.string_types):
+        errors.append(
+            checks.Error(
+                "CORS_MODEL should be a string or None.",
+                id="corsheaders.E010"
+            )
+        )
+
+    if not isinstance(conf.CORS_REPLACE_HTTPS_REFERER, bool):
+        errors.append(
+            checks.Error(
+                "CORS_REPLACE_HTTPS_REFERER should be a bool.",
+                id="corsheaders.E011"
+            )
+        )
+
+    return errors
+
+
+def is_sequence(thing, types):
+    return (
+        isinstance(thing, Sequence)
+        and all(isinstance(x, types) for x in thing)
+    )

+ 58 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/conf.py

@@ -0,0 +1,58 @@
+from __future__ import absolute_import
+
+from django.conf import settings
+
+from .defaults import default_headers, default_methods  # Kept here for backwards compatibility
+
+
+class Settings(object):
+    """
+    Shadow Django's settings with a little logic
+    """
+
+    @property
+    def CORS_ALLOW_HEADERS(self):
+        return getattr(settings, 'CORS_ALLOW_HEADERS', default_headers)
+
+    @property
+    def CORS_ALLOW_METHODS(self):
+        return getattr(settings, 'CORS_ALLOW_METHODS', default_methods)
+
+    @property
+    def CORS_ALLOW_CREDENTIALS(self):
+        return getattr(settings, 'CORS_ALLOW_CREDENTIALS', False)
+
+    @property
+    def CORS_PREFLIGHT_MAX_AGE(self):
+        return getattr(settings, 'CORS_PREFLIGHT_MAX_AGE', 86400)
+
+    @property
+    def CORS_ORIGIN_ALLOW_ALL(self):
+        return getattr(settings, 'CORS_ORIGIN_ALLOW_ALL', False)
+
+    @property
+    def CORS_ORIGIN_WHITELIST(self):
+        return getattr(settings, 'CORS_ORIGIN_WHITELIST', ())
+
+    @property
+    def CORS_ORIGIN_REGEX_WHITELIST(self):
+        return getattr(settings, 'CORS_ORIGIN_REGEX_WHITELIST', ())
+
+    @property
+    def CORS_EXPOSE_HEADERS(self):
+        return getattr(settings, 'CORS_EXPOSE_HEADERS', ())
+
+    @property
+    def CORS_URLS_REGEX(self):
+        return getattr(settings, 'CORS_URLS_REGEX', r'^.*$')
+
+    @property
+    def CORS_MODEL(self):
+        return getattr(settings, 'CORS_MODEL', None)
+
+    @property
+    def CORS_REPLACE_HTTPS_REFERER(self):
+        return getattr(settings, 'CORS_REPLACE_HTTPS_REFERER', False)
+
+
+conf = Settings()

+ 20 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/defaults.py

@@ -0,0 +1,20 @@
+default_headers = (
+    'accept',
+    'accept-encoding',
+    'authorization',
+    'content-type',
+    'dnt',
+    'origin',
+    'user-agent',
+    'x-csrftoken',
+    'x-requested-with',
+)
+
+default_methods = (
+    'DELETE',
+    'GET',
+    'OPTIONS',
+    'PATCH',
+    'POST',
+    'PUT',
+)

+ 178 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/middleware.py

@@ -0,0 +1,178 @@
+from __future__ import absolute_import
+
+import re
+
+from django import http
+from django.apps import apps
+from django.utils.cache import patch_vary_headers
+from django.utils.deprecation import MiddlewareMixin
+from django.utils.six.moves.urllib.parse import urlparse
+
+from .conf import conf
+from .signals import check_request_enabled
+
+ACCESS_CONTROL_ALLOW_ORIGIN = 'Access-Control-Allow-Origin'
+ACCESS_CONTROL_EXPOSE_HEADERS = 'Access-Control-Expose-Headers'
+ACCESS_CONTROL_ALLOW_CREDENTIALS = 'Access-Control-Allow-Credentials'
+ACCESS_CONTROL_ALLOW_HEADERS = 'Access-Control-Allow-Headers'
+ACCESS_CONTROL_ALLOW_METHODS = 'Access-Control-Allow-Methods'
+ACCESS_CONTROL_MAX_AGE = 'Access-Control-Max-Age'
+
+
+class CorsPostCsrfMiddleware(MiddlewareMixin):
+
+    def _https_referer_replace_reverse(self, request):
+        """
+        Put the HTTP_REFERER back to its original value and delete the
+        temporary storage
+        """
+        if conf.CORS_REPLACE_HTTPS_REFERER and 'ORIGINAL_HTTP_REFERER' in request.META:
+            http_referer = request.META['ORIGINAL_HTTP_REFERER']
+            request.META['HTTP_REFERER'] = http_referer
+            del request.META['ORIGINAL_HTTP_REFERER']
+
+    def process_request(self, request):
+        self._https_referer_replace_reverse(request)
+        return None
+
+    def process_view(self, request, callback, callback_args, callback_kwargs):
+        self._https_referer_replace_reverse(request)
+        return None
+
+
+class CorsMiddleware(MiddlewareMixin):
+
+    def _https_referer_replace(self, request):
+        """
+        When https is enabled, django CSRF checking includes referer checking
+        which breaks when using CORS. This function updates the HTTP_REFERER
+        header to make sure it matches HTTP_HOST, provided that our cors logic
+        succeeds
+        """
+        origin = request.META.get('HTTP_ORIGIN')
+
+        if request.is_secure() and origin and 'ORIGINAL_HTTP_REFERER' not in request.META:
+
+            url = urlparse(origin)
+            if not conf.CORS_ORIGIN_ALLOW_ALL and not self.origin_found_in_white_lists(origin, url):
+                return
+
+            try:
+                http_referer = request.META['HTTP_REFERER']
+                http_host = "https://%s/" % request.META['HTTP_HOST']
+                request.META = request.META.copy()
+                request.META['ORIGINAL_HTTP_REFERER'] = http_referer
+                request.META['HTTP_REFERER'] = http_host
+            except KeyError:
+                pass
+
+    def process_request(self, request):
+        """
+        If CORS preflight header, then create an
+        empty body response (200 OK) and return it
+
+        Django won't bother calling any other request
+        view/exception middleware along with the requested view;
+        it will call any response middlewares
+        """
+        request._cors_enabled = self.is_enabled(request)
+        if request._cors_enabled:
+            if conf.CORS_REPLACE_HTTPS_REFERER:
+                self._https_referer_replace(request)
+
+            if (
+                request.method == 'OPTIONS'
+                and 'HTTP_ACCESS_CONTROL_REQUEST_METHOD' in request.META
+            ):
+                response = http.HttpResponse()
+                response['Content-Length'] = '0'
+                return response
+
+    def process_view(self, request, callback, callback_args, callback_kwargs):
+        """
+        Do the referer replacement here as well
+        """
+        if request._cors_enabled and conf.CORS_REPLACE_HTTPS_REFERER:
+            self._https_referer_replace(request)
+        return None
+
+    def process_response(self, request, response):
+        """
+        Add the respective CORS headers
+        """
+        enabled = getattr(request, '_cors_enabled', None)
+        if enabled is None:
+            enabled = self.is_enabled(request)
+
+        if not enabled:
+            return response
+
+        patch_vary_headers(response, ['Origin'])
+
+        origin = request.META.get('HTTP_ORIGIN')
+        if not origin:
+            return response
+
+        # todo: check hostname from db instead
+        url = urlparse(origin)
+
+        if conf.CORS_ALLOW_CREDENTIALS:
+            response[ACCESS_CONTROL_ALLOW_CREDENTIALS] = 'true'
+
+        if (
+            not conf.CORS_ORIGIN_ALLOW_ALL
+            and not self.origin_found_in_white_lists(origin, url)
+            and not self.origin_found_in_model(url)
+            and not self.check_signal(request)
+        ):
+            return response
+
+        if conf.CORS_ORIGIN_ALLOW_ALL and not conf.CORS_ALLOW_CREDENTIALS:
+            response[ACCESS_CONTROL_ALLOW_ORIGIN] = "*"
+        else:
+            response[ACCESS_CONTROL_ALLOW_ORIGIN] = origin
+
+        if len(conf.CORS_EXPOSE_HEADERS):
+            response[ACCESS_CONTROL_EXPOSE_HEADERS] = ', '.join(conf.CORS_EXPOSE_HEADERS)
+
+        if request.method == 'OPTIONS':
+            response[ACCESS_CONTROL_ALLOW_HEADERS] = ', '.join(conf.CORS_ALLOW_HEADERS)
+            response[ACCESS_CONTROL_ALLOW_METHODS] = ', '.join(conf.CORS_ALLOW_METHODS)
+            if conf.CORS_PREFLIGHT_MAX_AGE:
+                response[ACCESS_CONTROL_MAX_AGE] = conf.CORS_PREFLIGHT_MAX_AGE
+
+        return response
+
+    def origin_found_in_white_lists(self, origin, url):
+        return (
+            url.netloc in conf.CORS_ORIGIN_WHITELIST
+            or (origin == 'null' and origin in conf.CORS_ORIGIN_WHITELIST)
+            or self.regex_domain_match(origin)
+        )
+
+    def regex_domain_match(self, origin):
+        for domain_pattern in conf.CORS_ORIGIN_REGEX_WHITELIST:
+            if re.match(domain_pattern, origin):
+                return origin
+
+    def origin_found_in_model(self, url):
+        if conf.CORS_MODEL is None:
+            return False
+        model = apps.get_model(*conf.CORS_MODEL.split('.'))
+        return model.objects.filter(cors=url.netloc).exists()
+
+    def is_enabled(self, request):
+        return (
+            bool(re.match(conf.CORS_URLS_REGEX, request.path_info))
+            or self.check_signal(request)
+        )
+
+    def check_signal(self, request):
+        signal_responses = check_request_enabled.send(
+            sender=None,
+            request=request,
+        )
+        return any(
+            return_value for
+            function, return_value in signal_responses
+        )

+ 11 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/models.py

@@ -0,0 +1,11 @@
+from __future__ import absolute_import
+
+from django.db import models
+
+
+class AbstractCorsModel(models.Model):
+    class Meta:
+        abstract = True
+        db_table = 'corsheaders_corsmodel'
+
+    cors = models.CharField(max_length=255)

+ 8 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/corsheaders/signals.py

@@ -0,0 +1,8 @@
+from __future__ import absolute_import
+
+from django.dispatch import Signal
+
+# If any attached handler returns Truthy, CORS will be allowed for the request.
+# This can be used to build custom logic into the request handling when the
+# configuration doesn't work.
+check_request_enabled = Signal(providing_args=['request'])

+ 5 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/pytest.ini

@@ -0,0 +1,5 @@
+[pytest]
+addopts = -p no:doctest
+      --cov=corsheaders
+      --cov-report term-missing
+      --cov-fail-under 100

+ 37 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/requirements.txt

@@ -0,0 +1,37 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+#    __main__.py compile -r -U
+#
+atomicwrites==1.3.0       # via pytest
+attrs==19.1.0             # via pytest
+backports.functools-lru-cache==1.5 ; python_version < '3.0'  # via isort
+configparser==3.7.4       # via entrypoints, flake8
+coverage==4.5.3           # via pytest-cov
+docutils==0.14
+entrypoints==0.3          # via flake8
+enum34==1.1.6             # via flake8
+flake8==3.7.7
+funcsigs==1.0.2           # via pytest
+functools32==3.2.3.post2 ; python_version < '3.0'  # via flake8
+futures==3.1.1
+isort==4.3.17
+mccabe==0.6.1             # via flake8
+modernize==0.7
+more-itertools==5.0.0     # via pytest
+multilint==2.4.0
+pathlib2==2.3.3           # via pytest, pytest-django
+pluggy==0.9.0             # via pytest
+py==1.8.0                 # via pytest
+pycodestyle==2.5.0        # via flake8
+pyflakes==2.1.1           # via flake8
+pygments==2.3.1
+pytest-cov==2.6.1
+pytest-django==3.4.8
+pytest==4.4.1
+pytz==2019.1
+scandir==1.10.0           # via pathlib2
+six==1.12.0               # via more-itertools, multilint, pathlib2, pytest
+sqlparse==0.3.0
+typing==3.6.6             # via flake8

+ 17 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/runtests.py

@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function
+
+import os
+import sys
+
+import pytest
+
+
+def main():
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tests.settings')
+    return pytest.main()
+
+
+if __name__ == '__main__':
+    sys.exit(main())

+ 28 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/setup.cfg

@@ -0,0 +1,28 @@
+[bdist_wheel]
+universal = 1
+
+[flake8]
+ignore = X99999, W503
+max-complexity = 12
+max-line-length = 120
+
+[isort]
+known_first_party = corsheaders
+known_third_party = django
+line_length = 120
+multi_line_output = 5
+not_skip = __init__.py
+
+[metadata]
+license_file = LICENSE
+
+[tool:multilint]
+paths = corsheaders
+	runtests.py
+	tests
+	setup.py
+
+[egg_info]
+tag_build = 
+tag_date = 0
+

+ 63 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/setup.py

@@ -0,0 +1,63 @@
+from __future__ import absolute_import
+
+import codecs
+import os
+import re
+
+from setuptools import setup
+
+
+def get_version(filename):
+    with codecs.open(filename, 'r', 'utf-8') as fp:
+        contents = fp.read()
+    return re.search(r"__version__ = ['\"]([^'\"]+)['\"]", contents).group(1)
+
+
+version = get_version(os.path.join('corsheaders', '__init__.py'))
+
+with codecs.open('README.rst', 'r', 'utf-8') as readme_file:
+    readme = readme_file.read()
+
+with codecs.open('HISTORY.rst', 'r', 'utf-8') as history_file:
+    history = history_file.read()
+
+setup(
+    name='django-cors-headers',
+    version=version,
+    description=(
+        'django-cors-headers is a Django application for handling the server '
+        'headers required for Cross-Origin Resource Sharing (CORS).'
+    ),
+    long_description=readme + '\n\n' + history,
+    author='Otto Yiu',
+    author_email='otto@live.ca',
+    url='https://github.com/ottoyiu/django-cors-headers',
+    packages=['corsheaders'],
+    license='MIT License',
+    keywords=['django', 'cors', 'middleware', 'rest', 'api'],
+    install_requires=[
+        'Django>=1.11',
+    ],
+    python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
+    classifiers=[
+        'Development Status :: 5 - Production/Stable',
+        'Environment :: Web Environment',
+        'Framework :: Django',
+        'Framework :: Django :: 1.11',
+        'Framework :: Django :: 2.0',
+        'Framework :: Django :: 2.1',
+        'Framework :: Django :: 2.2',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: MIT License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Programming Language :: Python :: 2',
+        'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3',
+        'Programming Language :: Python :: 3.5',
+        'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: 3.7',
+        'Topic :: Software Development :: Libraries :: Application Frameworks',
+        'Topic :: Software Development :: Libraries :: Python Modules',
+    ],
+)

+ 0 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/tests/__init__.py


+ 30 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/tests/settings.py

@@ -0,0 +1,30 @@
+from __future__ import absolute_import
+
+SECRET_KEY = 'NOTASECRET'
+
+ALLOWED_HOSTS = ['*']
+
+INSTALLED_APPS = [
+    'corsheaders',
+    'tests.testapp',
+]
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+    },
+}
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+    },
+]
+
+ROOT_URLCONF = 'tests.urls'
+
+MIDDLEWARE = [
+    'corsheaders.middleware.CorsMiddleware',
+]
+
+SECURE_PROXY_SSL_HEADER = ('HTTP_FAKE_SECURE', 'true')

+ 99 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/tests/test_checks.py

@@ -0,0 +1,99 @@
+from __future__ import absolute_import
+
+import re
+
+import pytest
+from django.core.checks import Error
+from django.core.management import base, call_command
+from django.test import SimpleTestCase
+from django.test.utils import override_settings
+
+from corsheaders.checks import check_settings
+
+
+class ChecksTests(SimpleTestCase):
+
+    def check_error_codes(self, expected):
+        errors = check_settings([])
+        assert len(errors) == len(expected)
+        assert all(isinstance(e, Error) for e in errors)
+        assert [e.id for e in errors] == expected
+
+    def test_defaults_pass(self):
+        self.check_error_codes([])
+
+    def test_defaults_pass_check(self):
+        call_command('check')
+
+    @override_settings(CORS_ORIGIN_ALLOW_ALL=object)
+    def test_checks_are_bound(self):
+        with pytest.raises(base.SystemCheckError):
+            call_command('check')
+
+    @override_settings(CORS_ALLOW_HEADERS=object)
+    def test_cors_allow_headers_non_sequence(self):
+        self.check_error_codes(['corsheaders.E001'])
+
+    @override_settings(CORS_ALLOW_HEADERS=[object])
+    def test_cors_allow_headers_non_string(self):
+        self.check_error_codes(['corsheaders.E001'])
+
+    @override_settings(CORS_ALLOW_METHODS=object)
+    def test_cors_allow_methods_non_sequence(self):
+        self.check_error_codes(['corsheaders.E002'])
+
+    @override_settings(CORS_ALLOW_METHODS=[object])
+    def test_cors_allow_methods_non_string(self):
+        self.check_error_codes(['corsheaders.E002'])
+
+    @override_settings(CORS_ALLOW_CREDENTIALS=object)
+    def test_cors_allow_credentials_non_bool(self):
+        self.check_error_codes(['corsheaders.E003'])
+
+    @override_settings(CORS_PREFLIGHT_MAX_AGE='10')
+    def test_cors_preflight_max_age_non_integer(self):
+        self.check_error_codes(['corsheaders.E004'])
+
+    @override_settings(CORS_PREFLIGHT_MAX_AGE=-1)
+    def test_cors_preflight_max_age_negative(self):
+        self.check_error_codes(['corsheaders.E004'])
+
+    @override_settings(CORS_ORIGIN_ALLOW_ALL=object)
+    def test_cors_origin_allow_all_non_bool(self):
+        self.check_error_codes(['corsheaders.E005'])
+
+    @override_settings(CORS_ORIGIN_WHITELIST=object)
+    def test_cors_origin_whitelist_non_sequence(self):
+        self.check_error_codes(['corsheaders.E006'])
+
+    @override_settings(CORS_ORIGIN_WHITELIST=[object])
+    def test_cors_origin_whitelist_non_string(self):
+        self.check_error_codes(['corsheaders.E006'])
+
+    @override_settings(CORS_ORIGIN_REGEX_WHITELIST=object)
+    def test_cors_origin_regex_whitelist_non_sequence(self):
+        self.check_error_codes(['corsheaders.E007'])
+
+    @override_settings(CORS_ORIGIN_REGEX_WHITELIST=[re.compile(r'a')])
+    def test_cors_origin_regex_whitelist_regex(self):
+        self.check_error_codes([])
+
+    @override_settings(CORS_EXPOSE_HEADERS=object)
+    def test_cors_expose_headers_non_sequence(self):
+        self.check_error_codes(['corsheaders.E008'])
+
+    @override_settings(CORS_EXPOSE_HEADERS=[object])
+    def test_cors_expose_headers_non_string(self):
+        self.check_error_codes(['corsheaders.E008'])
+
+    @override_settings(CORS_URLS_REGEX=object)
+    def test_cors_urls_regex_non_string(self):
+        self.check_error_codes(['corsheaders.E009'])
+
+    @override_settings(CORS_MODEL=object)
+    def test_cors_model_failure(self):
+        self.check_error_codes(['corsheaders.E010'])
+
+    @override_settings(CORS_REPLACE_HTTPS_REFERER=object)
+    def test_cors_replace_https_referer_failure(self):
+        self.check_error_codes(['corsheaders.E011'])

+ 13 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/tests/test_conf.py

@@ -0,0 +1,13 @@
+from __future__ import absolute_import
+
+from django.test import SimpleTestCase
+from django.test.utils import override_settings
+
+from corsheaders.conf import conf
+
+
+class ConfTests(SimpleTestCase):
+
+    @override_settings(CORS_ALLOW_HEADERS=['foo'])
+    def test_can_override(self):
+        assert conf.CORS_ALLOW_HEADERS == ['foo']

+ 453 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/tests/test_middleware.py

@@ -0,0 +1,453 @@
+from __future__ import absolute_import
+
+from django.http import HttpResponse
+from django.test import TestCase
+from django.test.utils import override_settings
+from django.utils.deprecation import MiddlewareMixin
+
+from corsheaders.middleware import (
+    ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS,
+    ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_EXPOSE_HEADERS, ACCESS_CONTROL_MAX_AGE
+)
+from tests.testapp.models import CorsModel
+
+from .utils import append_middleware, prepend_middleware, temporary_check_request_hander
+
+
+class ShortCircuitMiddleware(MiddlewareMixin):
+
+    def process_request(self, request):
+        return HttpResponse('short-circuit-middleware-response')
+
+
+class CorsMiddlewareTests(TestCase):
+
+    def test_get_no_origin(self):
+        resp = self.client.get('/')
+        assert ACCESS_CONTROL_ALLOW_ORIGIN not in resp
+
+    def test_get_origin_vary_by_default(self):
+        resp = self.client.get('/')
+        assert resp['Vary'] == 'Origin'
+
+    @override_settings(CORS_ORIGIN_WHITELIST=['example.com'])
+    def test_get_not_in_whitelist(self):
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.org')
+        assert ACCESS_CONTROL_ALLOW_ORIGIN not in resp
+
+    @override_settings(CORS_ORIGIN_WHITELIST=['example.com', 'example.org'])
+    def test_get_in_whitelist(self):
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.org')
+        assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'http://example.org'
+
+    @override_settings(CORS_ORIGIN_WHITELIST=['example.com', 'null'])
+    def test_null_in_whitelist(self):
+        resp = self.client.get('/', HTTP_ORIGIN='null')
+        assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'null'
+
+    @override_settings(
+        CORS_ORIGIN_ALLOW_ALL=True,
+        CORS_EXPOSE_HEADERS=['accept', 'origin', 'content-type'],
+    )
+    def test_get_expose_headers(self):
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.com')
+        assert resp[ACCESS_CONTROL_EXPOSE_HEADERS] == 'accept, origin, content-type'
+
+    @override_settings(CORS_ORIGIN_ALLOW_ALL=True)
+    def test_get_dont_expose_headers(self):
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.com')
+        assert ACCESS_CONTROL_EXPOSE_HEADERS not in resp
+
+    @override_settings(
+        CORS_ALLOW_CREDENTIALS=True,
+        CORS_ORIGIN_ALLOW_ALL=True,
+    )
+    def test_get_allow_credentials(self):
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.com')
+        assert resp[ACCESS_CONTROL_ALLOW_CREDENTIALS] == 'true'
+
+    @override_settings(CORS_ORIGIN_ALLOW_ALL=True)
+    def test_get_dont_allow_credentials(self):
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.com')
+        assert ACCESS_CONTROL_ALLOW_CREDENTIALS not in resp
+
+    @override_settings(
+        CORS_ALLOW_HEADERS=['content-type', 'origin'],
+        CORS_ALLOW_METHODS=['GET', 'OPTIONS'],
+        CORS_PREFLIGHT_MAX_AGE=1002,
+        CORS_ORIGIN_ALLOW_ALL=True,
+    )
+    def test_options_allowed_origin(self):
+        resp = self.client.options(
+            '/',
+            HTTP_ORIGIN='http://example.com',
+        )
+        assert resp[ACCESS_CONTROL_ALLOW_HEADERS] == 'content-type, origin'
+        assert resp[ACCESS_CONTROL_ALLOW_METHODS] == 'GET, OPTIONS'
+        assert resp[ACCESS_CONTROL_MAX_AGE] == '1002'
+
+    @override_settings(
+        CORS_ALLOW_HEADERS=['content-type', 'origin'],
+        CORS_ALLOW_METHODS=['GET', 'OPTIONS'],
+        CORS_PREFLIGHT_MAX_AGE=0,
+        CORS_ORIGIN_ALLOW_ALL=True,
+    )
+    def test_options_no_max_age(self):
+        resp = self.client.options('/', HTTP_ORIGIN='http://example.com')
+        assert resp[ACCESS_CONTROL_ALLOW_HEADERS] == 'content-type, origin'
+        assert resp[ACCESS_CONTROL_ALLOW_METHODS] == 'GET, OPTIONS'
+        assert ACCESS_CONTROL_MAX_AGE not in resp
+
+    @override_settings(
+        CORS_ALLOW_METHODS=['OPTIONS'],
+        CORS_ALLOW_CREDENTIALS=True,
+        CORS_ORIGIN_WHITELIST=('localhost:9000',),
+    )
+    def test_options_whitelist_with_port(self):
+        resp = self.client.options('/', HTTP_ORIGIN='http://localhost:9000')
+        assert resp[ACCESS_CONTROL_ALLOW_CREDENTIALS] == 'true'
+
+    @override_settings(
+        CORS_ALLOW_METHODS=['OPTIONS'],
+        CORS_ALLOW_CREDENTIALS=True,
+        CORS_ORIGIN_REGEX_WHITELIST=[r'^http?://(\w+\.)?example\.com$'],
+    )
+    def test_options_adds_origin_when_domain_found_in_origin_regex_whitelist(self):
+        resp = self.client.options('/', HTTP_ORIGIN='http://foo.example.com')
+        assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'http://foo.example.com'
+
+    @override_settings(
+        CORS_ALLOW_METHODS=['OPTIONS'],
+        CORS_ALLOW_CREDENTIALS=True,
+        CORS_ORIGIN_REGEX_WHITELIST=(r'^http?://(\w+\.)?example\.org$',),
+    )
+    def test_options_will_not_add_origin_when_domain_not_found_in_origin_regex_whitelist(self):
+        resp = self.client.options('/', HTTP_ORIGIN='http://foo.example.com')
+        assert ACCESS_CONTROL_ALLOW_ORIGIN not in resp
+
+    @override_settings(CORS_MODEL='testapp.CorsModel')
+    def test_get_when_custom_model_enabled(self):
+        CorsModel.objects.create(cors='example.com')
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.com')
+        assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'http://example.com'
+        assert ACCESS_CONTROL_ALLOW_CREDENTIALS not in resp
+
+    @override_settings(CORS_MODEL='testapp.CorsModel', CORS_ALLOW_CREDENTIALS=True)
+    def test_get_when_custom_model_enabled_and_allow_credentials(self):
+        CorsModel.objects.create(cors='example.com')
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.com')
+        assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'http://example.com'
+        assert resp[ACCESS_CONTROL_ALLOW_CREDENTIALS] == 'true'
+
+    def test_options(self):
+        resp = self.client.options(
+            '/',
+            HTTP_ACCESS_CONTROL_REQUEST_METHOD='value',
+        )
+        assert resp.status_code == 200
+
+    def test_options_empty_request_method(self):
+        resp = self.client.options(
+            '/',
+            HTTP_ACCESS_CONTROL_REQUEST_METHOD='',
+        )
+        assert resp.status_code == 200
+
+    def test_options_no_header(self):
+        resp = self.client.options('/')
+        assert resp.status_code == 404
+
+    @override_settings(CORS_MODEL='testapp.CorsModel')
+    def test_options_when_custom_model_enabled(self):
+        CorsModel.objects.create(cors='example.com')
+        resp = self.client.options(
+            '/',
+            HTTP_ORIGIN='http://example.com',
+            HTTP_ACCESS_CONTROL_REQUEST_METHOD='value',
+        )
+        assert ACCESS_CONTROL_ALLOW_HEADERS in resp
+
+    @override_settings(CORS_MODEL='testapp.CorsModel')
+    def test_process_response_when_custom_model_enabled(self):
+        CorsModel.objects.create(cors='foo.google.com')
+        response = self.client.get('/', HTTP_ORIGIN='http://foo.google.com')
+        assert response.get(ACCESS_CONTROL_ALLOW_ORIGIN, None) == 'http://foo.google.com'
+
+    @override_settings(
+        CORS_ALLOW_CREDENTIALS=True,
+        CORS_ORIGIN_ALLOW_ALL=True,
+    )
+    def test_allow_all_origins_get(self):
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.com')
+        assert resp.status_code == 200
+        assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'http://example.com'
+        assert resp['Vary'] == 'Origin'
+
+    @override_settings(
+        CORS_ALLOW_CREDENTIALS=True,
+        CORS_ORIGIN_ALLOW_ALL=True,
+    )
+    def test_allow_all_origins_options(self):
+        resp = self.client.options(
+            '/',
+            HTTP_ORIGIN='http://example.com',
+            HTTP_ACCESS_CONTROL_REQUEST_METHOD='value',
+        )
+        assert resp.status_code == 200
+        assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'http://example.com'
+        assert resp['Vary'] == 'Origin'
+
+    @override_settings(
+        CORS_ALLOW_CREDENTIALS=True,
+        CORS_ORIGIN_ALLOW_ALL=True,
+    )
+    def test_non_200_headers_still_set(self):
+        """
+        It's not clear whether the header should still be set for non-HTTP200
+        when not a preflight request. However this is the existing behaviour for
+        django-cors-middleware, so at least this test makes that explicit, especially
+        since for the switch to Django 1.10, special-handling will need to be put in
+        place to preserve this behaviour. See `ExceptionMiddleware` mention here:
+        https://docs.djangoproject.com/en/1.10/topics/http/middleware/#upgrading-pre-django-1-10-style-middleware
+        """
+        resp = self.client.get('/test-401/', HTTP_ORIGIN='http://example.com')
+        assert resp.status_code == 401
+        assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'http://example.com'
+
+    @override_settings(
+        CORS_ALLOW_CREDENTIALS=True,
+        CORS_ORIGIN_ALLOW_ALL=True,
+    )
+    def test_auth_view_options(self):
+        """
+        Ensure HTTP200 and header still set, for preflight requests to views requiring
+        authentication. See: https://github.com/ottoyiu/django-cors-headers/issues/3
+        """
+        resp = self.client.options(
+            '/test-401/',
+            HTTP_ORIGIN='http://example.com',
+            HTTP_ACCESS_CONTROL_REQUEST_METHOD='value',
+        )
+        assert resp.status_code == 200
+        assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'http://example.com'
+        assert resp['Content-Length'] == '0'
+
+    def test_signal_handler_that_returns_false(self):
+        def handler(*args, **kwargs):
+            return False
+
+        with temporary_check_request_hander(handler):
+            resp = self.client.options(
+                '/',
+                HTTP_ORIGIN='http://example.com',
+                HTTP_ACCESS_CONTROL_REQUEST_METHOD='value',
+            )
+
+            assert resp.status_code == 200
+            assert ACCESS_CONTROL_ALLOW_ORIGIN not in resp
+
+    def test_signal_handler_that_returns_true(self):
+        def handler(*args, **kwargs):
+            return True
+
+        with temporary_check_request_hander(handler):
+            resp = self.client.options(
+                '/',
+                HTTP_ORIGIN='http://example.com',
+                HTTP_ACCESS_CONTROL_REQUEST_METHOD='value',
+            )
+            assert resp.status_code == 200
+            assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'http://example.com'
+
+    @override_settings(CORS_ORIGIN_WHITELIST=['example.com'])
+    def test_signal_handler_allow_some_urls_to_everyone(self):
+        def allow_api_to_all(sender, request, **kwargs):
+            return request.path.startswith('/api/')
+
+        with temporary_check_request_hander(allow_api_to_all):
+            resp = self.client.options(
+                '/',
+                HTTP_ORIGIN='http://example.org',
+                HTTP_ACCESS_CONTROL_REQUEST_METHOD='value',
+            )
+            assert resp.status_code == 200
+            assert ACCESS_CONTROL_ALLOW_ORIGIN not in resp
+
+            resp = self.client.options(
+                '/api/something/',
+                HTTP_ORIGIN='http://example.org',
+                HTTP_ACCESS_CONTROL_REQUEST_METHOD='value',
+            )
+            assert resp.status_code == 200
+            assert resp[ACCESS_CONTROL_ALLOW_ORIGIN] == 'http://example.org'
+
+    @override_settings(CORS_ORIGIN_WHITELIST=['example.com'])
+    def test_signal_called_once_during_normal_flow(self):
+        def allow_all(sender, request, **kwargs):
+            allow_all.calls += 1
+            return True
+        allow_all.calls = 0
+
+        with temporary_check_request_hander(allow_all):
+            self.client.get('/', HTTP_ORIGIN='http://example.org')
+
+            assert allow_all.calls == 1
+
+    @override_settings(CORS_ORIGIN_WHITELIST=['example.com'])
+    @prepend_middleware('tests.test_middleware.ShortCircuitMiddleware')
+    def test_get_short_circuit(self):
+        """
+        Test a scenario when a middleware that returns a response is run before
+        the ``CorsMiddleware``. In this case
+        ``CorsMiddleware.process_response()`` should ignore the request if
+        MIDDLEWARE setting is used (new mechanism in Django 1.10+).
+        """
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.com')
+        assert ACCESS_CONTROL_ALLOW_ORIGIN not in resp
+
+    @override_settings(
+        CORS_ORIGIN_WHITELIST=['example.com'],
+        CORS_URLS_REGEX=r'^/foo/$',
+    )
+    @prepend_middleware(__name__ + '.ShortCircuitMiddleware')
+    def test_get_short_circuit_should_be_ignored(self):
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.com')
+        assert ACCESS_CONTROL_ALLOW_ORIGIN not in resp
+
+    @override_settings(
+        CORS_ORIGIN_WHITELIST=['example.com'],
+        CORS_URLS_REGEX=r'^/foo/$',
+    )
+    def test_get_regex_matches(self):
+        resp = self.client.get('/foo/', HTTP_ORIGIN='http://example.com')
+        assert ACCESS_CONTROL_ALLOW_ORIGIN in resp
+
+    @override_settings(
+        CORS_ORIGIN_WHITELIST=['example.com'],
+        CORS_URLS_REGEX=r'^/not-foo/$',
+    )
+    def test_get_regex_doesnt_match(self):
+        resp = self.client.get('/foo/', HTTP_ORIGIN='http://example.com')
+        assert ACCESS_CONTROL_ALLOW_ORIGIN not in resp
+
+    @override_settings(
+        CORS_ORIGIN_WHITELIST=['example.com'],
+        CORS_URLS_REGEX=r'^/foo/$',
+    )
+    def test_get_regex_matches_path_info(self):
+        resp = self.client.get('/foo/', HTTP_ORIGIN='http://example.com', SCRIPT_NAME='/prefix/')
+        assert ACCESS_CONTROL_ALLOW_ORIGIN in resp
+
+    @override_settings(CORS_ORIGIN_WHITELIST=['example.com'])
+    def test_cors_enabled_is_attached_and_bool(self):
+        """
+        Ensure that request._cors_enabled is available - although a private API
+        someone might use it for debugging
+        """
+        resp = self.client.get('/', HTTP_ORIGIN='http://example.com')
+        request = resp.wsgi_request
+        assert isinstance(request._cors_enabled, bool)
+        assert request._cors_enabled
+
+    @override_settings(CORS_ORIGIN_WHITELIST=['example.com'])
+    def test_works_if_view_deletes_cors_enabled(self):
+        """
+        Just in case something crazy happens in the view or other middleware,
+        check that get_response doesn't fall over if `_cors_enabled` is removed
+        """
+        resp = self.client.get(
+            '/delete-is-enabled/',
+            HTTP_ORIGIN='http://example.com',
+        )
+        assert ACCESS_CONTROL_ALLOW_ORIGIN in resp
+
+
+@override_settings(
+    CORS_REPLACE_HTTPS_REFERER=True,
+    CORS_ORIGIN_REGEX_WHITELIST=(r'.*example.*',),
+)
+class RefererReplacementCorsMiddlewareTests(TestCase):
+
+    def test_get_replaces_referer_when_secure(self):
+        resp = self.client.get(
+            '/',
+            HTTP_FAKE_SECURE='true',
+            HTTP_HOST='example.com',
+            HTTP_ORIGIN='https://example.org',
+            HTTP_REFERER='https://example.org/foo'
+        )
+        assert resp.status_code == 200
+        assert resp.wsgi_request.META['HTTP_REFERER'] == 'https://example.com/'
+        assert resp.wsgi_request.META['ORIGINAL_HTTP_REFERER'] == 'https://example.org/foo'
+
+    @append_middleware('corsheaders.middleware.CorsPostCsrfMiddleware')
+    def test_get_post_middleware_rereplaces_referer_when_secure(self):
+        resp = self.client.get(
+            '/',
+            HTTP_FAKE_SECURE='true',
+            HTTP_HOST='example.com',
+            HTTP_ORIGIN='https://example.org',
+            HTTP_REFERER='https://example.org/foo'
+        )
+        assert resp.status_code == 200
+        assert resp.wsgi_request.META['HTTP_REFERER'] == 'https://example.org/foo'
+        assert 'ORIGINAL_HTTP_REFERER' not in resp.wsgi_request.META
+
+    def test_get_does_not_replace_referer_when_insecure(self):
+        resp = self.client.get(
+            '/',
+            HTTP_HOST='example.com',
+            HTTP_ORIGIN='https://example.org',
+            HTTP_REFERER='https://example.org/foo'
+        )
+        assert resp.status_code == 200
+        assert resp.wsgi_request.META['HTTP_REFERER'] == 'https://example.org/foo'
+        assert 'ORIGINAL_HTTP_REFERER' not in resp.wsgi_request.META
+
+    @override_settings(CORS_REPLACE_HTTPS_REFERER=False)
+    def test_get_does_not_replace_referer_when_disabled(self):
+        resp = self.client.get(
+            '/',
+            HTTP_FAKE_SECURE='true',
+            HTTP_HOST='example.com',
+            HTTP_ORIGIN='https://example.org',
+            HTTP_REFERER='https://example.org/foo',
+        )
+        assert resp.status_code == 200
+        assert resp.wsgi_request.META['HTTP_REFERER'] == 'https://example.org/foo'
+        assert 'ORIGINAL_HTTP_REFERER' not in resp.wsgi_request.META
+
+    def test_get_does_not_fail_in_referer_replacement_when_referer_missing(self):
+        resp = self.client.get(
+            '/',
+            HTTP_FAKE_SECURE='true',
+            HTTP_HOST='example.com',
+            HTTP_ORIGIN='https://example.org',
+        )
+        assert resp.status_code == 200
+        assert 'HTTP_REFERER' not in resp.wsgi_request.META
+        assert 'ORIGINAL_HTTP_REFERER' not in resp.wsgi_request.META
+
+    def test_get_does_not_fail_in_referer_replacement_when_host_missing(self):
+        resp = self.client.get(
+            '/',
+            HTTP_FAKE_SECURE='true',
+            HTTP_ORIGIN='https://example.org',
+            HTTP_REFERER='https://example.org/foo',
+        )
+        assert resp.status_code == 200
+        assert resp.wsgi_request.META['HTTP_REFERER'] == 'https://example.org/foo'
+        assert 'ORIGINAL_HTTP_REFERER' not in resp.wsgi_request.META
+
+    @override_settings(CORS_ORIGIN_REGEX_WHITELIST=())
+    def test_get_does_not_replace_referer_when_not_valid_request(self):
+        resp = self.client.get(
+            '/',
+            HTTP_FAKE_SECURE='true',
+            HTTP_HOST='example.com',
+            HTTP_ORIGIN='https://example.org',
+            HTTP_REFERER='https://example.org/foo',
+        )
+        assert resp.status_code == 200
+        assert resp.wsgi_request.META['HTTP_REFERER'] == 'https://example.org/foo'
+        assert 'ORIGINAL_HTTP_REFERER' not in resp.wsgi_request.META

+ 0 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/tests/testapp/__init__.py


+ 7 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/tests/testapp/models.py

@@ -0,0 +1,7 @@
+from __future__ import absolute_import
+
+from corsheaders.models import AbstractCorsModel
+
+
+class CorsModel(AbstractCorsModel):
+    pass

+ 28 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/tests/urls.py

@@ -0,0 +1,28 @@
+from __future__ import absolute_import
+
+from django.conf.urls import url
+from django.http import Http404, HttpResponse
+
+
+def test_view(request):
+    if request.method != 'GET':
+        raise Http404()
+    return HttpResponse("Test view")
+
+
+def test_view_http401(request):
+    return HttpResponse('Unauthorized', status=401)
+
+
+def test_view_that_deletes_is_enabled(request):
+    if hasattr(request, '_cors_enabled'):
+        del request._cors_enabled
+    return HttpResponse()
+
+
+urlpatterns = [
+    url(r'^$', test_view),
+    url(r'^foo/$', test_view),
+    url(r'^test-401/$', test_view_http401),
+    url(r'^delete-is-enabled/$', test_view_that_deletes_is_enabled),
+]

+ 32 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/tests/utils.py

@@ -0,0 +1,32 @@
+from __future__ import absolute_import
+
+from contextlib import contextmanager
+
+from django.test.utils import modify_settings
+
+from corsheaders.signals import check_request_enabled
+
+
+def add_middleware(action, path):
+    return modify_settings(**{
+        'MIDDLEWARE': {
+            action: path,
+        }
+    })
+
+
+def append_middleware(path):
+    return add_middleware('append', path)
+
+
+def prepend_middleware(path):
+    return add_middleware('prepend', path)
+
+
+@contextmanager
+def temporary_check_request_hander(handler):
+    check_request_enabled.connect(handler)
+    try:
+        yield
+    finally:
+        check_request_enabled.disconnect(handler)

+ 26 - 0
desktop/core/ext-py/django-cors-headers-2.5.3/tox.ini

@@ -0,0 +1,26 @@
+[tox]
+envlist =
+    py{27,3}-django{111},
+    py3-django{20,21,22},
+    py{27,3}-codestyle
+
+[testenv]
+setenv =
+    PYTHONDONTWRITEBYTECODE=1
+install_command = pip install --no-deps {opts} {packages}
+deps =
+    -rrequirements.txt
+    django111: Django>=1.11,<2.0
+    django20: Django>=2.0,<2.1
+    django21: Django>=2.1,<2.2
+    django22: Django>=2.2,<2.3
+commands = ./runtests.py {posargs}
+
+[testenv:py27-codestyle]
+# setup.py check broken on travis python 2.7
+skip_install = true
+commands = multilint --skip setup.py
+
+[testenv:py3-codestyle]
+skip_install = true
+commands = multilint