#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#
#
# userland-fetch - a file download utility
#
# A simple program similiar to wget(1), but handles local file copy, ignores
# directories, and verifies file hashes.
#
""" Function to decode and print IOError type exception """
try:
print str(e)
"""Given paths to a file and a detached PGP signature, verify that
the signature is valid for the file. Current configuration allows for
unrecognized keys to be downloaded as necessary."""
# Find the root of the repo so that we can point GnuPG at the right
# configuration and keyring.
if proc.returncode != 0:
return False
# Skip the permissions warning: none of the information here is private,
# so not having to worry about getting mercurial keeping the directory
# unreadable is just simplest.
try:
# If the executable simply couldn't be found, just skip the
# validation.
if e.errno == errno.ENOENT:
return False
if proc.returncode != 0:
# Only print GnuPG's output when there was a problem.
print proc.stdout.read()
return False
return True
"""Given a file-like object and a hash string, verify that the hash
matches the file contents."""
try:
algorithm = "sha256"
# force migration away from sha1
if algorithm == "sha1":
algorithm = "sha256"
try:
m = hashlib.new(algorithm)
return False
while True:
try:
break
if block == '':
break
"""Given a file path and a hash string, verify that the hash matches the
file contents."""
try:
return False
"""Given a file path and a hash string, verify that the hash matches the
payload (uncompressed content) of the file."""
try:
if expr_bz.match(filename):
elif expr_gz.match(filename):
elif expr_tgz.match(filename):
else:
return False
return False
"""Download the content at the given URL to the given filename
(defaulting to the basename of the URL if not given. If 'quiet' is
True, throw away any error messages. Returns the name of the file to
which the content was donloaded."""
try:
return None
# 3xx, 4xx and 5xx (f|ht)tp codes designate unsuccessfull action
return None
try:
return None
while True:
if block == '':
break;
# return the name of the file that we downloaded the data to.
return filename
The pypi scheme has a host (with an empty host defaulting to
pypi.python.org), and a path that should be of the form
only thing that makes sense in this context.
The filename argument is the name of the expected file to download, so
that when pypi gives us multiple archives to choose from, we can pick
the right one.
"""
# We have to use ==; anything fancier would require pkg_resources, but
# really that's the only thing that makes sense in this context.
try:
print "PyPI URLs must be of the form 'pypi:///component==version'"
return None
else:
try:
# Don't wait very long for the connection
print "Unknown component '%s'" % name
else:
return None
return None
try:
print "Unknown version '%s'" % version
return None
return archiveurl
if urls:
print "None of the following URLs delivers '%s':" % filename
else:
print "Couldn't find any suitable URLs"
return None
"""Returns a list of URLs where the file 'filename' might be found,
using 'url', 'search', and $DOWNLOAD_SEARCH_PATH as places to look.
If 'filename' is None, then the list will simply contain 'url'.
"""
if tmp:
# filename should always be first
urls.insert(0, filename)
# command line url is a fallback, so it's last
return urls
"""Attempts to download a file from a number of possible locations.
Generates a list of paths where the file ends up on the local
filesystem. This is a generator because while a download might be
successful, the signature or hash may not validate, and the caller may
want to try again from the next location. The 'link_arg' argument is a
boolean which, when True, specifies that if the source is not a remote
URL and not already found where it should be, to make a symlink to the
source rather than copying it.
"""
print "Source %s..." % url,
print "not found, skipping file copy"
continue
print "\n copying..."
else:
print "\n linking..."
print "\n downloading...",
print "failed"
continue
elif scheme == "pypi":
if nurl:
print "\n translated %s to %s..." % (
print "\n downloading...",
else:
print "\n unable to contact PyPI",
continue
print "failed"
continue
else:
print " unknown scheme '%s'" % scheme
return
print "Usage: %s [-f|--file (file)] [-l|--link] [-h|--hash (hash)] " \
"[-s|--search (search-dir)] [-S|--sigurl (signature-url)] " \
"[-t|--timeout (timeout)] --url (url)" % \
sys.exit(1)
# FLUSH STDOUT
timeout_arg = 300
try:
["file=", "link", "hash=", "search=", "sigurl=",
"timeout=", "url="])
usage()
try:
timeout_arg = int(arg)
print "Invalid argument for %s, should be a " \
sys.exit(1)
if timeout_arg < 0:
print "Invalid argument for %s, should be a " \
sys.exit(1)
else:
print "\n validating signature...",
print "skipping (no signature URL)"
else:
# Put the signature file in the same directory as the
# file we're downloading.
# Validate with the first signature we find.
sig_arg, timeout_arg, link_arg, True):
if sig_file:
if validate_signature(name, sig_file):
print "ok"
else:
print "failed"
break
else:
continue
else:
print "failed (couldn't fetch signature)"
print " validating hash...",
print "skipping (no hash)"
print "hash is: %s" % realhash
print "ok"
else:
if payloadhash == hash_arg:
print "ok"
else:
# If the signature validated, then we assume
# that the expected hash is just a typo, but we
# warn just in case.
if sig_valid:
print "invalid hash! Did you forget " \
"to update it?"
else:
print "corruption detected"
print " expected: %s" % hash_arg
print " actual: %s" % realhash
print " payload: %s" % payloadhash
# If the hash is invalid, but the signature
# validation succeeded, rename the archive (so
# the user doesn't have to re-download it) and
# fail. Otherwise, try to remove the file and
# try again.
if sig_valid:
try:
else:
print "archive saved as %s; " \
"if it isn't corrupt, " \
"rename to %s" % (newname,
name)
sys.exit(1)
else:
try:
continue
sys.exit(0)
sys.exit(1)
if __name__ == "__main__":
main()