diff --git a/README.md b/README.md index 73b5329c..7a161d04 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ pseudo-mailing list: BM-2D9QKN4teYRvoq2fyzpiftPh9WP9qggtzh -references +References ---------- -* [project website](https://bitmessage.org) -* [protocol specification](https://bitmessage.org/wiki/Protocol_specification) -* [whitepaper](https://bitmessage.org/bitmessage.pdf) -* [installation](https://bitmessage.org/wiki/Compiling_instructions) +* [Project Website](https://bitmessage.org) +* [Protocol Specification](https://bitmessage.org/wiki/Protocol_specification) +* [Whitepaper](https://bitmessage.org/bitmessage.pdf) +* [Installation](https://bitmessage.org/wiki/Compiling_instructions) diff --git a/src/addresses.py b/src/addresses.py index 5f666543..b9135d04 100644 --- a/src/addresses.py +++ b/src/addresses.py @@ -42,14 +42,12 @@ def decodeBase58(string, alphabet=ALPHABET): - `alphabet`: The alphabet to use for encoding """ base = len(alphabet) - strlen = len(string) num = 0 - + try: - power = strlen - 1 for char in string: - num += alphabet.index(char) * (base ** power) - power -= 1 + num *= base + num += alphabet.index(char) except: #character not found (like a space character or a 0) return 0 diff --git a/src/bitmessagecurses/__init__.py b/src/bitmessagecurses/__init__.py index 91c99df8..1c88d222 100644 --- a/src/bitmessagecurses/__init__.py +++ b/src/bitmessagecurses/__init__.py @@ -25,6 +25,7 @@ import shared import ConfigParser from addresses import * from pyelliptic.openssl import OpenSSL +import l10n quit = False menutab = 1 @@ -210,7 +211,7 @@ def drawtab(stdscr): stdscr.addstr(8+i, 18, str(item).ljust(2)) # Uptime and processing data - stdscr.addstr(6, 35, "Since startup on "+unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(startuptime))))) + stdscr.addstr(6, 35, "Since startup on "+l10n.formatTimestamp(startuptime, False)) stdscr.addstr(7, 40, "Processed "+str(shared.numberOfMessagesProcessed).ljust(4)+" person-to-person messages.") stdscr.addstr(8, 40, "Processed "+str(shared.numberOfBroadcastsProcessed).ljust(4)+" broadcast messages.") stdscr.addstr(9, 40, "Processed "+str(shared.numberOfPubkeysProcessed).ljust(4)+" public keys.") @@ -851,8 +852,7 @@ def loadInbox(): # Load into array inbox.append([msgid, tolabel, toaddr, fromlabel, fromaddr, subject, - strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(received))), - read]) + l10n.formatTimestamp(received, False), read]) inbox.reverse() def loadSent(): sys.stdout = sys.__stdout__ @@ -902,20 +902,20 @@ def loadSent(): elif status == "msgqueued": statstr = "Message queued" elif status == "msgsent": - t = strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime))) + t = l10n.formatTimestamp(lastactiontime, False) statstr = "Message sent at "+t+".Waiting for acknowledgement." elif status == "msgsentnoackexpected": - t = strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime))) + t = l10n.formatTimestamp(lastactiontime, False) statstr = "Message sent at "+t+"." elif status == "doingmsgpow": statstr = "The proof of work required to send the message has been queued." elif status == "askreceived": - t = strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime))) + t = l10n.formatTimestamp(lastactiontime, False) statstr = "Acknowledgment of the message received at "+t+"." elif status == "broadcastqueued": statstr = "Broadcast queued." elif status == "broadcastsent": - t = strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime))) + t = l10n.formatTimestamp(lastactiontime, False) statstr = "Broadcast sent at "+t+"." elif status == "forcepow": statstr = "Forced difficulty override. Message will start sending soon." @@ -924,12 +924,12 @@ def loadSent(): elif status == "toodifficult": statstr = "Error: The work demanded by the recipient is more difficult than you are willing to do." else: - t = strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime))) + t = l10n.formatTimestamp(lastactiontime, False) statstr = "Unknown status "+status+" at "+t+"." # Load into array sentbox.append([tolabel, toaddr, fromlabel, fromaddr, subject, statstr, ackdata, - strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(lastactiontime)))]) + l10n.formatTimestamp(lastactiontime, False)]) sentbox.reverse() def loadAddrBook(): sys.stdout = sys.__stdout__ diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index 40e63400..5a506232 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -9,6 +9,26 @@ # The software version variable is now held in shared.py + +import sys +#Version check +#Older versions of Python don't support the print function while Python 3 doesn't +#like the print statement, so we use sys.stdout for the version check. After this +#check we can then use the print function in the remainder of this file. Currently +#in order to use logging, a lot of unnecessary code needs to be executed which could +#potentially render this version check useless. So logging won't be used here until +#there is a more efficient way to configure logging +if sys.hexversion >= 0x3000000: + msg = "PyBitmessage does not support Python 3. Python 2.7.3 or later is required. Your version: %s" % sys.version + #logger.critical(msg) + sys.stdout.write(msg) + sys.exit(0) +if sys.hexversion < 0x20703F0: + msg = "You should use Python 2.7.3 or greater (but not Python 3). Your version: %s" % sys.version + #logger.critical(msg) + sys.stdout.write(msg) + sys.exit(0) + import signal # Used to capture a Ctrl-C keypress so that Bitmessage can shutdown gracefully. # The next 3 are used for the API import singleton @@ -46,15 +66,7 @@ import helper_generic from subprocess import call import time - -# OSX python version check -import sys -if 'win' in sys.platform: - if float("{1}.{2}".format(*sys.version_info)) < 7.5: - msg = "You should use python 2.7.5 or greater. Your version: %s", "{0}.{1}.{2}".format(*sys.version_info) - logger.critical(msg) - print msg - sys.exit(0) + def connectToStream(streamNumber): shared.streamsInWhichIAmParticipating[streamNumber] = 'no data' @@ -200,7 +212,7 @@ class Main: apiNotifyPath = '' if apiNotifyPath != '': with shared.printLock: - print 'Trying to call', apiNotifyPath + print('Trying to call', apiNotifyPath) call([apiNotifyPath, "startingUp"]) singleAPIThread = singleAPI() @@ -222,15 +234,15 @@ class Main: try: from PyQt4 import QtCore, QtGui except Exception as err: - print 'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\'. If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon' - print 'Error message:', err - print 'You can also run PyBitmessage with the new curses interface by providing \'-c\' as a commandline argument.' + print('PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download or by searching Google for \'PyQt Download\'. If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon') + print('Error message:', err) + print('You can also run PyBitmessage with the new curses interface by providing \'-c\' as a commandline argument.') os._exit(0) import bitmessageqt bitmessageqt.run() else: - print 'Running with curses' + print('Running with curses') import bitmessagecurses bitmessagecurses.runwrapper() else: @@ -238,16 +250,16 @@ class Main: if daemon: with shared.printLock: - print 'Running as a daemon. The main program should exit this thread.' + print('Running as a daemon. The main program should exit this thread.') else: with shared.printLock: - print 'Running as a daemon. You can use Ctrl+C to exit.' + print('Running as a daemon. You can use Ctrl+C to exit.') while True: time.sleep(20) def stop(self): with shared.printLock: - print 'Stopping Bitmessage Deamon.' + print('Stopping Bitmessage Deamon.') shared.doCleanShutdown() diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index dd67d211..e00011a9 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -1,8 +1,3 @@ -try: - import locale -except: - pass - withMessagingMenu = False try: from gi.repository import MessagingMenu @@ -40,6 +35,7 @@ from debug import logger import subprocess import datetime from helper_sql import * +import l10n try: from PyQt4 import QtCore, QtGui @@ -482,6 +478,10 @@ class MyForm(QtGui.QMainWindow): # startup for linux pass + + self.totalNumberOfBytesReceived = 0 + self.totalNumberOfBytesSent = 0 + self.ui.labelSendBroadcastWarning.setVisible(False) self.timer = QtCore.QTimer() @@ -574,7 +574,7 @@ class MyForm(QtGui.QMainWindow): self.statusbar = self.statusBar() self.statusbar.insertPermanentWidget(0, self.ui.pushButtonStatusIcon) self.ui.labelStartupTime.setText(_translate("MainWindow", "Since startup on %1").arg( - unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(int(time.time()))),'utf-8'))) + l10n.formatTimestamp())) self.numberOfMessagesProcessed = 0 self.numberOfBroadcastsProcessed = 0 self.numberOfPubkeysProcessed = 0 @@ -833,34 +833,34 @@ class MyForm(QtGui.QMainWindow): "MainWindow", "Queued.") elif status == 'msgsent': statusText = _translate("MainWindow", "Message sent. Waiting for acknowledgement. Sent at %1").arg( - unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8')) + l10n.formatTimestamp(lastactiontime)) elif status == 'msgsentnoackexpected': statusText = _translate("MainWindow", "Message sent. Sent at %1").arg( - unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8')) + l10n.formatTimestamp(lastactiontime)) elif status == 'doingmsgpow': statusText = _translate( "MainWindow", "Need to do work to send message. Work is queued.") elif status == 'ackreceived': statusText = _translate("MainWindow", "Acknowledgement of the message received %1").arg( - unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8')) + l10n.formatTimestamp(lastactiontime)) elif status == 'broadcastqueued': statusText = _translate( "MainWindow", "Broadcast queued.") elif status == 'broadcastsent': - statusText = _translate("MainWindow", "Broadcast on %1").arg(unicode(strftime( - shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8')) + statusText = _translate("MainWindow", "Broadcast on %1").arg( + l10n.formatTimestamp(lastactiontime)) elif status == 'toodifficult': statusText = _translate("MainWindow", "Problem: The work demanded by the recipient is more difficult than you are willing to do. %1").arg( - unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8')) + l10n.formatTimestamp(lastactiontime)) elif status == 'badkey': statusText = _translate("MainWindow", "Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1").arg( - unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8')) + l10n.formatTimestamp(lastactiontime)) elif status == 'forcepow': statusText = _translate( "MainWindow", "Forced difficulty override. Send should start soon.") else: - statusText = _translate("MainWindow", "Unknown status: %1 %2").arg(status).arg(unicode( - strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8')) + statusText = _translate("MainWindow", "Unknown status: %1 %2").arg(status).arg( + l10n.formatTimestamp(lastactiontime)) newItem = myTableWidgetItem(statusText) newItem.setToolTip(statusText) newItem.setData(Qt.UserRole, QByteArray(ackdata)) @@ -967,10 +967,8 @@ class MyForm(QtGui.QMainWindow): subject_item.setFont(font) self.ui.tableWidgetInbox.setItem(0, 2, subject_item) # time received - time_item = myTableWidgetItem(unicode(strftime(shared.config.get( - 'bitmessagesettings', 'timeformat'), localtime(int(received))), 'utf-8')) - time_item.setToolTip(unicode(strftime(shared.config.get( - 'bitmessagesettings', 'timeformat'), localtime(int(received))), 'utf-8')) + time_item = myTableWidgetItem(l10n.formatTimestamp(received)) + time_item.setToolTip(l10n.formatTimestamp(received)) time_item.setData(Qt.UserRole, QByteArray(msgid)) time_item.setData(33, int(received)) time_item.setFlags( @@ -1468,6 +1466,31 @@ class MyForm(QtGui.QMainWindow): self.ui.labelPubkeyCount.setText(_translate( "MainWindow", "Processed %1 public keys.").arg(str(shared.numberOfPubkeysProcessed))) + def formatBytes(self, num): + for x in ['bytes','KB','MB','GB']: + if num < 1000.0: + return "%3.0f %s" % (num, x) + num /= 1000.0 + return "%3.0f %s" % (num, 'TB') + + def formatByteRate(self, num): + num /= 1000 + return "%4.0f KB" % num + + def updateNumberOfBytes(self): + """ + This function is run every two seconds, so we divide the rate of bytes + sent and received by 2. + """ + self.ui.labelBytesRecvCount.setText(_translate( + "MainWindow", "Down: %1/s Total: %2").arg(self.formatByteRate(shared.numberOfBytesReceived/2), self.formatBytes(self.totalNumberOfBytesReceived))) + self.ui.labelBytesSentCount.setText(_translate( + "MainWindow", "Up: %1/s Total: %2").arg(self.formatByteRate(shared.numberOfBytesSent/2), self.formatBytes(self.totalNumberOfBytesSent))) + self.totalNumberOfBytesReceived += shared.numberOfBytesReceived + self.totalNumberOfBytesSent += shared.numberOfBytesSent + shared.numberOfBytesReceived = 0 + shared.numberOfBytesSent = 0 + def updateNetworkStatusTab(self): # print 'updating network status tab' totalNumberOfConnectionsFromAllStreams = 0 # One would think we could use len(sendDataQueues) for this but the number doesn't always match: just because we have a sendDataThread running doesn't mean that the connection has been fully established (with the exchange of version messages). @@ -1521,6 +1544,7 @@ class MyForm(QtGui.QMainWindow): self.ui.labelLookupsPerSecond.setText(_translate( "MainWindow", "Inventory lookups per second: %1").arg(str(shared.numberOfInventoryLookupsPerformed/2))) shared.numberOfInventoryLookupsPerformed = 0 + self.updateNumberOfBytes() # Indicates whether or not there is a connection to the Bitmessage network connected = False @@ -2032,12 +2056,9 @@ class MyForm(QtGui.QMainWindow): self.ui.tableWidgetSent.setItem(0, 2, newItem) # newItem = QtGui.QTableWidgetItem('Doing work necessary to send # broadcast...'+ - # unicode(strftime(shared.config.get('bitmessagesettings', - # 'timeformat'),localtime(int(time.time()))),'utf-8')) - newItem = myTableWidgetItem(_translate("MainWindow", "Work is queued. %1").arg(unicode(strftime(shared.config.get( - 'bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8'))) - newItem.setToolTip(_translate("MainWindow", "Work is queued. %1").arg(unicode(strftime(shared.config.get( - 'bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8'))) + # l10n.formatTimestamp()) + newItem = myTableWidgetItem(_translate("MainWindow", "Work is queued. %1").arg(l10n.formatTimestamp())) + newItem.setToolTip(_translate("MainWindow", "Work is queued. %1").arg(l10n.formatTimestamp())) newItem.setData(Qt.UserRole, QByteArray(ackdata)) newItem.setData(33, int(time.time())) self.ui.tableWidgetSent.setItem(0, 3, newItem) @@ -2104,10 +2125,8 @@ class MyForm(QtGui.QMainWindow): #newItem.setData(Qt.UserRole, unicode(message, 'utf-8)')) # No longer hold the message in the table; we'll use a SQL query to display it as needed. newItem.setFont(font) self.ui.tableWidgetInbox.setItem(0, 2, newItem) - newItem = myTableWidgetItem(unicode(strftime(shared.config.get( - 'bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')) - newItem.setToolTip(unicode(strftime(shared.config.get( - 'bitmessagesettings', 'timeformat'), localtime(int(time.time()))), 'utf-8')) + newItem = myTableWidgetItem(l10n.formatTimestamp()) + newItem.setToolTip(l10n.formatTimestamp()) newItem.setData(Qt.UserRole, QByteArray(inventoryHash)) newItem.setData(33, int(time.time())) newItem.setFont(font) @@ -3781,52 +3800,12 @@ def run(): app = QtGui.QApplication(sys.argv) translator = QtCore.QTranslator() - try: - locale_countrycode = str(locale.getdefaultlocale()[0]) - except: - # The above is not compatible with all versions of OSX. - locale_countrycode = "en_US" # Default to english. - locale_lang = locale_countrycode[0:2] - user_countrycode = str(shared.config.get('bitmessagesettings', 'userlocale')) - user_lang = user_countrycode[0:2] - try: - translation_path = os.path.join(sys._MEIPASS, "translations/bitmessage_") - except Exception, e: - translation_path = "translations/bitmessage_" - - if shared.config.get('bitmessagesettings', 'userlocale') == 'system': - # try to detect the users locale otherwise fallback to English - try: - # try the users full locale, e.g. 'en_US': - # since we usually only provide languages, not localozations - # this will usually fail - translator.load(translation_path + locale_countrycode) - except: - try: - # try the users locale language, e.g. 'en': - # since we usually only provide languages, not localozations - # this will usually succeed - translator.load(translation_path + locale_lang) - except: - # as English is already the default language, we don't - # need to do anything. No need to translate. - pass - else: - try: - # check if the user input is a valid translation file: - # since user_countrycode will be usually set by the combobox - # it will usually just be a language code - translator.load(translation_path + user_countrycode) - except: - try: - # check if the user lang is a valid translation file: - # this is only needed if the user manually set his 'userlocale' - # in the keys.dat to a countrycode (e.g. 'de_CH') - translator.load(translation_path + user_lang) - except: - # as English is already the default language, we don't - # need to do anything. No need to translate. - pass + translationpath = os.path.join( + getattr(sys, '_MEIPASS', ''), + 'translations', + 'bitmessage_' + l10n.getTranslationLanguage() + ) + translator.load(translationpath) QtGui.QApplication.installTranslator(translator) app.setStyleSheet("QStatusBar::item { border: 0px solid black }") diff --git a/src/bitmessageqt/bitmessageui.py b/src/bitmessageqt/bitmessageui.py index b80367dd..fb0056aa 100644 --- a/src/bitmessageqt/bitmessageui.py +++ b/src/bitmessageqt/bitmessageui.py @@ -2,8 +2,8 @@ # Form implementation generated from reading ui file 'bitmessageui.ui' # -# Created: Sat Nov 2 18:01:09 2013 -# by: PyQt4 UI code generator 4.10 +# Created: Fri Aug 01 15:30:14 2014 +# by: PyQt4 UI code generator 4.10.3 # # WARNING! All changes made in this file will be lost! @@ -431,15 +431,21 @@ class Ui_MainWindow(object): self.labelBroadcastCount.setGeometry(QtCore.QRect(350, 150, 351, 16)) self.labelBroadcastCount.setObjectName(_fromUtf8("labelBroadcastCount")) self.labelLookupsPerSecond = QtGui.QLabel(self.networkstatus) - self.labelLookupsPerSecond.setGeometry(QtCore.QRect(320, 210, 291, 16)) + self.labelLookupsPerSecond.setGeometry(QtCore.QRect(320, 250, 291, 16)) self.labelLookupsPerSecond.setObjectName(_fromUtf8("labelLookupsPerSecond")) + self.labelBytesRecvCount = QtGui.QLabel(self.networkstatus) + self.labelBytesRecvCount.setGeometry(QtCore.QRect(350, 210, 251, 16)) + self.labelBytesRecvCount.setObjectName(_fromUtf8("labelBytesRecvCount")) + self.labelBytesSentCount = QtGui.QLabel(self.networkstatus) + self.labelBytesSentCount.setGeometry(QtCore.QRect(350, 230, 251, 16)) + self.labelBytesSentCount.setObjectName(_fromUtf8("labelBytesSentCount")) icon9 = QtGui.QIcon() icon9.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/networkstatus.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.tabWidget.addTab(self.networkstatus, icon9, _fromUtf8("")) self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtGui.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 27)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 21)) self.menubar.setObjectName(_fromUtf8("menubar")) self.menuFile = QtGui.QMenu(self.menubar) self.menuFile.setObjectName(_fromUtf8("menuFile")) @@ -557,8 +563,8 @@ class Ui_MainWindow(object): self.textEditMessage.setHtml(_translate("MainWindow", "\n" "
\n" -"