def _setup_environment(self): """Finish misc startup tasks like starting logging, zipping any crash logs from the last run, installing signal handlers, startup argument handler, etc""" #apply the necessary hacks: Twisted.apply_dns_hack() Twisted.apply_dns_hack2() if System.IS_WINDOWS: Win32HiddenWindowHack.apply() #start listening for connections from any other instances of BitBlinder StartupServer.start() Profiler.start() #Make sure we log ALL exceptions Twisted.install_exception_handlers(self.on_quit_signal) #Set the signal handler for exiting def sig_handler(signum, frame): self.on_quit_signal() signal.signal(signal.SIGTERM, sig_handler) #make the gui: GUIController.start() self.gui = GUIController.get() #do some tests to see how this user's network is configured: NetworkState.test_network_state() #TODO: figure out what needs to change in the wrapper and submit a fix warnings.filterwarnings('ignore', module=".*TwistedProtocolWrapper.*", lineno=447)
def on_response(self, dialog, response_id): if (response_id == gtk.RESPONSE_OK): #get the login details, etc: self.username = str(self.nameEntry.get_text()) if not self.username: GUIController.get().show_msgbox("You must enter a username of some sort.", title="Invalid Username") return #ship off to the ftp server! log_msg("archiving stuffs", 2) startiter = self.textbuffer.get_start_iter() enditer = self.textbuffer.get_end_iter() buf = self.textbuffer.get_text(startiter, enditer) ClientUtil.create_error_archive(buf) log_msg("submiting archive", 2) def response(success): if success: GUIController.get().show_msgbox("The bug report was sent successfully.", title="Success!") else: if not ProgramState.DONE: GUIController.get().show_msgbox("The bug report failed. You can submit the bug manually at:", title="Too Much Fail", link=GTKUtils.make_html_link("http://innomi.net/bugs/report/1", 'http://innomi.net/bugs/report/1')) ftpSubmitter = ErrorReporting.send_error_report() ftpSubmitter.cb = response GUIController.get().show_msgbox("The bug report is being sent. BitBlinder will alert you when it is finished.", title="Thanks!") self.dia.destroy() elif (response_id == gtk.RESPONSE_CANCEL): self.dia.destroy() else: log_msg("canceled error submition", 2)
def _remove_file_cb(self, widget=None, event=None): torrentsToDelete = self._get_selected_torrents() if len(torrentsToDelete) <= 0: return def do_remove(dialog, response): for torrentHash in torrentsToDelete: if response in (0, -4): return elif response == 1: self.app.remove_download(torrentHash, False, False) elif response == 2: self.app.remove_download(torrentHash, True, False) elif response == 3: self.app.remove_download(torrentHash, False, True) elif response == 4: self.app.remove_download(torrentHash, True, True) else: raise Exception( "Got bad response from delete torrent dialog! %s" % (response)) GUIController.get().show_msgbox( "Would you like to delete both the torrent file and all data that has been downloaded?", title="Delete Torrent?", cb=do_remove, buttons=("Cancel", 0, "Remove from list", 1, "Delete .torrent ONLY", 2, "Delete data ONLY", 3, "Delete .torrent AND data", 4), width=400)
def launch_failed(self, reason): log_ex(reason, "Failed to launch application: %s" % (self.name), [DependencyError]) GUIController.get().show_msgbox("Failed to launch %s: %s" % (self.name, reason), title="Error", makeSafe=True) if self.startupDeferred: tempDeferred = self.startupDeferred self.startupDeferred = None tempDeferred.callback(False)
def msg_event(self, event): for badMessage in self.badMessages: if badMessage in event.msg: if not self.badMessages[badMessage]: GUIController.get().show_msgbox(event.msg, title=event.level) self.badMessages[badMessage] = True
def on_response(self, dialog, responseId): if responseId == gtk.RESPONSE_OK: startiter = self.textbuffer.get_start_iter() enditer = self.textbuffer.get_end_iter() buf = self.textbuffer.get_text(startiter, enditer) buf = buf.replace("\r", "") buf = buf.replace(" ", "") buf = buf.replace("\t", "") trackerList = buf.split("\n") #remove duplicates newTrackerSet = set(trackerList) #figure out what lines are invalid toRemove = [] badTrackerList = [] trackerRegex = re.compile("^https?://.*$", re.IGNORECASE) for line in newTrackerSet: if not trackerRegex.match(line): toRemove.append(line) if line: badTrackerList.append(line) if badTrackerList: GUIController.get().show_msgbox("Bad format for tracker(s). These trackers were ignored: \n%s\n\nShould be like this:\nhttp://something.com/whatever" % ("\n".join(badTrackerList)), title="Bad format!") return #then remove them for line in toRemove: newTrackerSet.remove(line) if len(newTrackerSet) <= 0: self.callback(None) else: self.callback(list(newTrackerSet)) elif responseId in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT): self.callback(None) else: raise Exception("Unknown gtk response: %s" % (responseId)) self.dia.destroy()
def unpickle(obj, fileName): """main unpickle function""" config = configobj.ConfigObj(fileName, encoding="utf-8") # generate the config spec: for name in config.keys(): # dont load settings that no longer exist if not obj.ranges.has_key(name): continue range = obj.ranges[name] defaultVal = obj.defaults[name] loadedVal = config[name] try: if type(range) == types.TupleType and type(range[0]) != types.StringType: if type(range[0]) == types.FloatType: loadedVal = float(loadedVal) assert loadedVal <= range[1], "%s not in range %s" % (loadedVal, range) assert loadedVal >= range[0], "%s not in range %s" % (loadedVal, range) elif type(range[0]) == types.IntType: loadedVal = int(loadedVal) assert loadedVal <= range[1], "%s not in range %s" % (loadedVal, range) assert loadedVal >= range[0], "%s not in range %s" % (loadedVal, range) else: raise Exception("Weird type for range: %s" % (range)) elif type(range) == types.TupleType and type(range[0]) == types.StringType: assert loadedVal in range, "%s not in range %s" % (loadedVal, range) elif type(defaultVal) == types.BooleanType: if loadedVal.lower() in ("1", "true", "t", "y", "yes", "on"): loadedVal = True else: loadedVal = False # default to text entry for special types that need validation elif type(range) == types.StringType: if range == "folder": assert os.path.isdir(loadedVal), "%s is not a valid directory" % (loadedVal) elif range == "ip": if loadedVal: assert isIPAddress(loadedVal), "%s is not a valid ip address" % (loadedVal) elif range in ("GB", "KBps"): loadedVal = int(loadedVal) elif range == "password": pass elif range == "scheduler": pass elif range == "anonymity level": loadedVal = int(loadedVal) assert loadedVal in (1, 2, 3), "anonymity value not in range (1,3)" else: regex = re.compile(range) assert regex.match(loadedVal), "settings string (%s) does not match expression (%s)" % ( loadedVal, range, ) else: raise Exception("Unknown range/value combination (%s, %s)" % (range, defaultVal)) except Exception, e: log_msg("Bad option value (%s) for option %s" % (e, name), 0) GUIController.get().show_msgbox("Bad option value (%s) for option %s" % (e, name)) setattr(obj, name, loadedVal)
def hash_done(self, ourHash): self.downloadingUpdate = False if ourHash.lower() != self.trueHash.lower(): self.hash_failed("Download hash was wrong.") return shutil.move(Globals.UPDATE_FILE_NAME+".download", Globals.UPDATE_FILE_NAME) #Now ask the user if they want to update: GUIController.get().update_prompt(self.newVersion, "%s\n\nWould you like to apply the update right now?" % (self.updateString), self.restart_for_update)
def restart_for_update(self, newVersion): """Trigger an update after it has been downloaded""" if System.IS_WINDOWS: self.APPLY_UPDATE = True GlobalEvents.throw_event("quit_signal") else: #just prompt the user, since we cant really auto update in linux: GUIController.get().show_msgbox("Please close BitBlinder and run the following commands to update BitBlinder:\n\nsudo dpkg -P python-bitblinder\nsudo dpkg -i %s" % (Globals.UPDATE_FILE_NAME))
def on_open_web_page_signal(self, url, openDirectly=True): """Either use our Firefox application to open the web page (if openDirectly is False and we actually have a Firefox application), or just use their default browser.""" if not self.ffApp or openDirectly: try: webbrowser.open(url) except Exception, error: GUIController.get().show_msgbox("Could not open website: %s" % (error))
def dht_cb(self, widget=None): selectedTorrents = GUIController.get().btWindow._get_selected_torrents() if len(selectedTorrents) != 1: log_msg("Select a torrent for the DHT request in the BitTorrent window", 0) return infohash = selectedTorrents[0] def callback(*args): log_msg("Got DHT response! %s" % (str(args))) GUIController.get().btWindow.app.btInstance.dht.circ = self.getSelected() GUIController.get().btWindow.app.btInstance.dht.get_peers(infohash, callback)
def response(success): if success: GUIController.get().show_msgbox( "The bug report was sent successfully.", title="Success!") else: if not ProgramState.DONE: GUIController.get().show_msgbox( "The bug report failed. You can submit the bug manually at:", title="Too Much Fail", link=GTKUtils.make_html_link( "http://innomi.net/bugs/report/1", 'http://innomi.net/bugs/report/1'))
def on_login_success(self, bankApp, text): #show the server message if there was any: if text: GUIController.get().show_msgbox(text, "Server Notice") #save all this information to the settings files if necessary: settings = GlobalSettings.get() settings.save_password = self.savePassCheck.get_active() if not settings.save_password: self.username = "" self.password = "" settings.username = self.username settings.password = self.password settings.save() self.succeeded = True self.dia.destroy()
def prompt_about_bug_report(): coreSettings = CoreSettings.get() def response(dialog, response): if response == 0: coreSettings.sendBugReports = True send_error_report() else: coreSettings.sendBugReports = False coreSettings.save() if not coreSettings.askedAboutBugReports: GUIController.get().show_msgbox("BitBlinder had errors or crashed last time it was run. Is it ok to send the anonymized error report to the developers? If you dont, they will not be able to fix the errors! :(", title="Please Send Us Your Errors!", cb=response, buttons=("Yes, send anonymous crash data", 0, "No", 1), width=400) coreSettings.askedAboutBugReports = True coreSettings.save() elif coreSettings.sendBugReports: send_error_report()
def on_response(self, dialog, response_id): if response_id == gtk.RESPONSE_YES: self.cb(self.newVersion) else: log_msg("User elected not to update.", 4) GUIController.get().updateDialog = None self.dia.destroy()
def on_response(self, dialog, response_id): if (response_id == gtk.RESPONSE_YES): self.cb(self.newVersion) else: log_msg("User elected not to update.", 4) GUIController.get().updateDialog = None self.dia.destroy()
def dht_cb(self, widget=None): selectedTorrents = GUIController.get().btWindow._get_selected_torrents( ) if len(selectedTorrents) != 1: log_msg( "Select a torrent for the DHT request in the BitTorrent window", 0) return infohash = selectedTorrents[0] def callback(*args): log_msg("Got DHT response! %s" % (str(args))) GUIController.get( ).btWindow.app.btInstance.dht.circ = self.getSelected() GUIController.get().btWindow.app.btInstance.dht.get_peers( infohash, callback)
def on_new_balance_from_bank(self, newBalance): """Called any time we learn a new bank balance from some message. Checks if we maybe want to get more coins now. @param newBalance: the new balance @type newBalance: int""" #TODO: disassociate testing code with real code. Put it in a subclass or testing harness instead #to test interactions when we run out of credits if ProgramState.DEBUG and ProgramState.USE_GTK and GUIController.get( ) and GUIController.get().socksClientWindow.bankDisplay: bankDisplay = GUIController.get().socksClientWindow.bankDisplay if bankDisplay.entry.get_text(): newBalance = int(bankDisplay.entry.get_text()) if ProgramState.DEBUG and self._forceSetBalance != None: newBalance = self._forceSetBalance self.lastBankBalance = long(newBalance) self.balanceLastUpdatedAt = time.time() self.check_wallet_balance()
def _remove_file_cb(self, widget=None, event=None): torrentsToDelete = self._get_selected_torrents() if len(torrentsToDelete) <= 0: return def do_remove(dialog, response): for torrentHash in torrentsToDelete: if response in (0, -4): return elif response == 1: self.app.remove_download(torrentHash, False, False) elif response == 2: self.app.remove_download(torrentHash, True, False) elif response == 3: self.app.remove_download(torrentHash, False, True) elif response == 4: self.app.remove_download(torrentHash, True, True) else: raise Exception("Got bad response from delete torrent dialog! %s" % (response)) GUIController.get().show_msgbox("Would you like to delete both the torrent file and all data that has been downloaded?", title="Delete Torrent?", cb=do_remove, buttons=("Cancel", 0, "Remove from list", 1, "Delete .torrent ONLY", 2, "Delete data ONLY", 3, "Delete .torrent AND data", 4), width=400)
def show_tracker_shutdown_prompt(self): def callback(dialog, response): self.exitDialog = None if response == gtk.RESPONSE_OK: self.app.force_stop() self.exitDialog = GUIController.get().show_msgbox( "Bitblinder is sending shutdown events to trackers. If you are using only public trackers, you can safely exit immediately.", cb=callback, buttons=("Exit Now", gtk.RESPONSE_OK))
def add(self, hash, data): #check if we already know about this torrent: if hash in self.downloads: #if so, just add the trackers and return: self.downloads[hash].add_trackers(data['metainfo']) #and tell the user that that is what happened, so they're not suprised: GUIController.get().show_msgbox( "BitBlinder added all new trackers from that .torrent file.", title="Already Downloading Torrent!") return None self.counter += 1 peer_id = createPeerID() d = Torrent(self, hash, data['metainfo'], self.config, peer_id, self.dht, self.can_open_more_connections) self.torrent_list.append(hash) self.downloads[hash] = d #added because this normally happens when scanning: self.torrent_cache[hash] = data return d
def check_port(portNum, successFunc): if portNum: pid = System.get_pid_from_port(portNum) if pid > 0: controller = GUIController.get() if controller: controller.prompt_about_port(portNum, successFunc) else: log_msg("no gui controller yet to prompt_about_port", 2) return successFunc()
def on_response(self, dialog, response_id): if (response_id == gtk.RESPONSE_OK): #get the login details, etc: self.username = str(self.nameEntry.get_text()) if not self.username: GUIController.get().show_msgbox( "You must enter a username of some sort.", title="Invalid Username") return #ship off to the ftp server! log_msg("archiving stuffs", 2) startiter = self.textbuffer.get_start_iter() enditer = self.textbuffer.get_end_iter() buf = self.textbuffer.get_text(startiter, enditer) ClientUtil.create_error_archive(buf) log_msg("submiting archive", 2) def response(success): if success: GUIController.get().show_msgbox( "The bug report was sent successfully.", title="Success!") else: if not ProgramState.DONE: GUIController.get().show_msgbox( "The bug report failed. You can submit the bug manually at:", title="Too Much Fail", link=GTKUtils.make_html_link( "http://innomi.net/bugs/report/1", 'http://innomi.net/bugs/report/1')) ftpSubmitter = ErrorReporting.send_error_report() ftpSubmitter.cb = response GUIController.get().show_msgbox( "The bug report is being sent. BitBlinder will alert you when it is finished.", title="Thanks!") self.dia.destroy() elif (response_id == gtk.RESPONSE_CANCEL): self.dia.destroy() else: log_msg("canceled error submition", 2)
def toggle_anon_cb(self, widget): def apply(app): app.settings.pathLength = self.anonEntry.get_value() app.settings.on_apply(app, "") app.settings.save() app = self.selectedApp if not app: apply(self.app) return def cb(dialog, response, app=app): if response == gtk.RESPONSE_OK: apply(app) elif response in (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT): self.anonEntry.set_value(app.settings.pathLength) else: raise Exception("Unknown response: %s" % (response)) if app.settings.pathLength != self.anonEntry.get_value(): if app.is_running(): GUIController.get().show_msgbox("Changing the mode will restart %s. Ok?" % (app.name), title="Restart?", cb=cb, buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) else: cb(None, gtk.RESPONSE_OK)
def on_update(self): """is responsible for updating the stat_dict""" global _showedLowMoneyWarning currentBalance = Bank.get().get_expected_balance() #if you have <HIGH_WATER credits: if currentBalance < LOW_MONEY_WARNING_LEVEL: #if you are NOT correctly set up as a relay, inform the user that they must be a relay for this system to keep working #are we not yet acting as a relay? if not Tor.get().settings.beRelay: #have we already warned them? if not _showedLowMoneyWarning: _showedLowMoneyWarning = True #Prompt the user about whether they want to run a relay and earn credits or not: if CoreSettings.get().askAboutRelay: GUIController.get().on_low_credits() self.statistics["Local Balance"].stat_value = str(Bank.get().get_wallet_balance()) self.statistics["Bank Balance"].stat_value = str(currentBalance) self.statistics["Credits Earned"].stat_value = str(Bank.get().get_earnings()) for text, label in self.statistics.iteritems(): label.set_text(text + ": " + label.stat_value)
def _stop_done(self, result): Basic.validate_result(result, "BitTorrentWindow::_stop_done") if not BitBlinder.get().is_running(): GlobalEvents.throw_event("quit_signal") else: #are there any other apps using bitblinder? for app in BitBlinder.get().applications.values(): #if there is another app, dont bother shutting down everything if app.is_running() and app != Bank.get(): return #ok, check if there is a relay then if Tor.get().settings.beRelay: #then we should prompt about shutdown def callback(dialog, response): if response == gtk.RESPONSE_YES: self._do_quit() msgText = "BitBlinder is acting as a server and help others be anonymous, and earning you more credits!\n\nDo you also want to stop the server?" GUIController.get().show_preference_prompt(msgText, "Stop Relay?", callback, "promptAboutRelayQuit") else: #otherwise shutdown completely: self._do_quit()
def on_update(self): """is responsible for updating the stat_dict""" global _showedLowMoneyWarning currentBalance = Bank.get().get_expected_balance() #if you have <HIGH_WATER credits: if currentBalance < LOW_MONEY_WARNING_LEVEL: #if you are NOT correctly set up as a relay, inform the user that they must be a relay for this system to keep working #are we not yet acting as a relay? if not Tor.get().settings.beRelay: #have we already warned them? if not _showedLowMoneyWarning: _showedLowMoneyWarning = True #Prompt the user about whether they want to run a relay and earn credits or not: if CoreSettings.get().askAboutRelay: GUIController.get().on_low_credits() self.statistics["Local Balance"].stat_value = str( Bank.get().get_wallet_balance()) self.statistics["Bank Balance"].stat_value = str(currentBalance) self.statistics["Credits Earned"].stat_value = str( Bank.get().get_earnings()) for text, label in self.statistics.iteritems(): label.set_text(text + ": " + label.stat_value)
def _stop_done(self, result): Basic.validate_result(result, "BitTorrentWindow::_stop_done") if not BitBlinder.get().is_running(): GlobalEvents.throw_event("quit_signal") else: #are there any other apps using bitblinder? for app in BitBlinder.get().applications.values(): #if there is another app, dont bother shutting down everything if app.is_running() and app != Bank.get(): return #ok, check if there is a relay then if Tor.get().settings.beRelay: #then we should prompt about shutdown def callback(dialog, response): if response == gtk.RESPONSE_YES: self._do_quit() msgText = "BitBlinder is acting as a server and help others be anonymous, and earning you more credits!\n\nDo you also want to stop the server?" GUIController.get().show_preference_prompt( msgText, "Stop Relay?", callback, "promptAboutRelayQuit") else: #otherwise shutdown completely: self._do_quit()
def download_update(self, newVersionData): """Download the latest version of InnomiNet from the web server newVersion=the version to download""" self.newVersion = newVersionData[0] self.trueHash = newVersionData[1] self.updateString = newVersionData[2] if System.IS_WINDOWS: #if we're not already doing the update: if not self.downloadingUpdate: self.downloadingUpdate = True #baseURL += "BitBlinderUpdate-%s-%s.exe" % (Globals.VERSION, self.newVersion) fileName = "BitBlinderInstaller-%s.exe" % (self.newVersion) url = self.baseURL + fileName #TODO: go through a circuit if the user wants to be stealthy: BitBlinder.http_download(url, None, self.request_done, self.request_failed, progressCB=self.progressCB, fileName=Globals.UPDATE_FILE_NAME+".download") GUIController.get().show_msgbox("BitBlinder found a new version (%s)!\n\nDownloading update now... (you can choose whether to restart later)" % (self.newVersion)) else: #url = self.baseURL + "python-bitblinder_%s_%s.deb" % (self.newVersion, platform.machine()) url = "%s/download/" % (ProgramState.Conf.BASE_HTTP) if ProgramState.USE_GTK: link = GTKUtils.make_html_link(url, url) else: link = url GUIController.get().show_msgbox("A new linux package is available! Changes:\n\n%s\n\nGo download and install it from:" % (self.updateString), title="Update Available", link=link)
def show_help(self, widget): GUIController.get().show_msgbox( "See our website... and visit the chatroom to let us know if you have questions!", title="Help", width=400)
def unpickle(obj, fileName): """main unpickle function""" config = configobj.ConfigObj(fileName, encoding='utf-8') #generate the config spec: for name in config.keys(): #dont load settings that no longer exist if not obj.ranges.has_key(name): continue range = obj.ranges[name] defaultVal = obj.defaults[name] loadedVal = config[name] try: if type(range) == types.TupleType and type( range[0]) != types.StringType: if type(range[0]) == types.FloatType: loadedVal = float(loadedVal) assert loadedVal <= range[1], "%s not in range %s" % ( loadedVal, range) assert loadedVal >= range[0], "%s not in range %s" % ( loadedVal, range) elif type(range[0]) == types.IntType: loadedVal = int(loadedVal) assert loadedVal <= range[1], "%s not in range %s" % ( loadedVal, range) assert loadedVal >= range[0], "%s not in range %s" % ( loadedVal, range) else: raise Exception("Weird type for range: %s" % (range)) elif type(range) == types.TupleType and type( range[0]) == types.StringType: assert loadedVal in range, "%s not in range %s" % (loadedVal, range) elif type(defaultVal) == types.BooleanType: if loadedVal.lower() in ("1", "true", "t", "y", "yes", "on"): loadedVal = True else: loadedVal = False #default to text entry for special types that need validation elif type(range) == types.StringType: if range == "folder": assert os.path.isdir( loadedVal), "%s is not a valid directory" % (loadedVal) elif range == "ip": if loadedVal: assert isIPAddress( loadedVal), "%s is not a valid ip address" % ( loadedVal) elif range in ("GB", "KBps"): loadedVal = int(loadedVal) elif range == "password": pass elif range == "scheduler": pass elif range == "anonymity level": loadedVal = int(loadedVal) assert loadedVal in ( 1, 2, 3), "anonymity value not in range (1,3)" else: regex = re.compile(range) assert regex.match( loadedVal ), "settings string (%s) does not match expression (%s)" % ( loadedVal, range) else: raise Exception("Unknown range/value combination (%s, %s)" % (range, defaultVal)) except Exception, e: log_msg("Bad option value (%s) for option %s" % (e, name), 0) GUIController.get().show_msgbox( "Bad option value (%s) for option %s" % (e, name)) setattr(obj, name, loadedVal)
def show_help(self, widget): GUIController.get().show_msgbox("See our website... and visit the chatroom to let us know if you have questions!", title="Help", width=400)
def show_tracker_shutdown_prompt(self): def callback(dialog, response): self.exitDialog = None if response == gtk.RESPONSE_OK: self.app.force_stop() self.exitDialog = GUIController.get().show_msgbox("Bitblinder is sending shutdown events to trackers. If you are using only public trackers, you can safely exit immediately.", cb=callback, buttons=("Exit Now", gtk.RESPONSE_OK))
def response(success): if success: GUIController.get().show_msgbox("The bug report was sent successfully.", title="Success!") else: if not ProgramState.DONE: GUIController.get().show_msgbox("The bug report failed. You can submit the bug manually at:", title="Too Much Fail", link=GTKUtils.make_html_link("http://innomi.net/bugs/report/1", 'http://innomi.net/bugs/report/1'))