#! /usr/bin/env python2.4

#Copyright Rob Bradford <rob@debianplanet.org> 2002
#This program is licensed under the terms of the GNU GPL version 2 or later.
#Please see www.gnu.org for full details

# Checks to see if there any packages on the system are out of date in
# compared to those on security.debian.org

import rfc822,urllib,string,os,sys,StringIO,re,gzip,xml.dom.minidom

def extractText(nodelist):
  text=""
  for node in nodelist:
    if node.nodeType == node.TEXT_NODE:
      text += node.data
  return text

def parseDSA():

  rdf=urllib.urlopen("http://www.debian.org/security/dsa.en.rdf")

  dom = xml.dom.minidom.parse(rdf)

  items = dom.getElementsByTagName("item")

  advisories=[]

  for item in items:
    advisory ={}
    advisory['title'] = extractText(item.getElementsByTagName("title")[0].childNodes)
    advisory['desc'] = extractText(item.getElementsByTagName("description")[0].childNodes)
    advisories+=[advisory]

  return advisories

pipe=os.popen("dpkg --print-installation-architecture")
arch=string.strip(pipe.read())

url="http://security.debian.org/dists/etch/updates/main/binary-%s/Packages.gz" % (arch)


(filename,headers)=urllib.urlretrieve(url)

pkgfile=gzip.open(filename)
pkgdata=pkgfile.read()

packages = string.split(pkgdata,"\n\n")

available={}

for package in packages:

 if package: 
   tmp=StringIO.StringIO(package)
   
   p=rfc822.Message(tmp)
   available[p["Package"]]=p["Version"]

pkgfile=open("/var/lib/dpkg/status")
pkgdata=pkgfile.read()

packages = string.split(pkgdata,"\n\n")

installed={}
for package in packages:

  if package: 
    tmp=StringIO.StringIO(package)
   
    p=rfc822.Message(tmp)
    if (p["Status"]=="install ok installed"):
      installed[p["Package"]]=p["Version"]

report=[]
for item in available.keys():

  if installed.has_key(item):
    if (os.system("dpkg --compare-versions %s le %s" % (available[item],installed[item]))):
       result={}
       result["package"]=item
       result["available"]=available[item]
       result["installed"]=installed[item]
       result["note"]=""       
       for advisory in parseDSA():
         if (string.split(advisory['title'])[1]==item):
           title=string.split(string.strip(advisory['title']))[0]
           desc=string.strip(advisory['desc'])
           result["note"]="%s - %s"  % (title,desc)

       report = report + [result]


if report:

  apt_update = 0
  for entry in report:
    
    # try to check if apt repository is up to date, if not call
    # apt-get update
    # we asume that the available package Version shows up in "apt-cache show packagename"
    cmd="apt-cache show %s" % entry["package"]
    
    update = 1
    r = re.compile('^Version: (.*)$')
    for line in os.popen(cmd).readlines():
      m = r.match(line)
      # 
      if m:
        if (m.group().split(" ")[1] == entry["available"]):
          update = 0
    if update:
      apt_update = 1
      
  print """Versions of the following packages were found to be newer in the
security archives than installed locally. This means you should probably
upgrade\n"""

  print "%s%s%s%s" % (string.ljust("Package",24),string.ljust("Installed",18),string.ljust("Available",18),string.ljust("Note",24))
  
  for entry in report:
    print "%s%s%s%s" % (string.ljust(entry["package"],24),string.ljust(entry["installed"],18),string.ljust(entry["available"],18),string.ljust(entry["note"],24))

  print "\nThe following command will install them:\n"
  sys.stdout.write("apt-get install ")

  for entry in report:
    sys.stdout.write("%s%s" % (entry["package"]," "))

  print '\n'

  if apt_update:
    sys.stdout.write("Also running 'apt-get update' for convenience reasons...")
    os.system("apt-get update >/dev/null")
    sys.stdout.write("done.\n")
    
    
