1 # Copyright (C) 2011, Thomas Leonard
2 # See the README file for details, or visit http://0install.net.
4 import sys
, os
, socket
, ssl
6 from zeroinstall
import _
7 from zeroinstall
.injector
import download
9 import urllib2
, httplib
11 # This works on Debian. It probably needs to be updated to handle other platforms.
12 ca_file
= "/etc/ssl/certs/ca-certificates.crt"
14 if os
.path
.exists(ca_file
):
15 class ValidatingHTTPSConnection(httplib
.HTTPSConnection
):
17 sock
= socket
.create_connection((self
.host
, self
.port
), self
.timeout
)
21 self
.sock
= ssl
.wrap_socket(sock
, cert_reqs
= ssl
.CERT_REQUIRED
, ca_certs
= ca_file
)
23 class ValidatingHTTPSHandler(urllib2
.HTTPSHandler
):
24 def https_open(self
, req
):
25 return self
.do_open(self
.getConnection
, req
)
27 def getConnection(self
, host
, timeout
=300):
28 return ValidatingHTTPSConnection(host
)
30 urlopener
= urllib2
.build_opener(ValidatingHTTPSHandler
)
32 # Builds an opener that overrides the default HTTPS handler with our one
33 _my_urlopen
= urllib2
.build_opener(ValidatingHTTPSHandler()).open
35 _my_urlopen
= urllib2
.urlopen
37 def download_in_thread(url
, target_file
, if_modified_since
, notify_done
):
39 #print "Child downloading", url
40 if url
.startswith('http:') or url
.startswith('https:') or url
.startswith('ftp:'):
41 req
= urllib2
.Request(url
)
42 if url
.startswith('http:') and if_modified_since
:
43 req
.add_header('If-Modified-Since', if_modified_since
)
44 src
= _my_urlopen(req
)
46 raise Exception(_('Unsupported URL protocol in: %s') % url
)
50 except AttributeError:
51 sock
= src
.fp
.fp
._sock
# Python 2.5 on FreeBSD
55 target_file
.write(data
)
58 notify_done(download
.RESULT_OK
)
59 except (urllib2
.HTTPError
, urllib2
.URLError
, httplib
.HTTPException
) as ex
:
60 if isinstance(ex
, urllib2
.HTTPError
) and ex
.code
== 304: # Not modified
61 notify_done(download
.RESULT_NOT_MODIFIED
)
63 #print >>sys.stderr, "Error downloading '" + url + "': " + (str(ex) or str(ex.__class__.__name__))
64 __
, ex
, tb
= sys
.exc_info()
65 notify_done(download
.RESULT_FAILED
, (download
.DownloadError(unicode(ex
)), tb
))
66 except Exception as ex
:
67 __
, ex
, tb
= sys
.exc_info()
68 notify_done(download
.RESULT_FAILED
, (ex
, tb
))