prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Scrapy 1.1.0 RC3 - exception thrown with invalid ssl certificate
  Hello,
  
  I am crawling sometimes websites with an invalid ssl certificate. For example, Scrapy 1.1.0 RC3 fails to open when I do:
  
  > scrapy shell https://www.directoriosanitario.com/directorio
  > or
  > scrapy shell https://saobinv.5go.cc/top/
  
  and throws the following exception:
  
  > twisted.web._newclient.ResponseNeverReceived: [<twisted.python.failure.Failure service_identity.exceptions.VerificationError: VerificationError(errors=[DNSMismatch(mismatched_id=DNS_ID(hostname=b'www.directoriosanitario.com'))])>]
  
  I tried it with Scrapy 1.0.5 on python 2.7 and the spider opens but warns with: 
  
  > AttributeError: 'NoneType' object has no attribute 'failVerification'
  
  Is there a way to force the spider to open with Scrapy 1.1.0 RC3?
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `scrapy/core/downloader/tls.py`
  Content:
  ```
  1 from OpenSSL import SSL
  2 
  3 
  4 METHOD_SSLv3 = 'SSLv3'
  5 METHOD_TLS = 'TLS'
  6 METHOD_TLSv10 = 'TLSv1.0'
  7 METHOD_TLSv11 = 'TLSv1.1'
  8 METHOD_TLSv12 = 'TLSv1.2'
  9 
  10 openssl_methods = {
  11     METHOD_TLS:    SSL.SSLv23_METHOD,                   # protocol negotiation (recommended)
  12     METHOD_SSLv3:  SSL.SSLv3_METHOD,                    # SSL 3 (NOT recommended)
  13     METHOD_TLSv10: SSL.TLSv1_METHOD,                    # TLS 1.0 only
  14     METHOD_TLSv11: getattr(SSL, 'TLSv1_1_METHOD', 5),   # TLS 1.1 only
  15     METHOD_TLSv12: getattr(SSL, 'TLSv1_2_METHOD', 6),   # TLS 1.2 only
  16 }
  17
  ```
  
  Path: `scrapy/core/downloader/contextfactory.py`
  Content:
  ```
  1 from OpenSSL import SSL
  2 from twisted.internet.ssl import ClientContextFactory
  3 
  4 try:
  5 
  6     from zope.interface.declarations import implementer
  7 
  8     # the following should be available from Twisted 14.0.0
  9     from twisted.internet.ssl import optionsForClientTLS, CertificateOptions, platformTrust
  10     from twisted.internet._sslverify import ClientTLSOptions
  11     from twisted.web.client import BrowserLikePolicyForHTTPS
  12     from twisted.web.iweb import IPolicyForHTTPS
  13 
  14     @implementer(IPolicyForHTTPS)
  15     class ScrapyClientContextFactory(BrowserLikePolicyForHTTPS):
  16         """
  17         Non-peer-certificate verifying HTTPS context factory
  18 
  19         Default OpenSSL method is TLS_METHOD (also called SSLv23_METHOD)
  20         which allows TLS protocol negotiation
  21 
  22         'A TLS/SSL connection established with [this method] may
  23          understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols.'
  24         """
  25 
  26         def __init__(self, method=SSL.SSLv23_METHOD, *args, **kwargs):
  27             super(ScrapyClientContextFactory, self).__init__(*args, **kwargs)
  28             self._ssl_method = method
  29 
  30         def getCertificateOptions(self):
  31             # setting verify=True will require you to provide CAs
  32             # to verify against; in other words: it's not that simple
  33 
  34             # backward-compatible SSL/TLS method:
  35             #
  36             # * this will respect `method` attribute in often recommended
  37             #   `ScrapyClientContextFactory` subclass
  38             #   (https://github.com/scrapy/scrapy/issues/1429#issuecomment-131782133)
  39             #
  40             # * getattr() for `_ssl_method` attribute for context factories
  41             #   not calling super(..., self).__init__
  42             return CertificateOptions(verify=False,
  43                         method=getattr(self, 'method',
  44                                        getattr(self, '_ssl_method', None)))
  45 
  46         # kept for old-style HTTP/1.0 downloader context twisted calls,
  47         # e.g. connectSSL()
  48         def getContext(self, hostname=None, port=None):
  49             return self.getCertificateOptions().getContext()
  50 
  51         def creatorForNetloc(self, hostname, port):
  52             return ClientTLSOptions(hostname.decode("ascii"), self.getContext())
  53 
  54 
  55     @implementer(IPolicyForHTTPS)
  56     class BrowserLikeContextFactory(ScrapyClientContextFactory):
  57         """
  58         Twisted-recommended context factory for web clients.
  59 
  60         Quoting http://twistedmatrix.com/documents/current/api/twisted.web.client.Agent.html:
  61         "The default is to use a BrowserLikePolicyForHTTPS,
  62         so unless you have special requirements you can leave this as-is."
  63 
  64         creatorForNetloc() is the same as BrowserLikePolicyForHTTPS
  65         except this context factory allows setting the TLS/SSL method to use.
  66 
  67         Default OpenSSL method is TLS_METHOD (also called SSLv23_METHOD)
  68         which allows TLS protocol negotiation.
  69         """
  70         def creatorForNetloc(self, hostname, port):
  71 
  72             # trustRoot set to platformTrust() will use the platform's root CAs.
  73             #
  74             # This means that a website like https://www.cacert.org will be rejected
  75             # by default, since CAcert.org CA certificate is seldom shipped.
  76             return optionsForClientTLS(hostname.decode("ascii"),
  77                                        trustRoot=platformTrust(),
  78                                        extraCertificateOptions={
  79                                             'method': self._ssl_method,
  80                                        })
  81 
  82 except ImportError:
  83 
  84     class ScrapyClientContextFactory(ClientContextFactory):
  85         "A SSL context factory which is more permissive against SSL bugs."
  86         # see https://github.com/scrapy/scrapy/issues/82
  87         # and https://github.com/scrapy/scrapy/issues/26
  88         # and https://github.com/scrapy/scrapy/issues/981
  89 
  90         def __init__(self, method=SSL.SSLv23_METHOD):
  91             self.method = method
  92 
  93         def getContext(self, hostname=None, port=None):
  94             ctx = ClientContextFactory.getContext(self)
  95             # Enable all workarounds to SSL bugs as documented by
  96             # http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html
  97             ctx.set_options(SSL.OP_ALL)
  98             return ctx
  99
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/scrapy/core/downloader/contextfactory.py b/scrapy/core/downloader/contextfactory.py
  --- a/scrapy/core/downloader/contextfactory.py
  +++ b/scrapy/core/downloader/contextfactory.py
  @@ -6,11 +6,16 @@
       from zope.interface.declarations import implementer
   
       # the following should be available from Twisted 14.0.0
  -    from twisted.internet.ssl import optionsForClientTLS, CertificateOptions, platformTrust
  -    from twisted.internet._sslverify import ClientTLSOptions
  +    from twisted.internet.ssl import (optionsForClientTLS,
  +                                      CertificateOptions,
  +                                      platformTrust)
  +
       from twisted.web.client import BrowserLikePolicyForHTTPS
       from twisted.web.iweb import IPolicyForHTTPS
   
  +    from scrapy.core.downloader.tls import ScrapyClientTLSOptions
  +
  +
       @implementer(IPolicyForHTTPS)
       class ScrapyClientContextFactory(BrowserLikePolicyForHTTPS):
           """
  @@ -49,7 +54,7 @@
               return self.getCertificateOptions().getContext()
   
           def creatorForNetloc(self, hostname, port):
  -            return ClientTLSOptions(hostname.decode("ascii"), self.getContext())
  +            return ScrapyClientTLSOptions(hostname.decode("ascii"), self.getContext())
   
   
       @implementer(IPolicyForHTTPS)
  diff --git a/scrapy/core/downloader/tls.py b/scrapy/core/downloader/tls.py
  --- a/scrapy/core/downloader/tls.py
  +++ b/scrapy/core/downloader/tls.py
  @@ -1,6 +1,9 @@
  +import logging
   from OpenSSL import SSL
   
   
  +logger = logging.getLogger(__name__)
  +
   METHOD_SSLv3 = 'SSLv3'
   METHOD_TLS = 'TLS'
   METHOD_TLSv10 = 'TLSv1.0'
  @@ -14,3 +17,36 @@
       METHOD_TLSv11: getattr(SSL, 'TLSv1_1_METHOD', 5),   # TLS 1.1 only
       METHOD_TLSv12: getattr(SSL, 'TLSv1_2_METHOD', 6),   # TLS 1.2 only
   }
  +
  +# ClientTLSOptions requires a recent-enough version of Twisted
  +try:
  +
  +    # taken from twisted/twisted/internet/_sslverify.py
  +    try:
  +        from OpenSSL.SSL import SSL_CB_HANDSHAKE_DONE, SSL_CB_HANDSHAKE_START
  +    except ImportError:
  +        SSL_CB_HANDSHAKE_START = 0x10
  +        SSL_CB_HANDSHAKE_DONE = 0x20
  +
  +    from twisted.internet._sslverify import (ClientTLSOptions,
  +                                             _maybeSetHostNameIndication,
  +                                             verifyHostname,
  +                                             VerificationError)
  +
  +    class ScrapyClientTLSOptions(ClientTLSOptions):
  +        # same as Twisted's ClientTLSOptions,
  +        # except that VerificationError is caught
  +        # and doesn't close the connection
  +        def _identityVerifyingInfoCallback(self, connection, where, ret):
  +            if where & SSL_CB_HANDSHAKE_START:
  +                _maybeSetHostNameIndication(connection, self._hostnameBytes)
  +            elif where & SSL_CB_HANDSHAKE_DONE:
  +                try:
  +                    verifyHostname(connection, self._hostnameASCII)
  +                except VerificationError as e:
  +                    logger.warning(e)
  +
  +except ImportError:
  +    # ImportError should not matter for older Twisted versions
  +    # as the above is not used in the fallback ScrapyClientContextFactory
  +    pass
  
verification_info: {"golden_diff": "diff --git a/scrapy/core/downloader/contextfactory.py b/scrapy/core/downloader/contextfactory.py\n--- a/scrapy/core/downloader/contextfactory.py\n+++ b/scrapy/core/downloader/contextfactory.py\n@@ -6,11 +6,16 @@\n     from zope.interface.declarations import implementer\n \n     # the following should be available from Twisted 14.0.0\n-    from twisted.internet.ssl import optionsForClientTLS, CertificateOptions, platformTrust\n-    from twisted.internet._sslverify import ClientTLSOptions\n+    from twisted.internet.ssl import (optionsForClientTLS,\n+                                      CertificateOptions,\n+                                      platformTrust)\n+\n     from twisted.web.client import BrowserLikePolicyForHTTPS\n     from twisted.web.iweb import IPolicyForHTTPS\n \n+    from scrapy.core.downloader.tls import ScrapyClientTLSOptions\n+\n+\n     @implementer(IPolicyForHTTPS)\n     class ScrapyClientContextFactory(BrowserLikePolicyForHTTPS):\n         \"\"\"\n@@ -49,7 +54,7 @@\n             return self.getCertificateOptions().getContext()\n \n         def creatorForNetloc(self, hostname, port):\n-            return ClientTLSOptions(hostname.decode(\"ascii\"), self.getContext())\n+            return ScrapyClientTLSOptions(hostname.decode(\"ascii\"), self.getContext())\n \n \n     @implementer(IPolicyForHTTPS)\ndiff --git a/scrapy/core/downloader/tls.py b/scrapy/core/downloader/tls.py\n--- a/scrapy/core/downloader/tls.py\n+++ b/scrapy/core/downloader/tls.py\n@@ -1,6 +1,9 @@\n+import logging\n from OpenSSL import SSL\n \n \n+logger = logging.getLogger(__name__)\n+\n METHOD_SSLv3 = 'SSLv3'\n METHOD_TLS = 'TLS'\n METHOD_TLSv10 = 'TLSv1.0'\n@@ -14,3 +17,36 @@\n     METHOD_TLSv11: getattr(SSL, 'TLSv1_1_METHOD', 5),   # TLS 1.1 only\n     METHOD_TLSv12: getattr(SSL, 'TLSv1_2_METHOD', 6),   # TLS 1.2 only\n }\n+\n+# ClientTLSOptions requires a recent-enough version of Twisted\n+try:\n+\n+    # taken from twisted/twisted/internet/_sslverify.py\n+    try:\n+        from OpenSSL.SSL import SSL_CB_HANDSHAKE_DONE, SSL_CB_HANDSHAKE_START\n+    except ImportError:\n+        SSL_CB_HANDSHAKE_START = 0x10\n+        SSL_CB_HANDSHAKE_DONE = 0x20\n+\n+    from twisted.internet._sslverify import (ClientTLSOptions,\n+                                             _maybeSetHostNameIndication,\n+                                             verifyHostname,\n+                                             VerificationError)\n+\n+    class ScrapyClientTLSOptions(ClientTLSOptions):\n+        # same as Twisted's ClientTLSOptions,\n+        # except that VerificationError is caught\n+        # and doesn't close the connection\n+        def _identityVerifyingInfoCallback(self, connection, where, ret):\n+            if where & SSL_CB_HANDSHAKE_START:\n+                _maybeSetHostNameIndication(connection, self._hostnameBytes)\n+            elif where & SSL_CB_HANDSHAKE_DONE:\n+                try:\n+                    verifyHostname(connection, self._hostnameASCII)\n+                except VerificationError as e:\n+                    logger.warning(e)\n+\n+except ImportError:\n+    # ImportError should not matter for older Twisted versions\n+    # as the above is not used in the fallback ScrapyClientContextFactory\n+    pass\n", "issue": "Scrapy 1.1.0 RC3 - exception thrown with invalid ssl certificate\nHello,\n\nI am crawling sometimes websites with an invalid ssl certificate. For example, Scrapy 1.1.0 RC3 fails to open when I do:\n\n> scrapy shell https://www.directoriosanitario.com/directorio\n> or\n> scrapy shell https://saobinv.5go.cc/top/\n\nand throws the following exception:\n\n> twisted.web._newclient.ResponseNeverReceived: [<twisted.python.failure.Failure service_identity.exceptions.VerificationError: VerificationError(errors=[DNSMismatch(mismatched_id=DNS_ID(hostname=b'www.directoriosanitario.com'))])>]\n\nI tried it with Scrapy 1.0.5 on python 2.7 and the spider opens but warns with: \n\n> AttributeError: 'NoneType' object has no attribute 'failVerification'\n\nIs there a way to force the spider to open with Scrapy 1.1.0 RC3?\n\n", "before_files": [{"content": "from OpenSSL import SSL\n\n\nMETHOD_SSLv3 = 'SSLv3'\nMETHOD_TLS = 'TLS'\nMETHOD_TLSv10 = 'TLSv1.0'\nMETHOD_TLSv11 = 'TLSv1.1'\nMETHOD_TLSv12 = 'TLSv1.2'\n\nopenssl_methods = {\n    METHOD_TLS:    SSL.SSLv23_METHOD,                   # protocol negotiation (recommended)\n    METHOD_SSLv3:  SSL.SSLv3_METHOD,                    # SSL 3 (NOT recommended)\n    METHOD_TLSv10: SSL.TLSv1_METHOD,                    # TLS 1.0 only\n    METHOD_TLSv11: getattr(SSL, 'TLSv1_1_METHOD', 5),   # TLS 1.1 only\n    METHOD_TLSv12: getattr(SSL, 'TLSv1_2_METHOD', 6),   # TLS 1.2 only\n}\n", "path": "scrapy/core/downloader/tls.py"}, {"content": "from OpenSSL import SSL\nfrom twisted.internet.ssl import ClientContextFactory\n\ntry:\n\n    from zope.interface.declarations import implementer\n\n    # the following should be available from Twisted 14.0.0\n    from twisted.internet.ssl import optionsForClientTLS, CertificateOptions, platformTrust\n    from twisted.internet._sslverify import ClientTLSOptions\n    from twisted.web.client import BrowserLikePolicyForHTTPS\n    from twisted.web.iweb import IPolicyForHTTPS\n\n    @implementer(IPolicyForHTTPS)\n    class ScrapyClientContextFactory(BrowserLikePolicyForHTTPS):\n        \"\"\"\n        Non-peer-certificate verifying HTTPS context factory\n\n        Default OpenSSL method is TLS_METHOD (also called SSLv23_METHOD)\n        which allows TLS protocol negotiation\n\n        'A TLS/SSL connection established with [this method] may\n         understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols.'\n        \"\"\"\n\n        def __init__(self, method=SSL.SSLv23_METHOD, *args, **kwargs):\n            super(ScrapyClientContextFactory, self).__init__(*args, **kwargs)\n            self._ssl_method = method\n\n        def getCertificateOptions(self):\n            # setting verify=True will require you to provide CAs\n            # to verify against; in other words: it's not that simple\n\n            # backward-compatible SSL/TLS method:\n            #\n            # * this will respect `method` attribute in often recommended\n            #   `ScrapyClientContextFactory` subclass\n            #   (https://github.com/scrapy/scrapy/issues/1429#issuecomment-131782133)\n            #\n            # * getattr() for `_ssl_method` attribute for context factories\n            #   not calling super(..., self).__init__\n            return CertificateOptions(verify=False,\n                        method=getattr(self, 'method',\n                                       getattr(self, '_ssl_method', None)))\n\n        # kept for old-style HTTP/1.0 downloader context twisted calls,\n        # e.g. connectSSL()\n        def getContext(self, hostname=None, port=None):\n            return self.getCertificateOptions().getContext()\n\n        def creatorForNetloc(self, hostname, port):\n            return ClientTLSOptions(hostname.decode(\"ascii\"), self.getContext())\n\n\n    @implementer(IPolicyForHTTPS)\n    class BrowserLikeContextFactory(ScrapyClientContextFactory):\n        \"\"\"\n        Twisted-recommended context factory for web clients.\n\n        Quoting http://twistedmatrix.com/documents/current/api/twisted.web.client.Agent.html:\n        \"The default is to use a BrowserLikePolicyForHTTPS,\n        so unless you have special requirements you can leave this as-is.\"\n\n        creatorForNetloc() is the same as BrowserLikePolicyForHTTPS\n        except this context factory allows setting the TLS/SSL method to use.\n\n        Default OpenSSL method is TLS_METHOD (also called SSLv23_METHOD)\n        which allows TLS protocol negotiation.\n        \"\"\"\n        def creatorForNetloc(self, hostname, port):\n\n            # trustRoot set to platformTrust() will use the platform's root CAs.\n            #\n            # This means that a website like https://www.cacert.org will be rejected\n            # by default, since CAcert.org CA certificate is seldom shipped.\n            return optionsForClientTLS(hostname.decode(\"ascii\"),\n                                       trustRoot=platformTrust(),\n                                       extraCertificateOptions={\n                                            'method': self._ssl_method,\n                                       })\n\nexcept ImportError:\n\n    class ScrapyClientContextFactory(ClientContextFactory):\n        \"A SSL context factory which is more permissive against SSL bugs.\"\n        # see https://github.com/scrapy/scrapy/issues/82\n        # and https://github.com/scrapy/scrapy/issues/26\n        # and https://github.com/scrapy/scrapy/issues/981\n\n        def __init__(self, method=SSL.SSLv23_METHOD):\n            self.method = method\n\n        def getContext(self, hostname=None, port=None):\n            ctx = ClientContextFactory.getContext(self)\n            # Enable all workarounds to SSL bugs as documented by\n            # http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html\n            ctx.set_options(SSL.OP_ALL)\n            return ctx\n", "path": "scrapy/core/downloader/contextfactory.py"}], "after_files": [{"content": "import logging\nfrom OpenSSL import SSL\n\n\nlogger = logging.getLogger(__name__)\n\nMETHOD_SSLv3 = 'SSLv3'\nMETHOD_TLS = 'TLS'\nMETHOD_TLSv10 = 'TLSv1.0'\nMETHOD_TLSv11 = 'TLSv1.1'\nMETHOD_TLSv12 = 'TLSv1.2'\n\nopenssl_methods = {\n    METHOD_TLS:    SSL.SSLv23_METHOD,                   # protocol negotiation (recommended)\n    METHOD_SSLv3:  SSL.SSLv3_METHOD,                    # SSL 3 (NOT recommended)\n    METHOD_TLSv10: SSL.TLSv1_METHOD,                    # TLS 1.0 only\n    METHOD_TLSv11: getattr(SSL, 'TLSv1_1_METHOD', 5),   # TLS 1.1 only\n    METHOD_TLSv12: getattr(SSL, 'TLSv1_2_METHOD', 6),   # TLS 1.2 only\n}\n\n# ClientTLSOptions requires a recent-enough version of Twisted\ntry:\n\n    # taken from twisted/twisted/internet/_sslverify.py\n    try:\n        from OpenSSL.SSL import SSL_CB_HANDSHAKE_DONE, SSL_CB_HANDSHAKE_START\n    except ImportError:\n        SSL_CB_HANDSHAKE_START = 0x10\n        SSL_CB_HANDSHAKE_DONE = 0x20\n\n    from twisted.internet._sslverify import (ClientTLSOptions,\n                                             _maybeSetHostNameIndication,\n                                             verifyHostname,\n                                             VerificationError)\n\n    class ScrapyClientTLSOptions(ClientTLSOptions):\n        # same as Twisted's ClientTLSOptions,\n        # except that VerificationError is caught\n        # and doesn't close the connection\n        def _identityVerifyingInfoCallback(self, connection, where, ret):\n            if where & SSL_CB_HANDSHAKE_START:\n                _maybeSetHostNameIndication(connection, self._hostnameBytes)\n            elif where & SSL_CB_HANDSHAKE_DONE:\n                try:\n                    verifyHostname(connection, self._hostnameASCII)\n                except VerificationError as e:\n                    logger.warning(e)\n\nexcept ImportError:\n    # ImportError should not matter for older Twisted versions\n    # as the above is not used in the fallback ScrapyClientContextFactory\n    pass\n", "path": "scrapy/core/downloader/tls.py"}, {"content": "from OpenSSL import SSL\nfrom twisted.internet.ssl import ClientContextFactory\n\ntry:\n\n    from zope.interface.declarations import implementer\n\n    # the following should be available from Twisted 14.0.0\n    from twisted.internet.ssl import (optionsForClientTLS,\n                                      CertificateOptions,\n                                      platformTrust)\n\n    from twisted.web.client import BrowserLikePolicyForHTTPS\n    from twisted.web.iweb import IPolicyForHTTPS\n\n    from scrapy.core.downloader.tls import ScrapyClientTLSOptions\n\n\n    @implementer(IPolicyForHTTPS)\n    class ScrapyClientContextFactory(BrowserLikePolicyForHTTPS):\n        \"\"\"\n        Non-peer-certificate verifying HTTPS context factory\n\n        Default OpenSSL method is TLS_METHOD (also called SSLv23_METHOD)\n        which allows TLS protocol negotiation\n\n        'A TLS/SSL connection established with [this method] may\n         understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols.'\n        \"\"\"\n\n        def __init__(self, method=SSL.SSLv23_METHOD, *args, **kwargs):\n            super(ScrapyClientContextFactory, self).__init__(*args, **kwargs)\n            self._ssl_method = method\n\n        def getCertificateOptions(self):\n            # setting verify=True will require you to provide CAs\n            # to verify against; in other words: it's not that simple\n\n            # backward-compatible SSL/TLS method:\n            #\n            # * this will respect `method` attribute in often recommended\n            #   `ScrapyClientContextFactory` subclass\n            #   (https://github.com/scrapy/scrapy/issues/1429#issuecomment-131782133)\n            #\n            # * getattr() for `_ssl_method` attribute for context factories\n            #   not calling super(..., self).__init__\n            return CertificateOptions(verify=False,\n                        method=getattr(self, 'method',\n                                       getattr(self, '_ssl_method', None)))\n\n        # kept for old-style HTTP/1.0 downloader context twisted calls,\n        # e.g. connectSSL()\n        def getContext(self, hostname=None, port=None):\n            return self.getCertificateOptions().getContext()\n\n        def creatorForNetloc(self, hostname, port):\n            return ScrapyClientTLSOptions(hostname.decode(\"ascii\"), self.getContext())\n\n\n    @implementer(IPolicyForHTTPS)\n    class BrowserLikeContextFactory(ScrapyClientContextFactory):\n        \"\"\"\n        Twisted-recommended context factory for web clients.\n\n        Quoting http://twistedmatrix.com/documents/current/api/twisted.web.client.Agent.html:\n        \"The default is to use a BrowserLikePolicyForHTTPS,\n        so unless you have special requirements you can leave this as-is.\"\n\n        creatorForNetloc() is the same as BrowserLikePolicyForHTTPS\n        except this context factory allows setting the TLS/SSL method to use.\n\n        Default OpenSSL method is TLS_METHOD (also called SSLv23_METHOD)\n        which allows TLS protocol negotiation.\n        \"\"\"\n        def creatorForNetloc(self, hostname, port):\n\n            # trustRoot set to platformTrust() will use the platform's root CAs.\n            #\n            # This means that a website like https://www.cacert.org will be rejected\n            # by default, since CAcert.org CA certificate is seldom shipped.\n            return optionsForClientTLS(hostname.decode(\"ascii\"),\n                                       trustRoot=platformTrust(),\n                                       extraCertificateOptions={\n                                            'method': self._ssl_method,\n                                       })\n\nexcept ImportError:\n\n    class ScrapyClientContextFactory(ClientContextFactory):\n        \"A SSL context factory which is more permissive against SSL bugs.\"\n        # see https://github.com/scrapy/scrapy/issues/82\n        # and https://github.com/scrapy/scrapy/issues/26\n        # and https://github.com/scrapy/scrapy/issues/981\n\n        def __init__(self, method=SSL.SSLv23_METHOD):\n            self.method = method\n\n        def getContext(self, hostname=None, port=None):\n            ctx = ClientContextFactory.getContext(self)\n            # Enable all workarounds to SSL bugs as documented by\n            # http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html\n            ctx.set_options(SSL.OP_ALL)\n            return ctx\n", "path": "scrapy/core/downloader/contextfactory.py"}]}