]> git.lizzy.rs Git - torbrowser-launcher.git/blobdiff - torbrowser-launcher
used wmctrl to finish #17
[torbrowser-launcher.git] / torbrowser-launcher
index 2cf264c1682227ac5ad140f49e35bad18659e6c3..8f57cd50c378e3b3a2da0e54b04943bf20332933 100755 (executable)
@@ -1,4 +1,8 @@
 #!/usr/bin/env python
+
+import gettext
+gettext.install('torbrowser-launcher', '/usr/share/torbrowser-launcher/locale')
+
 from twisted.internet import gtk2reactor
 gtk2reactor.install()
 from twisted.internet import reactor
@@ -7,7 +11,7 @@ import pygtk
 pygtk.require('2.0')
 import gtk
 
-import os, sys, subprocess, locale, urllib2, gobject, time, pickle, json
+import os, sys, subprocess, locale, urllib2, gobject, time, pickle, json, tarfile, psutil
 
 from twisted.web.client import Agent, ResponseDone
 from twisted.web.http_headers import Headers
@@ -40,6 +44,7 @@ class TorBrowserLauncher:
         self.build_paths()
         self.mkdir(self.paths['dir']['download'])
         self.mkdir(self.paths['dir']['tbb'])
+        self.init_gnupg()
 
         # allow buttons to have icons
         try:
@@ -56,28 +61,70 @@ class TorBrowserLauncher:
             if self.load_settings():
                 self.build_paths(self.settings['latest_version'])
 
+                # is tbb already running and we just need to open a new firefox?
+                if self.settings['installed_version']:
+                    vidalia_pid = None
+                    firefox_pid = None
+                    for p in psutil.process_iter():
+                        try:
+                            if p.exe == self.paths['file']['vidalia_bin']:
+                                vidalia_pid = p.pid
+                            if p.exe == self.paths['file']['firefox_bin']:
+                                firefox_pid = p.pid
+                        except:
+                            pass
+
+                    if vidalia_pid and not firefox_pid:
+                        print _('Vidalia is already open, but Firefox is closed. Launching new Firefox.')
+                        subprocess.Popen([self.paths['file']['firefox_bin'], '-no-remote', '-profile', self.paths['file']['firefox_profile']])
+                        return
+                    elif vidalia_pid and firefox_pid:
+                        print _('Vidalia and Firefox are already open, bringing them to focus')
+
+                        # figure out the window ids of vidalia and firefox
+                        vidalia_win_id = None
+                        firefox_win_id = None
+                        p = subprocess.Popen(['wmctrl', '-l', '-p'], stdout=subprocess.PIPE)
+                        for line in p.stdout.readlines():
+                            line_split = line.split()
+                            win_id = line_split[0]
+                            win_pid = int(line_split[2])
+                            if win_pid == vidalia_pid:
+                                vidalia_win_id = win_id
+                            if win_pid == firefox_pid:
+                                firefox_win_id = win_id
+
+                        # bring firefox to front, then vidalia
+                        if firefox_win_id:
+                            subprocess.call(['wmctrl', '-i', '-a', firefox_win_id])
+                        if vidalia_win_id:
+                            subprocess.call(['wmctrl', '-i', '-a', vidalia_win_id])
+
+                        return
+
                 # how long was it since the last update check?
                 # 86400 seconds = 24 hours
                 current_timestamp = int(time.time())
                 if current_timestamp - self.settings['last_update_check_timestamp'] >= 86400:
                     # check for update
                     print 'Checking for update'
-                    self.set_gui('task', "Checking for Tor Browser update."
+                    self.set_gui('task', _("Checking for Tor Browser update.")
                         ['download_update_check', 
                          'attempt_update'])
 
                 else:
                     # no need to check for update
-                    print 'Checked for update within 24 hours, skipping'
+                    print _('Checked for update within 24 hours, skipping')
                     self.start_launcher()
 
             else:
-                self.set_gui('error', "Error loading settings. Delete ~/.torbrowser and try again.", [])
+                self.set_gui('error', _("Error loading settings. Delete ~/.torbrowser and try again."), [])
 
         if self.launch_gui:
             # set up the window
             self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
-            self.window.set_title("Tor Browser")
+            self.window.set_title(_("Tor Browser"))
+            self.window.set_icon_from_file(self.paths['file']['icon'])
             self.window.set_position(gtk.WIN_POS_CENTER)
             self.window.set_border_width(10)
             self.window.connect("delete_event", self.delete_event)
@@ -85,7 +132,6 @@ class TorBrowserLauncher:
 
             # build the rest of the UI
             self.build_ui()
-            reactor.run()
 
     # download or run TBB
     def start_launcher(self):
@@ -97,7 +143,7 @@ class TorBrowserLauncher:
           self.launch_gui = False
         elif self.settings['installed_version'] < self.settings['latest_version']:
           # there is a tbb upgrade available
-          self.set_gui('task', "Your Tor Browser is out of date."
+          self.set_gui('task', _("Your Tor Browser is out of date.")
             ['download_tarball', 
              'download_tarball_sig', 
              'verify', 
@@ -105,21 +151,21 @@ class TorBrowserLauncher:
              'run'])
         else:
           # for some reason the installed tbb is newer than the current version?
-          self.set_gui('error', "Something is wrong. The version of Tor Browser Bundle you have installed is newer than the current version?", [])
+          self.set_gui('error', _("Something is wrong. The version of Tor Browser Bundle you have installed is newer than the current version?"), [])
 
       # not installed
       else:
           # are the tarball and sig already downloaded?
           if os.path.isfile(self.paths['file']['tarball']) and os.path.isfile(self.paths['file']['tarball_sig']):
               # start the gui with verify
-              self.set_gui('task', "Installing Tor Browser."
+              self.set_gui('task', _("Installing Tor Browser.")
                   ['verify', 
                    'extract', 
                    'run'])
 
           # first run
           else:
-              self.set_gui('task', "Downloading and installing Tor Browser."
+              self.set_gui('task', _("Downloading and installing Tor Browser.")
                   ['download_tarball', 
                    'download_tarball_sig', 
                    'verify', 
@@ -158,9 +204,9 @@ class TorBrowserLauncher:
                 try:
                     os.mkdir(homedir, 0700)
                 except:
-                    self.set_gui('error', "Error creating %s" % homedir, [], False)
+                    self.set_gui('error', _("Error creating {0}").format(homedir), [], False)
         if not os.access(homedir, os.W_OK):
-            self.set_gui('error', "%s is not writable" % homedir, [], False)
+            self.set_gui('error', _("{0} is not writable").format(homedir), [], False)
 
         tbb_data = '%s/.torbrowser' % homedir
 
@@ -179,15 +225,20 @@ class TorBrowserLauncher:
                     'data': tbb_data,
                     'download': tbb_data+'/download',
                     'tbb': tbb_data+'/tbb/'+self.architecture,
-                    'gpg': tbb_data+'/gpgtmp'
+                    'gnupg_homedir': tbb_data+'/gnupg_homedir'
                 },
                 'file': {
                     'settings': tbb_data+'/settings',
                     'version': tbb_data+'/version',
                     'start': tbb_data+'/tbb/'+self.architecture+'/tor-browser_'+self.language+'/start-tor-browser',
+                    'vidalia_bin': tbb_data+'/tbb/'+self.architecture+'/tor-browser_'+self.language+'/App/vidalia',
+                    'firefox_bin': tbb_data+'/tbb/'+self.architecture+'/tor-browser_'+self.language+'/App/Firefox/firefox',
+                    'firefox_profile': tbb_data+'/tbb/'+self.architecture+'/tor-browser_'+self.language+'/Data/profile',
                     'update_check': tbb_data+'/download/RecommendedTBBVersions',
-                    'verify': '/usr/share/torbrowser-launcher/verify.sh',
-                    'torproject_pem': '/usr/share/torbrowser-launcher/torproject.pem'
+                    'icon': '/usr/share/pixmaps/torbrowser80.xpm',
+                    'torproject_pem': '/usr/share/torbrowser-launcher/torproject.pem',
+                    'erinn_key': '/usr/share/torbrowser-launcher/erinn.asc',
+                    'sebastian_key': '/usr/share/torbrowser-launcher/sebastian.asc'
                 },
                 'url': {
                     'update_check': 'https://check.torproject.org/RecommendedTBBVersions'
@@ -200,10 +251,27 @@ class TorBrowserLauncher:
         try:
             if os.path.exists(path) == False:
                 os.makedirs(path, 0700)
+                return True
         except:
-            self.set_gui('error', "Cannot create directory %s" % path, [], False)
+            self.set_gui('error', _("Cannot create directory {0}").format(path), [], False)
+            return False
         if not os.access(path, os.W_OK):
-            self.set_gui('error', "%s is not writable" % path, [], False)
+            self.set_gui('error', _("{0} is not writable").format(path), [], False)
+            return False
+        return True
+
+    # if gnupg_homedir isn't set up, set it up
+    def init_gnupg(self):
+        if not os.path.exists(self.paths['dir']['gnupg_homedir']):
+            print _('Creating GnuPG homedir'), self.paths['dir']['gnupg_homedir']
+            if self.mkdir(self.paths['dir']['gnupg_homedir']):
+                # import keys
+                print _('Importing keys')
+                p1 = subprocess.Popen(['/usr/bin/gpg', '--homedir', self.paths['dir']['gnupg_homedir'], '--import', self.paths['file']['erinn_key']])
+                p2 = subprocess.Popen(['/usr/bin/gpg', '--homedir', self.paths['dir']['gnupg_homedir'], '--import', self.paths['file']['sebastian_key']])
+                # wait for keys to import before moving on
+                p1.wait()
+                p2.wait()
 
     # there are different GUIs that might appear, this sets which one we want
     def set_gui(self, gui, message, tasks, autostart=True):
@@ -293,7 +361,7 @@ class TorBrowserLauncher:
         self.window.show()
 
         if self.gui_autostart:
-          self.start(None)
+            self.start(None)
 
     # start button clicked, begin tasks
     def start(self, widget, data=None):
@@ -318,35 +386,35 @@ class TorBrowserLauncher:
         self.gui_task_i += 1
 
         if task == 'download_update_check':
-            print 'Downloading '+self.paths['url']['update_check']
+            print _('Downloading'), self.paths['url']['update_check']
             self.download('update check', self.paths['url']['update_check'], self.paths['file']['update_check'])
         
         if task == 'attempt_update':
-            print 'Checking to see if update it needed'
+            print _('Checking to see if update it needed')
             self.attempt_update()
 
         elif task == 'download_tarball':
-            print 'Downloading '+self.paths['url']['tarball']
+            print _('Downloading'), self.paths['url']['tarball']
             self.download('tarball', self.paths['url']['tarball'], self.paths['file']['tarball'])
 
         elif task == 'download_tarball_sig':
-            print 'Downloading '+self.paths['url']['tarball_sig']
+            print _('Downloading'), self.paths['url']['tarball_sig']
             self.download('signature', self.paths['url']['tarball_sig'], self.paths['file']['tarball_sig'])
 
         elif task == 'verify':
-            print 'Verifying signature'
+            print _('Verifying signature')
             self.verify()
 
         elif task == 'extract':
-            print 'Extracting '+self.paths['filename']['tarball']
+            print _('Extracting'), self.paths['filename']['tarball']
             self.extract()
 
         elif task == 'run':
-            print 'Running '+self.paths['file']['start']
+            print _('Running'), self.paths['file']['start']
             self.run()
         
         elif task == 'start_over':
-            print 'Starting download over again'
+            print _('Starting download over again')
             self.start_over()
 
     def response_received(self, response):
@@ -371,10 +439,10 @@ class TorBrowserLauncher:
                         amount = amount / float(size)
                         break
 
-                self.progress.set_text('Downloaded %2.1f%% (%2.1f %s)' % ((percent * 100.0), amount, units))
+                self.progress.set_text(_('Downloaded')+(' %2.1f%% (%2.1f %s)' % ((percent * 100.0), amount, units)))
 
             def connectionLost(self, reason):
-                print 'Finished receiving body:', reason.getErrorMessage()
+                print _('Finished receiving body:'), reason.getErrorMessage()
                 self.all_done(reason)
 
         dl = FileDownloader(self.file_download, response.length, self.progressbar, self.response_finished)
@@ -391,15 +459,15 @@ class TorBrowserLauncher:
             ## FIXME handle errors
 
     def download_error(self, f):
-        print "Download error", f
-        self.set_gui('error', "Error starting download:\n\n%s\n\nAre you connected to the internet?" % f.value, [], False)
+        print _("Download error"), f
+        self.set_gui('error', _("Error starting download:\n\n{0}\n\nAre you connected to the internet?").format(f.value), [], False)
         self.clear_ui()
         self.build_ui()
 
     def download(self, name, url, path):
         # initialize the progress bar
         self.progressbar.set_fraction(0) 
-        self.progressbar.set_text('Downloading '+name)
+        self.progressbar.set_text(_('Downloading {0}').format(name))
         self.progressbar.show()
         self.refresh_gtk()
 
@@ -410,6 +478,9 @@ class TorBrowserLauncher:
 
         self.file_download = open(path, 'w')
         d.addCallback(self.response_received).addErrback(self.download_error)
+        
+        if not reactor.running:
+            reactor.run()
 
     def attempt_update(self):
         # load the update check file
@@ -431,11 +502,11 @@ class TorBrowserLauncher:
 
             else:
                 # failed to find the latest version
-                self.set_gui('error', "Error checking for updates.", [], False)
+                self.set_gui('error', _("Error checking for updates."), [], False)
         
         except:
             # not a valid JSON object
-            self.set_gui('error', "Error checking for updates.", [], False)
+            self.set_gui('error', _("Error checking for updates."), [], False)
 
         # now start over
         self.clear_ui()
@@ -444,32 +515,37 @@ class TorBrowserLauncher:
     def verify(self):
         # initialize the progress bar
         self.progressbar.set_fraction(0) 
-        self.progressbar.set_text('Verifying Signature')
+        self.progressbar.set_text(_('Verifying Signature'))
         self.progressbar.show()
 
-        p = subprocess.Popen([self.paths['file']['verify'], self.paths['dir']['gpg'], self.paths['file']['tarball_sig']], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+        p = subprocess.Popen(['/usr/bin/gpg', '--homedir', self.paths['dir']['gnupg_homedir'], '--verify', self.paths['file']['tarball_sig']])
         self.pulse_until_process_exits(p)
-
-        output = p.stdout.read()
         
-        if 'Good signature' in output:
+        if p.returncode == 0:
             self.run_task()
         else:
-            self.progressbar.hide()
-            self.label.set_text("SIGNATURE VERIFICATION FAILED!\n\nYou might be under attack, or there might just be a networking problem. Click Start try the download again.")
-            self.gui_tasks = ['start_over']
-            self.gui_task_i = 0
-            self.start_button.show()
-            self.start_button.set_sensitive(True)
+            self.set_gui('task', _("SIGNATURE VERIFICATION FAILED!\n\nYou might be under attack, or there might just be a networking problem. Click Start try the download again."), ['start_over'], False)
+            self.clear_ui()
+            self.build_ui()
+
+            if not reactor.running:
+                reactor.run()
 
     def extract(self):
         # initialize the progress bar
         self.progressbar.set_fraction(0) 
-        self.progressbar.set_text('Installing')
+        self.progressbar.set_text(_('Installing'))
         self.progressbar.show()
+        self.refresh_gtk()
 
-        p = subprocess.Popen(['tar', '-xf', self.paths['file']['tarball'], '-C', self.paths['dir']['tbb']], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        self.pulse_until_process_exits(p)
+        # make sure this file is a tarfile
+        if tarfile.is_tarfile(self.paths['file']['tarball']):
+          tf = tarfile.open(self.paths['file']['tarball'])
+          tf.extractall(self.paths['dir']['tbb'])
+        else:
+            self.set_gui('task', _("Tor Browser Launcher doesn't understand the file format of {0}"), ['start_over'], False)
+            self.clear_ui()
+            self.build_ui()
 
         # installation is finished, so save installed_version
         self.settings['installed_version'] = self.settings['latest_version']
@@ -491,7 +567,7 @@ class TorBrowserLauncher:
 
     # start over and download TBB again
     def start_over(self):
-        self.label.set_text("Downloading Tor Browser Bundle over again.")
+        self.label.set_text(_("Downloading Tor Browser Bundle over again."))
         self.gui_tasks = ['download_tarball', 'download_tarball_sig', 'verify', 'extract', 'run']
         self.gui_task_i = 0
         self.start(None)
@@ -532,13 +608,14 @@ class TorBrowserLauncher:
     def destroy(self, widget, data=None):
         if hasattr(self, 'file_download'):
             self.file_download.close()
-        reactor.stop()
+        if reactor.running:
+            reactor.stop()
 
 if __name__ == "__main__":
     tor_browser_launcher_version = '0.1'
 
-    print 'Tor Browser Launcher'
-    print 'version %s' % (tor_browser_launcher_version)
+    print _('Tor Browser Launcher')
+    print _('version {0}').format(tor_browser_launcher_version)
     print 'https://github.com/micahflee/torbrowser-launcher'
 
     app = TorBrowserLauncher()