3 import os, sys, subprocess, locale, urllib2, gobject
9 def download_chunk(base):
10 # download 10kb a time
11 chunk = base.dl_response.read(10240)
12 base.dl_bytes_so_far += len(chunk)
13 base.tarball_file.write(chunk)
16 base.tarball_file.close()
19 percent = float(base.dl_bytes_so_far) / base.dl_total_size
20 base.progressbar.set_fraction(percent)
21 percent = round(percent*100, 2)
22 base.progressbar.set_text("Downloaded %d" % (percent) + '%')
24 sys.stdout.write("Downloaded %d of %d bytes (%0.2f%%)\r" % (base.dl_bytes_so_far, base.dl_total_size, percent))
26 if base.dl_bytes_so_far >= base.dl_total_size:
27 sys.stdout.write('\n')
31 class TorBrowserLauncher:
32 def __init__(self, current_tbb_version):
34 self.current_tbb_version = current_tbb_version
35 self.discover_arch_lang();
41 # is TBB already installed?
42 if os.path.isfile(self.paths['file']['start']) and os.access(self.paths['file']['start'], os.X_OK):
43 # does the version file exist?
44 if os.path.isfile(self.paths['file']['version']):
45 installed_tbb_version = open(self.paths['file']['version']).read().strip()
47 if installed_tbb_version == current_tbb_version:
48 # current version is tbb is installed, launch it
49 subprocess.call([self.paths['file']['start']])
51 elif installed_tbb_version < self.current_tbb_version:
52 # there is a tbb upgrade available
53 self.set_gui('task', "Your Tor Browser Launcher is out of date. Click Start to download the\nlatest version from https://www.torproject.org.", ['download_tarball', 'download_tarball_sig', 'verify', 'extract', 'run'])
55 # for some reason the installed tbb is newer than the current version?
56 self.set_gui('error', "Something is wrong. The version of Tor Browser Bundle\nyou have installed is newer than the current version?")
59 # if tbb is installed but the version file doesn't exist, something is wrong
60 self.set_gui('error', "Something is wrong. You have the Tor Browser Bundle\ninstalled, but the version file is missing.")
64 # save the current version to the file
65 open(self.paths['file']['version'], 'w').write(self.current_tbb_version)
67 # are the tarball and sig already downloaded?
68 if os.path.isfile(self.paths['file']['tarball']) and os.path.isfile(self.paths['file']['tarball_sig']):
69 # start the gui with verify
70 self.set_gui('task', "You already have Tor Browser Bundle downloaded, but\nit isn't installed yet.", ['verify', 'extract', 'run'])
74 self.set_gui('task', "The first time you run the Tor Browser Launcher you need to download\nthe Tor Browser Bundle. Click Start to download it now from\nhttps://www.torproject.org/.", ['download_tarball', 'download_tarball_sig', 'verify', 'extract', 'run'])
80 # discover the architecture and language
81 def discover_arch_lang(self):
82 # figure out the architecture
83 self.architecture = subprocess.check_output(['arch']).strip('\n')
85 # figure out the language
86 available_languages = ['en-US', 'ar', 'de', 'es-ES', 'fa', 'fr', 'it', 'ko', 'nl', 'pl', 'pt-PT', 'ru', 'vi', 'zh-CN']
87 self.language = locale.getdefaultlocale()[0].replace('_', '-')
88 if self.language not in available_languages:
89 self.language = self.language.split('-')[0]
90 if self.language not in available_languages:
91 for l in available_languages:
92 if l[0:2] == self.language:
94 # if language isn't available, default to english
95 if self.language not in available_languages:
96 self.language = 'en-US'
98 # build all relevant paths
99 def build_paths(self):
100 tbb_data = os.getenv('HOME')+'/.torbrowser'
101 tarball_filename = 'tor-browser-gnu-linux-'+self.architecture+'-'+self.current_tbb_version+'-dev-'+self.language+'.tar.gz'
106 'download': tbb_data+'/download',
107 'tbb': tbb_data+'/tbb/'+self.architecture
110 'version': tbb_data+'/version',
111 'start': tbb_data+'/tbb/'+self.architecture+'/tor-browser_'+self.language+'/start-tor-browser',
112 'tarball': tbb_data+'/download/'+tarball_filename,
113 'tarball_sig': tbb_data+'/download/'+tarball_filename+'.asc'
116 'tarball': 'https://www.torproject.org/dist/torbrowser/linux/'+tarball_filename,
117 'tarball_sig': 'https://www.torproject.org/dist/torbrowser/linux/'+tarball_filename+'.asc'
120 'tarball': tarball_filename,
121 'tarball_sig': tarball_filename+'.asc'
125 # create directories that don't exist
127 if os.path.exists(self.paths['dir']['download']) == False:
128 os.makedirs(self.paths['dir']['download'])
129 if os.path.exists(self.paths['dir']['tbb']) == False:
130 os.makedirs(self.paths['dir']['tbb'])
132 # there are different GUIs that might appear, this sets which one we want
133 def set_gui(self, gui, message, tasks):
135 self.gui_message = message
136 self.gui_task = tasks
138 # build the application's UI
142 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
143 self.window.set_title("Tor Browser Launcher")
144 self.window.set_border_width(10)
146 self.window.connect("delete_event", self.delete_event)
147 self.window.connect("destroy", self.destroy)
149 self.box = gtk.VBox(False, 20)
150 self.window.add(self.box)
152 self.label = gtk.Label("The first time you run the Tor Browser Launcher you need to download the Tor Browser Bundle. Would you like to download it from the following URL now?")
153 self.label.set_line_wrap(True)
154 self.box.pack_start(self.label, True, True, 0)
157 self.progressbar = gtk.ProgressBar(adjustment=None)
158 self.progressbar.set_orientation(gtk.PROGRESS_LEFT_TO_RIGHT)
159 self.box.pack_start(self.progressbar, True, True, 0)
161 self.button_box = gtk.HButtonBox()
162 self.button_box.set_layout(gtk.BUTTONBOX_SPREAD)
163 self.box.pack_start(self.button_box, True, True, 0)
164 self.button_box.show()
166 self.download = gtk.Button("Download")
167 self.download.connect("clicked", self.start_download, None)
168 self.button_box.add(self.download)
171 self.exit = gtk.Button("Exit")
172 self.exit.connect("clicked", self.destroy, None)
173 self.button_box.add(self.exit)
179 def delete_event(self, widget, event, data=None):
182 def destroy(self, widget, data=None):
184 gobject.source_remove(self.timer)
189 def start_download(self, widget, data=None):
190 print 'Starting to download '+self.tarball_url
192 # disable the download button
193 self.download.set_sensitive(False)
195 # initialize the progress bar
196 self.progressbar.set_fraction(0)
197 self.progressbar.set_text('Downloaded 0%')
198 self.progressbar.show()
201 self.dl_response = urllib2.urlopen(self.tarball_url);
203 self.dl_total_size = self.dl_response.info().getheader('Content-Length').strip()
204 self.dl_total_size = int(self.dl_total_size)
205 self.dl_bytes_so_far = 0
207 # set a timer to download more chunks
208 self.timer = gobject.timeout_add(1, download_chunk, self)
210 # open a file to write to
211 self.tarball_file = open(self.tarball_path, 'w')
213 if __name__ == "__main__":
214 print 'Tor Browser Launcher'
215 print 'https://github.com/micahflee/torbrowser-launcher'
217 current_tbb_version = '2.3.25-2'
218 app = TorBrowserLauncher(current_tbb_version)