# getbinpkg.py -- Portage binary-package helper functions
# Copyright 2003-2014 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

from __future__ import unicode_literals

from portage.output import colorize
from portage.cache.mappings import slot_dict_class
from portage.localization import _
import portage
from portage import os
from portage import _encodings
from portage import _unicode_decode
from portage import _unicode_encode
from portage.package.ebuild.fetch import _hide_url_passwd
from _emerge.Package import _all_metadata_keys

import sys
import socket
import time
import tempfile
import base64
from portage.const import CACHE_PATH
import warnings

_all_errors = [NotImplementedError, ValueError, socket.error]

try:
	from html.parser import HTMLParser as html_parser_HTMLParser
except ImportError:
	from HTMLParser import HTMLParser as html_parser_HTMLParser

try:
	from urllib.parse import unquote as urllib_parse_unquote
except ImportError:
	from urllib2 import unquote as urllib_parse_unquote

try:
	import cPickle as pickle
except ImportError:
	import pickle

try:
	import ftplib
except ImportError as e:
	sys.stderr.write(colorize("BAD", "!!! CANNOT IMPORT FTPLIB: ") + str(e) + "\n")
else:
	_all_errors.extend(ftplib.all_errors)

try:
	try:
		from http.client import HTTPConnection as http_client_HTTPConnection
		from http.client import BadStatusLine as http_client_BadStatusLine
		from http.client import ResponseNotReady as http_client_ResponseNotReady
		from http.client import error as http_client_error
	except ImportError:
		from httplib import HTTPConnection as http_client_HTTPConnection
		from httplib import BadStatusLine as http_client_BadStatusLine
		from httplib import ResponseNotReady as http_client_ResponseNotReady
		from httplib import error as http_client_error
except ImportError as e:
	sys.stderr.write(colorize("BAD", "!!! CANNOT IMPORT HTTP.CLIENT: ") + str(e) + "\n")
else:
	_all_errors.append(http_client_error)

_all_errors = tuple(_all_errors)

if sys.hexversion >= 0x3000000:
	# pylint: disable=W0622
	long = int

def make_metadata_dict(data):

	warnings.warn("portage.getbinpkg.make_metadata_dict() is deprecated",
		DeprecationWarning, stacklevel=2)

	myid, _myglob = data
	
	mydict = {}
	for k_bytes in portage.xpak.getindex_mem(myid):
		k = _unicode_decode(k_bytes,
			encoding=_encodings['repo.content'], errors='replace')
		if k not in _all_metadata_keys and k != "CATEGORY":
			continue
		v = _unicode_decode(portage.xpak.getitem(data, k_bytes),
			encoding=_encodings['repo.content'], errors='replace')
		mydict[k] = v

	return mydict

class ParseLinks(html_parser_HTMLParser):
	"""Parser class that overrides HTMLParser to grab all anchors from an html
	page and provide suffix and prefix limitors"""
	def __init__(self):

		warnings.warn("portage.getbinpkg.ParseLinks is deprecated",
			DeprecationWarning, stacklevel=2)

		self.PL_anchors = []
		html_parser_HTMLParser.__init__(self)

	def get_anchors(self):
		return self.PL_anchors
		
	def get_anchors_by_prefix(self, prefix):
		newlist = []
		for x in self.PL_anchors:
			if x.startswith(prefix):
				if x not in newlist:
					newlist.append(x[:])
		return newlist
		
	def get_anchors_by_suffix(self, suffix):
		newlist = []
		for x in self.PL_anchors:
			if x.endswith(suffix):
				if x not in newlist:
					newlist.append(x[:])
		return newlist
		
	def	handle_endtag(self, tag):
		pass

	def	handle_starttag(self, tag, attrs):
		if tag == "a":
			for x in attrs:
				if x[0] == 'href':
					if x[1] not in self.PL_anchors:
						self.PL_anchors.append(urllib_parse_unquote(x[1]))


def create_conn(baseurl, conn=None):
	"""Takes a protocol://site:port/address url, and an
	optional connection. If connection is already active, it is passed on.
	baseurl is reduced to address and is returned in tuple (conn,address)"""

	warnings.warn("portage.getbinpkg.create_conn() is deprecated",
		DeprecationWarning, stacklevel=2)

	parts = baseurl.split("://", 1)
	if len(parts) != 2:
		raise ValueError(_("Provided URI does not "
			"contain protocol identifier. '%s'") % baseurl)
	protocol, url_parts = parts
	del parts

	url_parts = url_parts.split("/")
	host = url_parts[0]
	if len(url_parts) < 2:
		address = "/"
	else:
		address = "/"+"/".join(url_parts[1:])
	del url_parts

	userpass_host = host.split("@", 1)
	if len(userpass_host) == 1:
		host = userpass_host[0]
		userpass = ["anonymous"]
	else:
		host = userpass_host[1]
		userpass = userpass_host[0].split(":")
	del userpass_host

	if len(userpass) > 2:
		raise ValueError(_("Unable to interpret username/password provided."))
	elif len(userpass) == 2:
		username = userpass[0]
		password = userpass[1]
	elif len(userpass) == 1:
		username = userpass[0]
		password = None
	del userpass

	http_headers = {}
	http_params = {}
	if username and password:
		try:
			encodebytes = base64.encodebytes
		except AttributeError:
			# Python 2
			encodebytes = base64.encodestring
		http_headers = {
			b"Authorization": "Basic %s" % \
			encodebytes(_unicode_encode("%s:%s" % (username, password))).replace(
			    b"\012",
			    b""
			  ),
		}

	if not conn:
		if protocol == "https":
			# Use local import since https typically isn't needed, and
			# this way we can usually avoid triggering the global scope
			# http.client ImportError handler (like during stage1 -> stage2
			# builds where USE=ssl is disabled for python).
			try:
				try:
					from http.client import HTTPSConnection as http_client_HTTPSConnection
				except ImportError:
					from httplib import HTTPSConnection as http_client_HTTPSConnection
			except ImportError:
				raise NotImplementedError(
					_("python must have ssl enabled for https support"))
			conn = http_client_HTTPSConnection(host)
		elif protocol == "http":
			conn = http_client_HTTPConnection(host)
		elif protocol == "ftp":
			passive = 1
			if(host[-1] == "*"):
				passive = 0
				host = host[:-1]
			conn = ftplib.FTP(host)
			if password:
				conn.login(username, password)
			else:
				sys.stderr.write(colorize("WARN",
					_(" * No password provided for username")) + " '%s'" % \
					(username,) + "\n\n")
				conn.login(username)
			conn.set_pasv(passive)
			conn.set_debuglevel(0)
		elif protocol == "sftp":
			try:
				import paramiko
			except ImportError:
				raise NotImplementedError(
					_("paramiko must be installed for sftp support"))
			t = paramiko.Transport(host)
			t.connect(username=username, password=password)
			conn = paramiko.SFTPClient.from_transport(t)
		else:
			raise NotImplementedError(_("%s is not a supported protocol.") % protocol)

	return (conn, protocol, address, http_params, http_headers)

def make_ftp_request(conn, address, rest=None, dest=None):
	"""Uses the |conn| object to request the data
	from address and issuing a rest if it is passed."""

	warnings.warn("portage.getbinpkg.make_ftp_request() is deprecated",
		DeprecationWarning, stacklevel=2)

	try:
	
		if dest:
			fstart_pos = dest.tell()
	
		conn.voidcmd("TYPE I")
		fsize = conn.size(address)

		if (rest != None) and (rest < 0):
			rest = fsize+int(rest)
		if rest < 0:
			rest = 0

		if rest != None:
			mysocket = conn.transfercmd("RETR %s" % str(address), rest)
		else:
			mysocket = conn.transfercmd("RETR %s" % str(address))

		mydata = ""
		while 1:
			somedata = mysocket.recv(8192)
			if somedata:
				if dest:
					dest.write(somedata)
				else:
					mydata = mydata + somedata
			else:
				break

		if dest:
			data_size = fstart_pos - dest.tell()
		else:
			data_size = len(mydata)

		mysocket.close()
		conn.voidresp()
		conn.voidcmd("TYPE A")

		return mydata, (fsize != data_size), ""

	except ValueError as e:
		return None, int(str(e)[:4]), str(e)
	

def make_http_request(conn, address, _params={}, headers={}, dest=None):
	"""Uses the |conn| object to request
	the data from address, performing Location forwarding and using the
	optional params and headers."""

	warnings.warn("portage.getbinpkg.make_http_request() is deprecated",
		DeprecationWarning, stacklevel=2)

	rc = 0
	response = None
	while (rc == 0) or (rc == 301) or (rc == 302):
		try:
			if rc != 0:
				conn = create_conn(address)[0]
			conn.request("GET", address, body=None, headers=headers)
		except SystemExit as e:
			raise
		except Exception as e:
			return None, None, "Server request failed: %s" % str(e)
		response = conn.getresponse()
		rc = response.status

		# 301 means that the page address is wrong.
		if ((rc == 301) or (rc == 302)):
			ignored_data = response.read()
			del ignored_data
			for x in str(response.msg).split("\n"):
				parts = x.split(": ", 1)
				if parts[0] == "Location":
					if (rc == 301):
						sys.stderr.write(colorize("BAD",
							_("Location has moved: ")) + str(parts[1]) + "\n")
					if (rc == 302):
						sys.stderr.write(colorize("BAD",
							_("Location has temporarily moved: ")) + \
							str(parts[1]) + "\n")
					address = parts[1]
					break
	
	if (rc != 200) and (rc != 206):
		return None, rc, "Server did not respond successfully (%s: %s)" % (str(response.status), str(response.reason))

	if dest:
		dest.write(response.read())
		return "", 0, ""

	return response.read(), 0, ""


def match_in_array(array, prefix="", suffix="", match_both=1, allow_overlap=0):

	warnings.warn("portage.getbinpkg.match_in_array() is deprecated",
		DeprecationWarning, stacklevel=2)

	myarray = []
	
	if not (prefix and suffix):
		match_both = 0
		
	for x in array:
		add_p = 0
		if prefix and (len(x) >= len(prefix)) and (x[:len(prefix)] == prefix):
			add_p = 1

		if match_both:
			if prefix and not add_p: # Require both, but don't have first one.
				continue
		else:
			if add_p:     # Only need one, and we have it.
				myarray.append(x[:])
				continue

		if not allow_overlap: # Not allow to overlap prefix and suffix
			if len(x) >= (len(prefix)+len(suffix)):
				pass
			else:
				continue          # Too short to match.
		else:
			pass                      # Do whatever... We're overlapping.
		
		if suffix and (len(x) >= len(suffix)) and (x[-len(suffix):] == suffix):
			myarray.append(x)   # It matches
		else:
			continue            # Doesn't match.

	return myarray


def dir_get_list(baseurl, conn=None):
	"""Takes a base url to connect to and read from.
	URI should be in the form <proto>://<site>[:port]<path>
	Connection is used for persistent connection instances."""

	warnings.warn("portage.getbinpkg.dir_get_list() is deprecated",
		DeprecationWarning, stacklevel=2)

	if not conn:
		keepconnection = 0
	else:
		keepconnection = 1

	conn, protocol, address, params, headers = create_conn(baseurl, conn)

	listing = None
	if protocol in ["http","https"]:
		if not address.endswith("/"):
			# http servers can return a 400 error here
			# if the address doesn't end with a slash.
			address += "/"
		page, rc, msg = make_http_request(conn, address, params, headers)
		
		if page:
			parser = ParseLinks()
			parser.feed(_unicode_decode(page))
			del page
			listing = parser.get_anchors()
		else:
			import portage.exception
			raise portage.exception.PortageException(
				_("Unable to get listing: %s %s") % (rc,msg))
	elif protocol in ["ftp"]:
		if address[-1] == '/':
			olddir = conn.pwd()
			conn.cwd(address)
			listing = conn.nlst()
			conn.cwd(olddir)
			del olddir
		else:
			listing = conn.nlst(address)
	elif protocol == "sftp":
		listing = conn.listdir(address)
	else:
		raise TypeError(_("Unknown protocol. '%s'") % protocol)

	if not keepconnection:
		conn.close()

	return listing

def file_get_metadata(baseurl, conn=None, chunk_size=3000):
	"""Takes a base url to connect to and read from.
	URI should be in the form <proto>://<site>[:port]<path>
	Connection is used for persistent connection instances."""

	warnings.warn("portage.getbinpkg.file_get_metadata() is deprecated",
		DeprecationWarning, stacklevel=2)

	if not conn:
		keepconnection = 0
	else:
		keepconnection = 1

	conn, protocol, address, params, headers = create_conn(baseurl, conn)

	if protocol in ["http","https"]:
		headers["Range"] = "bytes=-%s" % str(chunk_size)
		data, _x, _x = make_http_request(conn, address, params, headers)
	elif protocol in ["ftp"]:
		data, _x, _x = make_ftp_request(conn, address, -chunk_size)
	elif protocol == "sftp":
		f = conn.open(address)
		try:
			f.seek(-chunk_size, 2)
			data = f.read()
		finally:
			f.close()
	else:
		raise TypeError(_("Unknown protocol. '%s'") % protocol)
	
	if data:
		xpaksize = portage.xpak.decodeint(data[-8:-4])
		if (xpaksize + 8) > chunk_size:
			myid = file_get_metadata(baseurl, conn, xpaksize + 8)
			if not keepconnection:
				conn.close()
			return myid
		else:
			xpak_data = data[len(data) - (xpaksize + 8):-8]
		del data

		myid = portage.xpak.xsplit_mem(xpak_data)
		if not myid:
			myid = None, None
		del xpak_data
	else:
		myid = None, None

	if not keepconnection:
		conn.close()

	return myid


def file_get(baseurl=None, dest=None, conn=None, fcmd=None, filename=None,
	fcmd_vars=None):
	"""Takes a base url to connect to and read from.
	URI should be in the form <proto>://[user[:pass]@]<site>[:port]<path>"""

	if not fcmd:

		warnings.warn("Use of portage.getbinpkg.file_get() without the fcmd "
			"parameter is deprecated", DeprecationWarning, stacklevel=2)

		return file_get_lib(baseurl, dest, conn)

	variables = {}

	if fcmd_vars is not None:
		variables.update(fcmd_vars)

	if "DISTDIR" not in variables:
		if dest is None:
			raise portage.exception.MissingParameter(
				_("%s is missing required '%s' key") %
				("fcmd_vars", "DISTDIR"))
		variables["DISTDIR"] = dest

	if "URI" not in variables:
		if baseurl is None:
			raise portage.exception.MissingParameter(
				_("%s is missing required '%s' key") %
				("fcmd_vars", "URI"))
		variables["URI"] = baseurl

	if "FILE" not in variables:
		if filename is None:
			filename = os.path.basename(variables["URI"])
		variables["FILE"] = filename

	from portage.util import varexpand
	from portage.process import spawn
	myfetch = portage.util.shlex_split(fcmd)
	myfetch = [varexpand(x, mydict=variables) for x in myfetch]
	fd_pipes = {
		0: portage._get_stdin().fileno(),
		1: sys.__stdout__.fileno(),
		2: sys.__stdout__.fileno()
	}
	sys.__stdout__.flush()
	sys.__stderr__.flush()
	retval = spawn(myfetch, env=os.environ.copy(), fd_pipes=fd_pipes)
	if retval != os.EX_OK:
		sys.stderr.write(_("Fetcher exited with a failure condition.\n"))
		return 0
	return 1

def file_get_lib(baseurl, dest, conn=None):
	"""Takes a base url to connect to and read from.
	URI should be in the form <proto>://<site>[:port]<path>
	Connection is used for persistent connection instances."""

	warnings.warn("portage.getbinpkg.file_get_lib() is deprecated",
		DeprecationWarning, stacklevel=2)

	if not conn:
		keepconnection = 0
	else:
		keepconnection = 1

	conn, protocol, address, params, headers = create_conn(baseurl, conn)

	sys.stderr.write("Fetching '" + str(os.path.basename(address)) + "'\n")
	if protocol in ["http", "https"]:
		data, rc, _msg = make_http_request(conn, address, params, headers, dest=dest)
	elif protocol in ["ftp"]:
		data, rc, _msg = make_ftp_request(conn, address, dest=dest)
	elif protocol == "sftp":
		rc = 0
		try:
			f = conn.open(address)
		except SystemExit:
			raise
		except Exception:
			rc = 1
		else:
			try:
				if dest:
					bufsize = 8192
					while True:
						data = f.read(bufsize)
						if not data:
							break
						dest.write(data)
			finally:
				f.close()
	else:
		raise TypeError(_("Unknown protocol. '%s'") % protocol)
	
	if not keepconnection:
		conn.close()

	return rc


def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=1, makepickle=None):

	warnings.warn("portage.getbinpkg.dir_get_metadata() is deprecated",
		DeprecationWarning, stacklevel=2)

	if not conn:
		keepconnection = 0
	else:
		keepconnection = 1

	cache_path = CACHE_PATH
	metadatafilename = os.path.join(cache_path, 'remote_metadata.pickle')

	if makepickle is None:
		makepickle = CACHE_PATH+"/metadata.idx.most_recent"

	try:
		conn = create_conn(baseurl, conn)[0]
	except _all_errors as e:
		# ftplib.FTP(host) can raise errors like this:
		#   socket.error: (111, 'Connection refused')
		sys.stderr.write("!!! %s\n" % (e,))
		return {}

	out = sys.stdout
	try:
		metadatafile = open(_unicode_encode(metadatafilename,
			encoding=_encodings['fs'], errors='strict'), 'rb')
		mypickle = pickle.Unpickler(metadatafile)
		try:
			mypickle.find_global = None
		except AttributeError:
			# TODO: If py3k, override Unpickler.find_class().
			pass
		metadata = mypickle.load()
		out.write(_("Loaded metadata pickle.\n"))
		out.flush()
		metadatafile.close()
	except (SystemExit, KeyboardInterrupt):
		raise
	except Exception:
		metadata = {}
	if baseurl not in metadata:
		metadata[baseurl] = {}
	if "indexname" not in metadata[baseurl]:
		metadata[baseurl]["indexname"] = ""
	if "timestamp" not in metadata[baseurl]:
		metadata[baseurl]["timestamp"] = 0
	if "unmodified" not in metadata[baseurl]:
		metadata[baseurl]["unmodified"] = 0
	if "data" not in metadata[baseurl]:
		metadata[baseurl]["data"] = {}

	if not os.access(cache_path, os.W_OK):
		sys.stderr.write(_("!!! Unable to write binary metadata to disk!\n"))
		sys.stderr.write(_("!!! Permission denied: '%s'\n") % cache_path)
		return metadata[baseurl]["data"]

	import portage.exception
	try:
		filelist = dir_get_list(baseurl, conn)
	except portage.exception.PortageException as e:
		sys.stderr.write(_("!!! Error connecting to '%s'.\n") %
			_hide_url_passwd(baseurl))
		sys.stderr.write("!!! %s\n" % str(e))
		del e
		return metadata[baseurl]["data"]
	tbz2list = match_in_array(filelist, suffix=".tbz2")
	metalist = match_in_array(filelist, prefix="metadata.idx")
	del filelist
	
	# Determine if our metadata file is current.
	metalist.sort()
	metalist.reverse() # makes the order new-to-old.
	for mfile in metalist:
		if usingcache and \
		   ((metadata[baseurl]["indexname"] != mfile) or \
			  (metadata[baseurl]["timestamp"] < int(time.time() - (60 * 60 * 24)))):
			# Try to download new cache until we succeed on one.
			data = ""
			for trynum in [1, 2, 3]:
				mytempfile = tempfile.TemporaryFile()
				try:
					file_get(baseurl + "/" + mfile, mytempfile, conn)
					if mytempfile.tell() > len(data):
						mytempfile.seek(0)
						data = mytempfile.read()
				except ValueError as e:
					sys.stderr.write("--- %s\n" % str(e))
					if trynum < 3:
						sys.stderr.write(_("Retrying...\n"))
					sys.stderr.flush()
					mytempfile.close()
					continue
				if match_in_array([mfile], suffix=".gz"):
					out.write("gzip'd\n")
					out.flush()
					try:
						import gzip
						mytempfile.seek(0)
						gzindex = gzip.GzipFile(mfile[:-3], 'rb', 9, mytempfile)
						data = gzindex.read()
					except SystemExit as e:
						raise
					except Exception as e:
						mytempfile.close()
						sys.stderr.write(_("!!! Failed to use gzip: ") + str(e) + "\n")
						sys.stderr.flush()
					mytempfile.close()
				try:
					metadata[baseurl]["data"] = pickle.loads(data)
					del data
					metadata[baseurl]["indexname"] = mfile
					metadata[baseurl]["timestamp"] = int(time.time())
					metadata[baseurl]["modified"]  = 0 # It's not, right after download.
					out.write(_("Pickle loaded.\n"))
					out.flush()
					break
				except SystemExit as e:
					raise
				except Exception as e:
					sys.stderr.write(_("!!! Failed to read data from index: ") + str(mfile) + "\n")
					sys.stderr.write("!!! %s" % str(e))
					sys.stderr.flush()
			try:
				metadatafile = open(_unicode_encode(metadatafilename,
					encoding=_encodings['fs'], errors='strict'), 'wb')
				pickle.dump(metadata, metadatafile, protocol=2)
				metadatafile.close()
			except SystemExit as e:
				raise
			except Exception as e:
				sys.stderr.write(_("!!! Failed to write binary metadata to disk!\n"))
				sys.stderr.write("!!! %s\n" % str(e))
				sys.stderr.flush()
			break
	# We may have metadata... now we run through the tbz2 list and check.

	class CacheStats(object):
		from time import time
		def __init__(self, out):
			self.misses = 0
			self.hits = 0
			self.last_update = 0
			self.out = out
			self.min_display_latency = 0.2
		def update(self):
			cur_time = self.time()
			if cur_time - self.last_update >= self.min_display_latency:
				self.last_update = cur_time
				self.display()
		def display(self):
			self.out.write("\r"+colorize("WARN",
				_("cache miss: '") + str(self.misses) + "'") + \
				" --- " + colorize("GOOD", _("cache hit: '") + str(self.hits) + "'"))
			self.out.flush()

	cache_stats = CacheStats(out)
	have_tty = os.environ.get('TERM') != 'dumb' and out.isatty()
	if have_tty:
		cache_stats.display()
	binpkg_filenames = set()
	for x in tbz2list:
		x = os.path.basename(x)
		binpkg_filenames.add(x)
		if x not in metadata[baseurl]["data"]:
			cache_stats.misses += 1
			if have_tty:
				cache_stats.update()
			metadata[baseurl]["modified"] = 1
			myid = None
			for _x in range(3):
				try:
					myid = file_get_metadata(
						"/".join((baseurl.rstrip("/"), x.lstrip("/"))),
						conn, chunk_size)
					break
				except http_client_BadStatusLine:
					# Sometimes this error is thrown from conn.getresponse() in
					# make_http_request().  The docstring for this error in
					# httplib.py says "Presumably, the server closed the
					# connection before sending a valid response".
					conn = create_conn(baseurl)[0]
				except http_client_ResponseNotReady:
					# With some http servers this error is known to be thrown
					# from conn.getresponse() in make_http_request() when the
					# remote file does not have appropriate read permissions.
					# Maybe it's possible to recover from this exception in
					# cases though, so retry.
					conn = create_conn(baseurl)[0]

			if myid and myid[0]:
				metadata[baseurl]["data"][x] = make_metadata_dict(myid)
			elif verbose:
				sys.stderr.write(colorize("BAD",
					_("!!! Failed to retrieve metadata on: ")) + str(x) + "\n")
				sys.stderr.flush()
		else:
			cache_stats.hits += 1
			if have_tty:
				cache_stats.update()
	cache_stats.display()
	# Cleanse stale cache for files that don't exist on the server anymore.
	stale_cache = set(metadata[baseurl]["data"]).difference(binpkg_filenames)
	if stale_cache:
		for x in stale_cache:
			del metadata[baseurl]["data"][x]
		metadata[baseurl]["modified"] = 1
	del stale_cache
	del binpkg_filenames
	out.write("\n")
	out.flush()

	try:
		if "modified" in metadata[baseurl] and metadata[baseurl]["modified"]:
			metadata[baseurl]["timestamp"] = int(time.time())
			metadatafile = open(_unicode_encode(metadatafilename,
				encoding=_encodings['fs'], errors='strict'), 'wb')
			pickle.dump(metadata, metadatafile, protocol=2)
			metadatafile.close()
		if makepickle:
			metadatafile = open(_unicode_encode(makepickle,
				encoding=_encodings['fs'], errors='strict'), 'wb')
			pickle.dump(metadata[baseurl]["data"], metadatafile, protocol=2)
			metadatafile.close()
	except SystemExit as e:
		raise
	except Exception as e:
		sys.stderr.write(_("!!! Failed to write binary metadata to disk!\n"))
		sys.stderr.write("!!! "+str(e)+"\n")
		sys.stderr.flush()

	if not keepconnection:
		conn.close()
	
	return metadata[baseurl]["data"]

def _cmp_cpv(d1, d2):
	cpv1 = d1["CPV"]
	cpv2 = d2["CPV"]
	if cpv1 > cpv2:
		return 1
	elif cpv1 == cpv2:
		return 0
	else:
		return -1

class PackageIndex(object):

	def __init__(self,
		allowed_pkg_keys=None,
		default_header_data=None,
		default_pkg_data=None,
		inherited_keys=None,
		translated_keys=None):

		self._pkg_slot_dict = None
		if allowed_pkg_keys is not None:
			self._pkg_slot_dict = slot_dict_class(allowed_pkg_keys)

		self._default_header_data = default_header_data
		self._default_pkg_data = default_pkg_data
		self._inherited_keys = inherited_keys
		self._write_translation_map = {}
		self._read_translation_map = {}
		if translated_keys:
			self._write_translation_map.update(translated_keys)
			self._read_translation_map.update(((y, x) for (x, y) in translated_keys))
		self.header = {}
		if self._default_header_data:
			self.header.update(self._default_header_data)
		self.packages = []
		self.modified = True

	def _readpkgindex(self, pkgfile, pkg_entry=True):

		allowed_keys = None
		if self._pkg_slot_dict is None or not pkg_entry:
			d = {}
		else:
			d = self._pkg_slot_dict()
			allowed_keys = d.allowed_keys

		for line in pkgfile:
			line = line.rstrip("\n")
			if not line:
				break
			line = line.split(":", 1)
			if not len(line) == 2:
				continue
			k, v = line
			if v:
				v = v[1:]
			k = self._read_translation_map.get(k, k)
			if allowed_keys is not None and \
				k not in allowed_keys:
				continue
			d[k] = v
		return d

	def _writepkgindex(self, pkgfile, items):
		for k, v in items:
			pkgfile.write("%s: %s\n" % \
				(self._write_translation_map.get(k, k), v))
		pkgfile.write("\n")

	def read(self, pkgfile):
		self.readHeader(pkgfile)
		self.readBody(pkgfile)

	def readHeader(self, pkgfile):
		self.header.update(self._readpkgindex(pkgfile, pkg_entry=False))

	def readBody(self, pkgfile):
		while True:
			d = self._readpkgindex(pkgfile)
			if not d:
				break
			mycpv = d.get("CPV")
			if not mycpv:
				continue
			if self._default_pkg_data:
				for k, v in self._default_pkg_data.items():
					d.setdefault(k, v)
			if self._inherited_keys:
				for k in self._inherited_keys:
					v = self.header.get(k)
					if v is not None:
						d.setdefault(k, v)
			self.packages.append(d)

	def write(self, pkgfile):
		if self.modified:
			self.header["TIMESTAMP"] = str(long(time.time()))
			self.header["PACKAGES"] = str(len(self.packages))
		keys = list(self.header)
		keys.sort()
		self._writepkgindex(pkgfile, [(k, self.header[k]) \
			for k in keys if self.header[k]])
		for metadata in sorted(self.packages,
			key=portage.util.cmp_sort_key(_cmp_cpv)):
			metadata = metadata.copy()
			if self._inherited_keys:
				for k in self._inherited_keys:
					v = self.header.get(k)
					if v is not None and v == metadata.get(k):
						del metadata[k]
			if self._default_pkg_data:
				for k, v in self._default_pkg_data.items():
					if metadata.get(k) == v:
						metadata.pop(k, None)
			keys = list(metadata)
			keys.sort()
			self._writepkgindex(pkgfile,
				[(k, metadata[k]) for k in keys if metadata[k]])
