home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / python2.4 / site-packages / UpdateManager / DistUpgradeFetcher.py < prev    next >
Encoding:
Python Source  |  2006-08-24  |  9.3 KB  |  241 lines

  1. # DistUpgradeFetcher.py 
  2. #  
  3. #  Copyright (c) 2006 Canonical
  4. #  
  5. #  Author: Michael Vogt <michael.vogt@ubuntu.com>
  6. #  This program is free software; you can redistribute it and/or 
  7. #  modify it under the terms of the GNU General Public License as 
  8. #  published by the Free Software Foundation; either version 2 of the
  9. #  License, or (at your option) any later version.
  10. #  This program is distributed in the hope that it will be useful,
  11. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. #  GNU General Public License for more details.
  14. #  You should have received a copy of the GNU General Public License
  15. #  along with this program; if not, write to the Free Software
  16. #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  17. #  USA
  18.  
  19. import pygtk
  20. pygtk.require('2.0')
  21. import gtk
  22. import os
  23. import apt_pkg
  24. import tarfile
  25. import urllib2
  26. import tempfile
  27. import shutil
  28. import GnuPGInterface
  29. from gettext import gettext as _
  30.  
  31. import GtkProgress
  32. from ReleaseNotesViewer import ReleaseNotesViewer
  33. from Common.utils import *
  34.  
  35. class DistUpgradeFetcher(object):
  36.  
  37.     def __init__(self, parent, new_dist):
  38.         self.parent = parent
  39.         self.window_main = parent.window_main
  40.         self.new_dist = new_dist
  41.  
  42.     def showReleaseNotes(self):
  43.       # FIXME: care about i18n! (append -$lang or something)
  44.       if self.new_dist.releaseNotesURI != None:
  45.           uri = self.new_dist.releaseNotesURI
  46.           self.window_main.set_sensitive(False)
  47.           self.window_main.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  48.           while gtk.events_pending():
  49.               gtk.main_iteration()
  50.  
  51.           # download/display the release notes
  52.           # FIXME: add some progress reporting here
  53.           res = gtk.RESPONSE_CANCEL
  54.           try:
  55.               release_notes = urllib2.urlopen(uri)
  56.               notes = release_notes.read()
  57.               textview_release_notes = ReleaseNotesViewer(notes)
  58.               textview_release_notes.show()
  59.               self.parent.scrolled_notes.add(textview_release_notes)
  60.               self.parent.dialog_release_notes.set_transient_for(self.window_main)
  61.               res = self.parent.dialog_release_notes.run()
  62.               self.parent.dialog_release_notes.hide()
  63.           except urllib2.HTTPError:
  64.               primary = "<span weight=\"bold\" size=\"larger\">%s</span>" % \
  65.                         _("Could not find the release notes")
  66.               secondary = _("The server may be overloaded. ")
  67.               dialog = gtk.MessageDialog(self.window_main,gtk.DIALOG_MODAL,
  68.                                          gtk.MESSAGE_ERROR,gtk.BUTTONS_CLOSE,"")
  69.               dialog.set_title("")
  70.               dialog.set_markup(primary);
  71.               dialog.format_secondary_text(secondary);
  72.               dialog.run()
  73.               dialog.destroy()
  74.           except IOError:
  75.               primary = "<span weight=\"bold\" size=\"larger\">%s</span>" % \
  76.                         _("Could not download the release notes")
  77.               secondary = _("Please check your internet connection.")
  78.               dialog = gtk.MessageDialog(self.window_main,gtk.DIALOG_MODAL,
  79.                                          gtk.MESSAGE_ERROR,gtk.BUTTONS_CLOSE,"")
  80.               dialog.set_title("")
  81.               dialog.set_markup(primary);
  82.               dialog.format_secondary_text(secondary);
  83.               dialog.run()
  84.               dialog.destroy()
  85.           self.window_main.set_sensitive(True)
  86.           self.window_main.window.set_cursor(None)
  87.           # user clicked cancel
  88.           if res == gtk.RESPONSE_CANCEL:
  89.               return False
  90.       return True
  91.  
  92.     def authenticate(self):
  93.         if self.new_dist.upgradeToolSig:
  94.             f = self.tmpdir+"/"+os.path.basename(self.new_dist.upgradeTool)
  95.             sig = self.tmpdir+"/"+os.path.basename(self.new_dist.upgradeToolSig)
  96.             print "authenticate '%s' against '%s' " % (f,sig)
  97.             if not self.gpgauthenticate(f, sig):
  98.                 return False
  99.  
  100.         # we may return False here by default if we want to make a sig
  101.         # mandatory
  102.         return True
  103.  
  104.     def gpgauthenticate(self, file, signature,
  105.                         keyring='/etc/apt/trusted.gpg'):
  106.         """ authenticated a file against a given signature, if no keyring
  107.             is given use the apt default keyring
  108.         """
  109.         gpg = GnuPGInterface.GnuPG()
  110.         gpg.options.extra_args = ['--no-options',
  111.                                   '--no-default-keyring',
  112.                                   '--keyring', keyring]
  113.         proc = gpg.run(['--verify', signature, file],
  114.                        create_fhs=['status','logger','stderr'])
  115.         gpgres = proc.handles['status'].read()
  116.         try:
  117.             proc.wait()
  118.         except IOError,e:
  119.             # gnupg returned a problem (non-zero exit)
  120.             print "exception from gpg: %s" % e
  121.             return False
  122.         if "VALIDSIG" in gpgres:
  123.             return True
  124.         print "invalid result from gpg:"
  125.         print gpgres
  126.         return False
  127.  
  128.     def extractDistUpgrader(self):
  129.           # extract the tarbal
  130.           print "extracting '%s'" % (self.tmpdir+"/"+os.path.basename(self.uri))
  131.           tar = tarfile.open(self.tmpdir+"/"+os.path.basename(self.uri),"r")
  132.           for tarinfo in tar:
  133.               tar.extract(tarinfo)
  134.           tar.close()
  135.           return True
  136.  
  137.     def verifyDistUprader(self):
  138.         # FIXME: check a internal dependency file to make sure
  139.         #        that the script will run correctly
  140.           
  141.         # see if we have a script file that we can run
  142.         self.script = script = "%s/%s" % (self.tmpdir, self.new_dist.name)
  143.         if not os.path.exists(script):
  144.             # no script file found in extracted tarbal
  145.             primary = "<span weight=\"bold\" size=\"larger\">%s</span>" % \
  146.                       _("Could not run the upgrade tool")
  147.             secondary = _("This is most likely a bug in the upgrade tool. "
  148.                           "Please report it as a bug")
  149.             dialog = gtk.MessageDialog(self.window_main,gtk.DIALOG_MODAL,
  150.                                        gtk.MESSAGE_ERROR,gtk.BUTTONS_CLOSE,"")
  151.             dialog.set_title("")
  152.             dialog.set_markup(primary);
  153.             dialog.format_secondary_text(secondary);
  154.             dialog.run()
  155.             dialog.destroy()
  156.             return False
  157.         return True
  158.  
  159.     def fetchDistUpgrader(self):
  160.         # now download the tarball with the upgrade script
  161.         self.tmpdir = tmpdir = tempfile.mkdtemp()
  162.         os.chdir(tmpdir)
  163.  
  164.         # turn debugging on here (if required)
  165.         #apt_pkg.Config.Set("Debug::Acquire::http","1")
  166.  
  167.         progress = GtkProgress.GtkFetchProgress(self.parent,
  168.                                                 _("Downloading the upgrade "
  169.                                                   "tool"),
  170.                                                 _("The upgrade tool will "
  171.                                                   "guide you through the "
  172.                                                   "upgrade process."))
  173.         fetcher = apt_pkg.GetAcquire(progress)
  174.  
  175.         if self.new_dist.upgradeToolSig != None:
  176.             uri = self.new_dist.upgradeToolSig
  177.             af = apt_pkg.GetPkgAcqFile(fetcher,uri, descr=_("Upgrade tool signature"))
  178.         if self.new_dist.upgradeTool != None:
  179.             self.uri = self.new_dist.upgradeTool
  180.             af = apt_pkg.GetPkgAcqFile(fetcher,self.uri, descr=_("Upgrade tool"))
  181.             if fetcher.Run() != fetcher.ResultContinue:
  182.                 return False
  183.             return True
  184.         return False
  185.  
  186.     def runDistUpgrader(self):
  187.         #print "runing: %s" % script
  188.         if os.getuid() != 0:
  189.             os.execv("/usr/bin/gksu",["gksu",self.script])
  190.         else:
  191.             os.execv(self.script,[self.script])
  192.  
  193.     def cleanup(self):
  194.       # cleanup
  195.       os.chdir("..")
  196.       # del tmpdir
  197.       shutil.rmtree(self.tmpdir)
  198.  
  199.     def run(self):
  200.         # see if we have release notes
  201.         if not self.showReleaseNotes():
  202.             return
  203.         if not self.fetchDistUpgrader():
  204.             error(self.window_main,
  205.                   _("Failed to fetch"),
  206.                   _("Fetching the upgrade failed. There may be a network "
  207.                     "problem. "))
  208.             return
  209.         if not self.extractDistUpgrader():
  210.             error(self.window_main,
  211.                   _("Failed to extract"),
  212.                   _("Extracting the upgrade failed. There may be a problem "
  213.                   "with the network or with the server. "))
  214.                   
  215.             return
  216.         if not self.verifyDistUprader():
  217.             error(self.window_main,
  218.                   _("Verfication failed"),
  219.                   _("Verfing the upgrade failed.  There may be a problem "
  220.                     "with the network or with the server. "))
  221.             self.cleanup()
  222.             return
  223.         if not self.authenticate():
  224.             error(self.window_main,
  225.                   _("Authentication failed"),
  226.                   _("Authenticating the upgrade failed. There may be a problem "
  227.                     "with the network or with the server. "))
  228.             self.cleanup()
  229.             return
  230.         self.runDistUpgrader()
  231.  
  232.  
  233. if __name__ == "__main__":
  234.     error(None, "summary","message")
  235.     d = DistUpgradeFetcher(None,None)
  236.     print d.authenticate('/tmp/Release','/tmp/Release.gpg')
  237.  
  238.