diff --git a/onionshare/helpers.py b/onionshare/helpers.py index 33a46ce7..6ad8f80d 100644 --- a/onionshare/helpers.py +++ b/onionshare/helpers.py @@ -176,19 +176,26 @@ class ZipWriter(object): with. If a zip_filename is not passed in, it will use the default onionshare filename. """ - def __init__(self, zip_filename=None): + def __init__(self, zip_filename=None, processed_size_callback=None): if zip_filename: self.zip_filename = zip_filename else: self.zip_filename = '{0:s}/onionshare_{1:s}.zip'.format(tempfile.mkdtemp(), random_string(4, 6)) self.z = zipfile.ZipFile(self.zip_filename, 'w', allowZip64=True) + self.processed_size_callback = processed_size_callback + if self.processed_size_callback is None: + self.processed_size_callback = lambda _: None + self._size = 0 + self.processed_size_callback(self._size) def add_file(self, filename): """ Add a file to the zip archive. """ self.z.write(filename, os.path.basename(filename), zipfile.ZIP_DEFLATED) + self._size += os.path.getsize(filename) + self.processed_size_callback(self._size) def add_dir(self, filename): """ @@ -201,6 +208,8 @@ class ZipWriter(object): if not os.path.islink(full_filename): arc_filename = full_filename[len(dir_to_strip):] self.z.write(full_filename, arc_filename, zipfile.ZIP_DEFLATED) + self._size += os.path.getsize(full_filename) + self.processed_size_callback(self._size) def close(self): """ diff --git a/onionshare/web.py b/onionshare/web.py index 170775e9..8af634eb 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -30,7 +30,7 @@ file_info = [] zip_filename = None zip_filesize = None -def set_file_info(filenames): +def set_file_info(filenames, processed_size_callback=None): """ Using the list of filenames being shared, fill in details that the web page will need to display. This includes zipping up the file in order to @@ -61,7 +61,7 @@ def set_file_info(filenames): file_info['dirs'] = sorted(file_info['dirs'], key=lambda k: k['basename']) # zip up the files and folders - z = helpers.ZipWriter() + z = helpers.ZipWriter(processed_size_callback=processed_size_callback) for info in file_info['files']: z.add_file(info['filename']) for info in file_info['dirs']: diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 8a738d26..a6b81018 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -121,6 +121,9 @@ class OnionShareGui(QtWidgets.QMainWindow): self.status_bar.addPermanentWidget(version_label) self.setStatusBar(self.status_bar) + # status bar, zip progress bar + self._zip_progress_bar = None + # main layout self.layout = QtWidgets.QVBoxLayout() self.layout.addLayout(self.file_selection) @@ -175,12 +178,21 @@ class OnionShareGui(QtWidgets.QMainWindow): def start_server_step2(self): """ - Step 2 in starting the onionshare server. Prepare files for serving. + Step 2 in starting the onionshare server. Zipping up files. """ + # add progress bar to the status bar, indicating the crunching of files. + self._zip_progress_bar = ZipProgressBar(0) + self._zip_progress_bar.total_files_size = OnionShareGui._compute_total_size( + self.file_selection.file_list.filenames) + self.status_bar.clearMessage() + self.status_bar.insertWidget(0, self._zip_progress_bar) + # prepare the files for sending in a new thread def finish_starting_server(self): # prepare files to share - web.set_file_info(self.file_selection.file_list.filenames) + def _set_processed_size(x): + self._zip_progress_bar.processed_size = x + web.set_file_info(self.file_selection.file_list.filenames, processed_size_callback=_set_processed_size) self.app.cleanup_filenames.append(web.zip_filename) self.starting_server_step3.emit() @@ -192,7 +204,7 @@ class OnionShareGui(QtWidgets.QMainWindow): # done self.start_server_finished.emit() - self.status_bar.showMessage(strings._('gui_starting_server2', True)) + #self.status_bar.showMessage(strings._('gui_starting_server2', True)) t = threading.Thread(target=finish_starting_server, kwargs={'self': self}) t.daemon = True t.start() @@ -202,6 +214,11 @@ class OnionShareGui(QtWidgets.QMainWindow): Step 3 in starting the onionshare server. This displays the large filesize warning, if applicable. """ + # Remove zip progress bar + if self._zip_progress_bar is not None: + self.status_bar.removeWidget(self._zip_progress_bar) + self._zip_progress_bar = None + # warn about sending large files over Tor if web.zip_filesize >= 157286400: # 150mb self.filesize_warning.setText(strings._("large_filesize", True)) @@ -225,6 +242,16 @@ class OnionShareGui(QtWidgets.QMainWindow): self.filesize_warning.hide() self.stop_server_finished.emit() + @staticmethod + def _compute_total_size(filenames): + total_size = 0 + for filename in filenames: + if os.path.isfile(filename): + total_size += os.path.getsize(filename) + if os.path.isdir(filename): + total_size += helpers.dir_size(filename) + return total_size + def check_for_requests(self): """ Check for messages communicated from the web app, and update the GUI accordingly. @@ -308,6 +335,43 @@ class OnionShareGui(QtWidgets.QMainWindow): e.ignore() +class ZipProgressBar(QtWidgets.QProgressBar): + def __init__(self, total_files_size): + super(ZipProgressBar, self).__init__() + self.setMaximumHeight(15) + self.setMinimumWidth(200) + self.setValue(0) + self.setFormat(strings._('zip_progress_bar_format')) + self.setStyleSheet( + "QProgressBar::chunk { background-color: #05B8CC; } " + ) + + self._total_files_size = total_files_size + self._processed_size = 0 + + @property + def total_files_size(self): + return self._total_files_size + + @total_files_size.setter + def total_files_size(self, val): + self._total_files_size = val + + @property + def processed_size(self): + return self._processed_size + + @processed_size.setter + def processed_size(self, val): + self._processed_size = val + if self.processed_size < self.total_files_size: + self.setValue(int((self.processed_size * 100) / self.total_files_size)) + elif self.total_files_size != 0: + self.setValue(100) + else: + self.setValue(0) + + def alert(msg, icon=QtWidgets.QMessageBox.NoIcon): """ Pop up a message in a dialog window. diff --git a/resources/locale/cs.json b/resources/locale/cs.json index f33491cf..9be7c830 100644 --- a/resources/locale/cs.json +++ b/resources/locale/cs.json @@ -41,5 +41,7 @@ "gui_please_wait": "Prosím čekejte...", "error_hs_dir_cannot_create": "Nejde vytvořit složka {0:s} pro onion service", "error_hs_dir_not_writable": "Nejde zapisovat do složky {0:s} pro onion service", - "using_ephemeral": "Staring ephemeral Tor onion service and awaiting publication" + "using_ephemeral": "Staring ephemeral Tor onion service and awaiting publication", + "zip_progress_bar_format": "Crunching files: %p%" + } diff --git a/resources/locale/en.json b/resources/locale/en.json index 3d958dbf..42cdc385 100644 --- a/resources/locale/en.json +++ b/resources/locale/en.json @@ -51,5 +51,6 @@ "gui_quit_warning": "Are you sure you want to quit?\nThe URL you are sharing won't exist anymore.", "gui_quit_warning_quit": "Quit", "gui_quit_warning_dont_quit": "Don't Quit", - "error_rate_limit": "An attacker might be trying to guess your URL. To prevent this, OnionShare has automatically stopped the server. To share the files you must start it again and share the new URL." + "error_rate_limit": "An attacker might be trying to guess your URL. To prevent this, OnionShare has automatically stopped the server. To share the files you must start it again and share the new URL.", + "zip_progress_bar_format": "Crunching files: %p%" } diff --git a/resources/locale/eo.json b/resources/locale/eo.json index ae37656e..42c6fd9d 100644 --- a/resources/locale/eo.json +++ b/resources/locale/eo.json @@ -41,5 +41,6 @@ "gui_please_wait": "Bonvolu atendi...", "error_hs_dir_cannot_create": "Ne eblas krei hidden-service-dosierujon {0:s}", "error_hs_dir_not_writable": "Ne eblas konservi dosierojn en hidden-service-dosierujo {0:s}", - "using_ephemeral": "Staring ephemeral Tor onion service and awaiting publication" + "using_ephemeral": "Staring ephemeral Tor hidden service and awaiting publication", + "zip_progress_bar_format": "Crunching files: %p%" } diff --git a/resources/locale/fi.json b/resources/locale/fi.json index cad0ddf7..7e1fb1df 100644 --- a/resources/locale/fi.json +++ b/resources/locale/fi.json @@ -41,5 +41,6 @@ "gui_please_wait": "Odota...", "error_hs_dir_cannot_create": "Piilopalvelulle ei pystytty luomaan hakemistoa {0:s}", "error_hs_dir_not_writable": "Piilopalvelun hakemistoon {0:s} ei voi kirjoittaa", - "using_ephemeral": "Käynnistetään lyhytaikainen Tor piilopalvelu ja odotetaan julkaisua" + "using_ephemeral": "Käynnistetään lyhytaikainen Tor piilopalvelu ja odotetaan julkaisua", + "zip_progress_bar_format": "Tiivistän tiedostoja: %p%" } diff --git a/resources/locale/it.json b/resources/locale/it.json index 00388980..973a0576 100644 --- a/resources/locale/it.json +++ b/resources/locale/it.json @@ -41,5 +41,6 @@ "gui_please_wait": "Attendere prego...", "error_hs_dir_cannot_create": "Impossibile create la cartella per il servizio nascosto {0:s}", "error_hs_dir_not_writable": "La cartella per il servizio nascosto {0:s} non ha i permessi di scrittura", - "using_ephemeral": "Avviamento del servizio nascosto Tor ephemeral e attesa della pubblicazione" -} \ No newline at end of file + "using_ephemeral": "Avviamento del servizio nascosto Tor ephemeral e attesa della pubblicazione", + "zip_progress_bar_format": "Elaborazione files: %p%" +} diff --git a/resources/locale/nl.json b/resources/locale/nl.json index ced76f01..06ea85a1 100644 --- a/resources/locale/nl.json +++ b/resources/locale/nl.json @@ -41,5 +41,6 @@ "gui_please_wait": "Moment geduld...", "error_hs_dir_cannot_create": "Kan verborgen service map {0:s} niet aanmaken", "error_hs_dir_not_writable": "Verborgen service map {0:s} is niet schrijfbaar", - "using_ephemeral": "Kortstondige Tor onion service gestart en in afwachting van publicatie" + "using_ephemeral": "Kortstondige Tor onion service gestart en in afwachting van publicatie", + "zip_progress_bar_format": "Bestanden verwerken: %p%" } diff --git a/resources/locale/tr.json b/resources/locale/tr.json index 3b777b9d..78d590b0 100644 --- a/resources/locale/tr.json +++ b/resources/locale/tr.json @@ -41,5 +41,6 @@ "gui_please_wait": "Lütfen bekleyin...", "error_hs_dir_cannot_create": "Gizli hizmet klasörü {0:s} oluşturulamıyor", "error_hs_dir_not_writable": "Gizle hizmet klasörü {0:s} yazılabilir değil", - "using_ephemeral": "Geçici Tor gizli hizmetine bakılıyor ve yayımı bekleniyor" + "using_ephemeral": "Geçici Tor gizli hizmetine bakılıyor ve yayımı bekleniyor", + "zip_progress_bar_format": "Dosyalar hazırlanıyor: %p%" }