diff --git a/src/api.py b/src/api.py index ebe295d5..21fd1bb6 100644 --- a/src/api.py +++ b/src/api.py @@ -67,6 +67,7 @@ import subprocess # nosec B404 import time from binascii import hexlify, unhexlify from struct import pack, unpack +import sqlite3 import six from six.moves import configparser, http_client, xmlrpc_server @@ -957,20 +958,32 @@ class BMRPCDispatcher(object): 23, 'Bool expected in readStatus, saw %s instead.' % type(readStatus)) queryreturn = sqlQuery( - "SELECT read FROM inbox WHERE msgid=?", msgid) + "SELECT read FROM inbox WHERE msgid=?", sqlite3.Binary(msgid)) + if len(queryreturn) < 1: + queryreturn = sqlQuery( + "SELECT read FROM inbox WHERE msgid=CAST(? AS TEXT)", msgid) # UPDATE is slow, only update if status is different try: if (queryreturn[0][0] == 1) != readStatus: - sqlExecute( + rowcount = sqlExecute( "UPDATE inbox set read = ? WHERE msgid=?", - readStatus, msgid) + readStatus, sqlite3.Binary(msgid)) + if rowcount < 1: + rowcount = sqlExecute( + "UPDATE inbox set read = ? WHERE msgid=CAST(? AS TEXT)", + readStatus, msgid) queues.UISignalQueue.put(('changedInboxUnread', None)) except IndexError: pass queryreturn = sqlQuery( "SELECT msgid, toaddress, fromaddress, subject, received, message," - " encodingtype, read FROM inbox WHERE msgid=?", msgid + " encodingtype, read FROM inbox WHERE msgid=?", sqlite3.Binary(msgid) ) + if len(queryreturn) < 1: + queryreturn = sqlQuery( + "SELECT msgid, toaddress, fromaddress, subject, received, message," + " encodingtype, read FROM inbox WHERE msgid=CAST(? AS TEXT)", msgid + ) try: return {"inboxMessage": [ self._dump_inbox_message(*queryreturn[0])]} @@ -1039,8 +1052,14 @@ class BMRPCDispatcher(object): queryreturn = sqlQuery( "SELECT msgid, toaddress, fromaddress, subject, lastactiontime," " message, encodingtype, status, ackdata FROM sent WHERE msgid=?", - msgid + sqlite3.Binary(msgid) ) + if len(queryreturn) < 1: + queryreturn = sqlQuery( + "SELECT msgid, toaddress, fromaddress, subject, lastactiontime," + " message, encodingtype, status, ackdata FROM sent WHERE msgid=CAST(? AS TEXT)", + msgid + ) try: return {"sentMessage": [ self._dump_sent_message(*queryreturn[0]) @@ -1076,8 +1095,14 @@ class BMRPCDispatcher(object): queryreturn = sqlQuery( "SELECT msgid, toaddress, fromaddress, subject, lastactiontime," " message, encodingtype, status, ackdata FROM sent" - " WHERE ackdata=?", ackData + " WHERE ackdata=?", sqlite3.Binary(ackData) ) + if len(queryreturn) < 1: + queryreturn = sqlQuery( + "SELECT msgid, toaddress, fromaddress, subject, lastactiontime," + " message, encodingtype, status, ackdata FROM sent" + " WHERE ackdata=CAST(? AS TEXT)", ackData + ) try: return {"sentMessage": [ @@ -1097,7 +1122,9 @@ class BMRPCDispatcher(object): # Trash if in inbox table helper_inbox.trash(msgid) # Trash if in sent table - sqlExecute("UPDATE sent SET folder='trash' WHERE msgid=?", msgid) + rowcount = sqlExecute("UPDATE sent SET folder='trash' WHERE msgid=?", sqlite3.Binary(msgid)) + if rowcount < 1: + sqlExecute("UPDATE sent SET folder='trash' WHERE msgid=CAST(? AS TEXT)", msgid) return 'Trashed message (assuming message existed).' @command('trashInboxMessage') @@ -1111,7 +1138,9 @@ class BMRPCDispatcher(object): def HandleTrashSentMessage(self, msgid): """Trash sent message by msgid (encoded in hex).""" msgid = self._decode(msgid, "hex") - sqlExecute('''UPDATE sent SET folder='trash' WHERE msgid=?''', msgid) + rowcount = sqlExecute('''UPDATE sent SET folder='trash' WHERE msgid=?''', sqlite3.Binary(msgid)) + if rowcount < 1: + sqlExecute('''UPDATE sent SET folder='trash' WHERE msgid=CAST(? AS TEXT)''', msgid) return 'Trashed sent message (assuming message existed).' @command('sendMessage') @@ -1221,7 +1250,10 @@ class BMRPCDispatcher(object): raise APIError(15, 'Invalid ackData object size.') ackdata = self._decode(ackdata, "hex") queryreturn = sqlQuery( - "SELECT status FROM sent where ackdata=?", ackdata) + "SELECT status FROM sent where ackdata=?", sqlite3.Binary(ackdata)) + if len(queryreturn) < 1: + queryreturn = sqlQuery( + "SELECT status FROM sent where ackdata=CAST(? AS TEXT)", ackdata) try: return queryreturn[0][0].decode("utf-8", "replace") except IndexError: @@ -1359,7 +1391,9 @@ class BMRPCDispatcher(object): """Trash a sent message by ackdata (hex encoded)""" # This API method should only be used when msgid is not available ackdata = self._decode(ackdata, "hex") - sqlExecute("UPDATE sent SET folder='trash' WHERE ackdata=?", ackdata) + rowcount = sqlExecute("UPDATE sent SET folder='trash' WHERE ackdata=?", sqlite3.Binary(ackdata)) + if rowcount < 1: + sqlExecute("UPDATE sent SET folder='trash' WHERE ackdata=CAST(? AS TEXT)", ackdata) return 'Trashed sent message (assuming message existed).' @command('disseminatePubkey') @@ -1426,19 +1460,29 @@ class BMRPCDispatcher(object): # use it we'll need to fill out a field in our inventory database # which is blank by default (first20bytesofencryptedmessage). queryreturn = sqlQuery( - "SELECT hash, payload FROM inventory WHERE tag = ''" - " and objecttype = 2") + "SELECT hash, payload FROM inventory WHERE tag = ?" + " and objecttype = 2", sqlite3.Binary(b"")) + if len(queryreturn) < 1: + queryreturn = sqlQuery( + "SELECT hash, payload FROM inventory WHERE tag = CAST(? AS TEXT)" + " and objecttype = 2", b"") with SqlBulkExecute() as sql: for hash01, payload in queryreturn: readPosition = 16 # Nonce length + time length # Stream Number length readPosition += decodeVarint( payload[readPosition:readPosition + 10])[1] - t = (payload[readPosition:readPosition + 32], hash01) - sql.execute("UPDATE inventory SET tag=? WHERE hash=?", *t) + t = (sqlite3.Binary(payload[readPosition:readPosition + 32]), sqlite3.Binary(hash01)) + _, rowcount = sql.execute("UPDATE inventory SET tag=? WHERE hash=?", *t) + if rowcount < 1: + t = (sqlite3.Binary(payload[readPosition:readPosition + 32]), hash01) + sql.execute("UPDATE inventory SET tag=? WHERE hash=CAST(? AS TEXT)", *t) queryreturn = sqlQuery( - "SELECT payload FROM inventory WHERE tag = ?", requestedHash) + "SELECT payload FROM inventory WHERE tag = ?", sqlite3.Binary(requestedHash)) + if len(queryreturn) < 1: + queryreturn = sqlQuery( + "SELECT payload FROM inventory WHERE tag = CAST(? AS TEXT)", requestedHash) return {"receivedMessageDatas": [ {'data': hexlify(payload)} for payload, in queryreturn ]} diff --git a/src/bitmessagecurses/__init__.py b/src/bitmessagecurses/__init__.py index 2fdb8412..121d6072 100644 --- a/src/bitmessagecurses/__init__.py +++ b/src/bitmessagecurses/__init__.py @@ -18,6 +18,7 @@ import time from textwrap import fill from threading import Timer import six +import sqlite3 from dialog import Dialog import helper_sent @@ -360,7 +361,9 @@ def handlech(c, stdscr): inbox[inboxcur][1] + "\"") data = "" # pyint: disable=redefined-outer-name - ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", inbox[inboxcur][0]) + ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", sqlite3.Binary(inbox[inboxcur][0])) + if len(ret) < 1: + ret = sqlQuery("SELECT message FROM inbox WHERE msgid=CAST(? AS TEXT)", inbox[inboxcur][0]) if ret != []: for row in ret: data, = row @@ -369,12 +372,16 @@ def handlech(c, stdscr): for i, item in enumerate(data.split("\n")): msg += fill(item, replace_whitespace=False) + "\n" scrollbox(d, unicode(ascii(msg)), 30, 80) - sqlExecute("UPDATE inbox SET read=1 WHERE msgid=?", inbox[inboxcur][0]) + rowcount = sqlExecute("UPDATE inbox SET read=1 WHERE msgid=?", sqlite3.Binary(inbox[inboxcur][0])) + if rowcount < 1: + sqlExecute("UPDATE inbox SET read=1 WHERE msgid=CAST(? AS TEXT)", inbox[inboxcur][0]) inbox[inboxcur][7] = 1 else: scrollbox(d, unicode("Could not fetch message.")) elif t == "2": # Mark unread - sqlExecute("UPDATE inbox SET read=0 WHERE msgid=?", inbox[inboxcur][0]) + rowcount = sqlExecute("UPDATE inbox SET read=0 WHERE msgid=?", sqlite3.Binary(inbox[inboxcur][0])) + if rowcount < 1: + sqlExecute("UPDATE inbox SET read=0 WHERE msgid=CAST(? AS TEXT)", inbox[inboxcur][0]) inbox[inboxcur][7] = 0 elif t == "3": # Reply curses.curs_set(1) @@ -398,7 +405,9 @@ def handlech(c, stdscr): if not m[5][:4] == "Re: ": subject = "Re: " + m[5] body = "" - ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", m[0]) + ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", sqlite3.Binary(m[0])) + if len(ret) < 1: + ret = sqlQuery("SELECT message FROM inbox WHERE msgid=CAST(? AS TEXT)", m[0]) if ret != []: body = "\n\n------------------------------------------------------\n" for row in ret: @@ -425,7 +434,9 @@ def handlech(c, stdscr): r, t = d.inputbox("Filename", init=inbox[inboxcur][5] + ".txt") if r == d.DIALOG_OK: msg = "" - ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", inbox[inboxcur][0]) + ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", sqlite3.Binary(inbox[inboxcur][0])) + if len(ret) < 1: + ret = sqlQuery("SELECT message FROM inbox WHERE msgid=CAST(? AS TEXT)", inbox[inboxcur][0]) if ret != []: for row in ret: msg, = row @@ -436,7 +447,9 @@ def handlech(c, stdscr): else: scrollbox(d, unicode("Could not fetch message.")) elif t == "6": # Move to trash - sqlExecute("UPDATE inbox SET folder='trash' WHERE msgid=?", inbox[inboxcur][0]) + rowcount = sqlExecute("UPDATE inbox SET folder='trash' WHERE msgid=?", sqlite3.Binary(inbox[inboxcur][0])) + if rowcount < 1: + sqlExecute("UPDATE inbox SET folder='trash' WHERE msgid=CAST(? AS TEXT)", inbox[inboxcur][0]) del inbox[inboxcur] scrollbox(d, unicode( "Message moved to trash. There is no interface to view your trash," @@ -468,7 +481,12 @@ def handlech(c, stdscr): ret = sqlQuery( "SELECT message FROM sent WHERE subject=? AND ackdata=?", dbstr(sentbox[sentcur][4]), - sentbox[sentcur][6]) + sqlite3.Binary(sentbox[sentcur][6])) + if len(ret) < 1: + ret = sqlQuery( + "SELECT message FROM sent WHERE subject=? AND ackdata=CAST(? AS TEXT)", + dbstr(sentbox[sentcur][4]), + sentbox[sentcur][6]) if ret != []: for row in ret: data, = row @@ -480,10 +498,15 @@ def handlech(c, stdscr): else: scrollbox(d, unicode("Could not fetch message.")) elif t == "2": # Move to trash - sqlExecute( + rowcount = sqlExecute( "UPDATE sent SET folder='trash' WHERE subject=? AND ackdata=?", dbstr(sentbox[sentcur][4]), - sentbox[sentcur][6]) + sqlite3.Binary(sentbox[sentcur][6])) + if rowcount < 1: + rowcount = sqlExecute( + "UPDATE sent SET folder='trash' WHERE subject=? AND ackdata=CAST(? AS TEXT)", + dbstr(sentbox[sentcur][4]), + sentbox[sentcur][6]) del sentbox[sentcur] scrollbox(d, unicode( "Message moved to trash. There is no interface to view your trash" diff --git a/src/bitmessagekivy/baseclass/maildetail.py b/src/bitmessagekivy/baseclass/maildetail.py index 5168a522..a0715aaf 100644 --- a/src/bitmessagekivy/baseclass/maildetail.py +++ b/src/bitmessagekivy/baseclass/maildetail.py @@ -7,6 +7,7 @@ Maildetail screen for inbox, sent, draft and trash. import os from datetime import datetime +import sqlite3 from kivy.core.clipboard import Clipboard from kivy.clock import Clock @@ -111,7 +112,11 @@ class MailDetail(Screen): # pylint: disable=too-many-instance-attributes elif self.kivy_state.detail_page_type == 'inbox': data = sqlQuery( "select toaddress, fromaddress, subject, message, received from inbox" - " where msgid = ?", self.kivy_state.mail_id) + " where msgid = ?", sqlite3.Binary(self.kivy_state.mail_id)) + if len(data) < 1: + data = sqlQuery( + "select toaddress, fromaddress, subject, message, received from inbox" + " where msgid = CAST(? AS TEXT)", self.kivy_state.mail_id) self.assign_mail_details(data) App.get_running_app().set_mail_detail_header() except Exception as e: # pylint: disable=unused-variable diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index bf82525c..999a1eea 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -15,12 +15,11 @@ import threading import time from datetime import datetime, timedelta from sqlite3 import register_adapter +import sqlite3 import six from six.moves import range as xrange if six.PY3: from codecs import escape_decode -if six.PY2: - import sqlite3 from unqstr import ustr, unic from dbcompat import dbstr @@ -2687,14 +2686,19 @@ class MyForm(settingsmixin.SMainWindow): msgids = [] for i in range(0, idCount): - msgids.append(tableWidget.item(i, 3).data()) + msgids.append(sqlite3.Binary(tableWidget.item(i, 3).data())) for col in xrange(tableWidget.columnCount()): tableWidget.item(i, col).setUnread(False) markread = sqlExecuteChunked( "UPDATE inbox SET read = 1 WHERE msgid IN({0}) AND read=0", - idCount, *msgids + False, idCount, *msgids ) + if markread < 1: + markread = sqlExecuteChunked( + "UPDATE inbox SET read = 1 WHERE msgid IN({0}) AND read=0", + True, idCount, *msgids + ) if markread > 0: self.propagateUnreadCount() @@ -2928,15 +2932,10 @@ class MyForm(settingsmixin.SMainWindow): if not msgid: return queryreturn = sqlQuery( - 'SELECT message FROM inbox WHERE msgid=?', msgid) - # for compatibility + 'SELECT message FROM inbox WHERE msgid=?', sqlite3.Binary(msgid)) if len(queryreturn) < 1: - if six.PY3: - queryreturn = sqlQuery( - 'SELECT message FROM inbox WHERE msgid=CAST(? AS TEXT)', msgid) - else: # assume six.PY2 - queryreturn = sqlQuery( - 'SELECT message FROM inbox WHERE msgid=?', sqlite3.Binary(msgid)) + queryreturn = sqlQuery( + 'SELECT message FROM inbox WHERE msgid=CAST(? AS TEXT)', msgid) try: lines_raw = queryreturn[-1][0].split('\n') lines = [] @@ -2976,7 +2975,7 @@ class MyForm(settingsmixin.SMainWindow): # modified = 0 for row in tableWidget.selectedIndexes(): currentRow = row.row() - msgid = tableWidget.item(currentRow, 3).data() + msgid = sqlite3.Binary(tableWidget.item(currentRow, 3).data()) msgids.add(msgid) # if not tableWidget.item(currentRow, 0).unread: # modified += 1 @@ -2985,10 +2984,15 @@ class MyForm(settingsmixin.SMainWindow): # for 1081 idCount = len(msgids) # rowcount = - sqlExecuteChunked( + total_row_count = sqlExecuteChunked( '''UPDATE inbox SET read=0 WHERE msgid IN ({0}) AND read=1''', - idCount, *msgids + False, idCount, *msgids ) + if total_row_count < 1: + sqlExecuteChunked( + '''UPDATE inbox SET read=0 WHERE msgid IN ({0}) AND read=1''', + True, idCount, *msgids + ) self.propagateUnreadCount() @@ -3064,8 +3068,12 @@ class MyForm(settingsmixin.SMainWindow): currentInboxRow, column_from).address msgid = tableWidget.item(currentInboxRow, 3).data() queryreturn = sqlQuery( - "SELECT message FROM inbox WHERE msgid=?", msgid - ) or sqlQuery("SELECT message FROM sent WHERE ackdata=?", msgid) + "SELECT message FROM inbox WHERE msgid=?", sqlite3.Binary(msgid) + ) or sqlQuery("SELECT message FROM sent WHERE ackdata=?", sqlite3.Binary(msgid)) + if len(queryreturn) < 1: + queryreturn = sqlQuery( + "SELECT message FROM inbox WHERE msgid=CAST(? AS TEXT)", msgid + ) or sqlQuery("SELECT message FROM sent WHERE ackdata=CAST(? AS TEXT)", msgid) if queryreturn != []: for row in queryreturn: messageAtCurrentInboxRow, = row @@ -3245,16 +3253,21 @@ class MyForm(settingsmixin.SMainWindow): )[::-1]: for i in range(r.bottomRow() - r.topRow() + 1): inventoryHashesToTrash.add( - tableWidget.item(r.topRow() + i, 3).data()) + sqlite3.Binary(tableWidget.item(r.topRow() + i, 3).data())) currentRow = r.topRow() self.getCurrentMessageTextedit().setText("") tableWidget.model().removeRows( r.topRow(), r.bottomRow() - r.topRow() + 1) idCount = len(inventoryHashesToTrash) - sqlExecuteChunked( + total_row_count = sqlExecuteChunked( ("DELETE FROM inbox" if folder == "trash" or shifted else - "UPDATE inbox SET folder='trash', read=1") - + " WHERE msgid IN ({0})", idCount, *inventoryHashesToTrash) + "UPDATE inbox SET folder='trash', read=1") + + " WHERE msgid IN ({0})", False, idCount, *inventoryHashesToTrash) + if total_row_count < 1: + sqlExecuteChunked( + ("DELETE FROM inbox" if folder == "trash" or shifted else + "UPDATE inbox SET folder='trash', read=1") + + " WHERE msgid IN ({0})", True, idCount, *inventoryHashesToTrash) tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1) tableWidget.setUpdatesEnabled(True) self.propagateUnreadCount(folder) @@ -3273,16 +3286,20 @@ class MyForm(settingsmixin.SMainWindow): )[::-1]: for i in range(r.bottomRow() - r.topRow() + 1): inventoryHashesToTrash.add( - tableWidget.item(r.topRow() + i, 3).data()) + sqlite3.Binary(tableWidget.item(r.topRow() + i, 3).data())) currentRow = r.topRow() self.getCurrentMessageTextedit().setText("") tableWidget.model().removeRows( r.topRow(), r.bottomRow() - r.topRow() + 1) tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1) idCount = len(inventoryHashesToTrash) - sqlExecuteChunked( + total_row_count = sqlExecuteChunked( "UPDATE inbox SET folder='inbox' WHERE msgid IN({0})", - idCount, *inventoryHashesToTrash) + False, idCount, *inventoryHashesToTrash) + if total_row_count < 1: + sqlExecuteChunked( + "UPDATE inbox SET folder='inbox' WHERE msgid IN({0})", + True, idCount, *inventoryHashesToTrash) tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1) tableWidget.setUpdatesEnabled(True) self.propagateUnreadCount() @@ -3302,7 +3319,10 @@ class MyForm(settingsmixin.SMainWindow): # Retrieve the message data out of the SQL database msgid = tableWidget.item(currentInboxRow, 3).data() queryreturn = sqlQuery( - 'SELECT message FROM inbox WHERE msgid=?', msgid) + 'SELECT message FROM inbox WHERE msgid=?', sqlite3.Binary(msgid)) + if len(queryreturn) < 1: + queryreturn = sqlQuery( + 'SELECT message FROM inbox WHERE msgid=CAST(? AS TEXT)', msgid) if queryreturn != []: for row in queryreturn: message, = row @@ -3335,11 +3355,17 @@ class MyForm(settingsmixin.SMainWindow): while tableWidget.selectedIndexes() != []: currentRow = tableWidget.selectedIndexes()[0].row() ackdataToTrash = tableWidget.item(currentRow, 3).data() - sqlExecute( + rowcount = sqlExecute( "DELETE FROM sent" if folder == "trash" or shifted else "UPDATE sent SET folder='trash'" - " WHERE ackdata = ?", ackdataToTrash + " WHERE ackdata = ?", sqlite3.Binary(ackdataToTrash) ) + if rowcount < 1: + sqlExecute( + "DELETE FROM sent" if folder == "trash" or shifted else + "UPDATE sent SET folder='trash'" + " WHERE ackdata = CAST(? AS TEXT)", ackdataToTrash + ) self.getCurrentMessageTextedit().setPlainText("") tableWidget.removeRow(currentRow) self.updateStatusBar(_translate( @@ -3353,9 +3379,13 @@ class MyForm(settingsmixin.SMainWindow): addressAtCurrentRow = self.ui.tableWidgetInbox.item( currentRow, 0).data(QtCore.Qt.UserRole) toRipe = decodeAddress(addressAtCurrentRow)[3] - sqlExecute( + rowcount = sqlExecute( '''UPDATE sent SET status='forcepow' WHERE toripe=? AND status='toodifficult' and folder='sent' ''', - toRipe) + sqlite3.Binary(toRipe)) + if rowcount < 1: + sqlExecute( + '''UPDATE sent SET status='forcepow' WHERE toripe=CAST(? AS TEXT) AND status='toodifficult' and folder='sent' ''', + toRipe) queryreturn = sqlQuery('''select ackdata FROM sent WHERE status='forcepow' ''') for row in queryreturn: ackdata, = row @@ -4057,7 +4087,9 @@ class MyForm(settingsmixin.SMainWindow): # menu option (Force Send) if it is. if currentRow >= 0: ackData = self.ui.tableWidgetInbox.item(currentRow, 3).data() - queryreturn = sqlQuery('''SELECT status FROM sent where ackdata=?''', ackData) + queryreturn = sqlQuery('''SELECT status FROM sent where ackdata=?''', sqlite3.Binary(ackData)) + if len(queryreturn) < 1: + queryreturn = sqlQuery('''SELECT status FROM sent where ackdata=CAST(? AS TEXT)''', ackData) for row in queryreturn: status, = row status = status.decode("utf-8", "replace") @@ -4162,24 +4194,15 @@ class MyForm(settingsmixin.SMainWindow): 'SELECT message FROM %s WHERE %s=?' % ( ('sent', 'ackdata') if folder == 'sent' else ('inbox', 'msgid') - ), msgid + ), sqlite3.Binary(msgid) ) - # for compatibility if len(queryreturn) < 1: - if six.PY3: - queryreturn = sqlQuery( - 'SELECT message FROM %s WHERE %s=CAST(? AS TEXT)' % ( - ('sent', 'ackdata') if folder == 'sent' - else ('inbox', 'msgid') - ), msgid - ) - else: # assume six.PY2 - queryreturn = sqlQuery( - 'SELECT message FROM %s WHERE %s=?' % ( - ('sent', 'ackdata') if folder == 'sent' - else ('inbox', 'msgid') - ), sqlite3.Binary(msgid) - ) + queryreturn = sqlQuery( + 'SELECT message FROM %s WHERE %s=CAST(? AS TEXT)' % ( + ('sent', 'ackdata') if folder == 'sent' + else ('inbox', 'msgid') + ), msgid + ) try: message = queryreturn[-1][0].decode("utf-8", "replace") @@ -4199,10 +4222,16 @@ class MyForm(settingsmixin.SMainWindow): if tableWidget.item(currentRow, 0).unread is True: self.updateUnreadStatus(tableWidget, currentRow, msgid) # propagate - if folder != 'sent' and sqlExecute( + rowcount = sqlExecute( 'UPDATE inbox SET read=1 WHERE msgid=? AND read=0', - msgid - ) > 0: + sqlite3.Binary(msgid) + ) + if rowcount < 1: + rowcount = sqlExecute( + 'UPDATE inbox SET read=1 WHERE msgid=CAST(? AS TEXT) AND read=0', + msgid + ) + if folder != 'sent' and rowcount > 0: self.propagateUnreadCount() messageTextedit.setCurrentFont(QtGui.QFont()) diff --git a/src/bitmessageqt/account.py b/src/bitmessageqt/account.py index 739ccfde..493f8a8e 100644 --- a/src/bitmessageqt/account.py +++ b/src/bitmessageqt/account.py @@ -7,6 +7,7 @@ import inspect import re import sys import time +import sqlite3 from unqstr import ustr, unic from dbcompat import dbstr @@ -192,13 +193,13 @@ class GatewayAccount(BMAccount): ackdata = genAckPayload(streamNumber, stealthLevel) sqlExecute( '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', - '', + sqlite3.Binary(b''), dbstr(self.toAddress), - ripe, + sqlite3.Binary(ripe), dbstr(self.fromAddress), dbstr(self.subject), dbstr(self.message), - ackdata, + sqlite3.Binary(ackdata), int(time.time()), # sentTime (this will never change) int(time.time()), # lastActionTime 0, # sleepTill time. This will get set when the POW gets done. diff --git a/src/class_objectProcessor.py b/src/class_objectProcessor.py index e92bf873..4870d256 100644 --- a/src/class_objectProcessor.py +++ b/src/class_objectProcessor.py @@ -12,6 +12,7 @@ import subprocess # nosec B404 import threading import time from binascii import hexlify +import sqlite3 import helper_bitcoin import helper_inbox @@ -122,7 +123,7 @@ class objectProcessor(threading.Thread): objectType, data = queues.objectProcessorQueue.get() sql.execute( 'INSERT INTO objectprocessorqueue VALUES (?,?)', - objectType, data) + objectType, sqlite3.Binary(data)) numberOfObjectsThatWereInTheObjectProcessorQueue += 1 logger.debug( 'Saved %s objects from the objectProcessorQueue to' @@ -145,12 +146,16 @@ class objectProcessor(threading.Thread): if data_bytes in state.ackdataForWhichImWatching: logger.info('This object is an acknowledgement bound for me.') del state.ackdataForWhichImWatching[data_bytes] - sqlExecute( + rowcount = sqlExecute( "UPDATE sent SET status='ackreceived', lastactiontime=?" - " WHERE ackdata=?", int(time.time()), data[readPosition:]) + " WHERE ackdata=?", int(time.time()), sqlite3.Binary(data_bytes)) + if rowcount < 1: + rowcount = sqlExecute( + "UPDATE sent SET status='ackreceived', lastactiontime=?" + " WHERE ackdata=CAST(? AS TEXT)", int(time.time()), data_bytes) queues.UISignalQueue.put(( 'updateSentItemStatusByAckdata', ( - data[readPosition:], _translate( + data_bytes, _translate( "MainWindow", "Acknowledgement of the message received {0}" ).format(l10n.formatTimestamp())) @@ -336,13 +341,13 @@ class objectProcessor(threading.Thread): if queryreturn != []: logger.info( 'We HAVE used this pubkey personally. Updating time.') - t = (dbstr(address), addressVersion, dataToStore, + t = (dbstr(address), addressVersion, sqlite3.Binary(dataToStore), int(time.time()), 'yes') else: logger.info( 'We have NOT used this pubkey personally. Inserting' ' in database.') - t = (dbstr(address), addressVersion, dataToStore, + t = (dbstr(address), addressVersion, sqlite3.Binary(dataToStore), int(time.time()), 'no') sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t) self.possibleNewPubkey(address) @@ -398,13 +403,13 @@ class objectProcessor(threading.Thread): if queryreturn != []: logger.info( 'We HAVE used this pubkey personally. Updating time.') - t = (dbstr(address), addressVersion, dataToStore, + t = (dbstr(address), addressVersion, sqlite3.Binary(dataToStore), int(time.time()), dbstr('yes')) else: logger.info( 'We have NOT used this pubkey personally. Inserting' ' in database.') - t = (dbstr(address), addressVersion, dataToStore, + t = (dbstr(address), addressVersion, sqlite3.Binary(dataToStore), int(time.time()), dbstr('no')) sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t) self.possibleNewPubkey(address) @@ -596,7 +601,7 @@ class objectProcessor(threading.Thread): '''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', dbstr(fromAddress), sendersAddressVersionNumber, - decryptedData[:endOfThePublicKeyPosition], + sqlite3.Binary(decryptedData[:endOfThePublicKeyPosition]), int(time.time()), dbstr('yes')) @@ -934,7 +939,7 @@ class objectProcessor(threading.Thread): sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', dbstr(fromAddress), dbstr(sendersAddressVersion), - decryptedData[:endOfPubkeyPosition], + sqlite3.Binary(decryptedData[:endOfPubkeyPosition]), int(time.time()), dbstr('yes')) diff --git a/src/class_singleCleaner.py b/src/class_singleCleaner.py index 83cb48b1..0c6ec021 100644 --- a/src/class_singleCleaner.py +++ b/src/class_singleCleaner.py @@ -22,6 +22,7 @@ It resends messages when there has been no response: import gc import os import time +import sqlite3 import queues import state @@ -180,9 +181,13 @@ class singleCleaner(StoppableThread): 'It has been a long time and we haven\'t heard an acknowledgement' ' to our msg. Sending again.' ) - sqlExecute( + rowcount = sqlExecute( "UPDATE sent SET status = 'msgqueued'" - " WHERE ackdata = ? AND folder = 'sent'", ackdata) + " WHERE ackdata = ? AND folder = 'sent'", sqlite3.Binary(ackdata)) + if rowcount < 1: + sqlExecute( + "UPDATE sent SET status = 'msgqueued'" + " WHERE ackdata = CAST(? AS TEXT) AND folder = 'sent'", ackdata) queues.workerQueue.put(('sendmessage', '')) queues.UISignalQueue.put(( 'updateStatusBar', diff --git a/src/class_singleWorker.py b/src/class_singleWorker.py index 0e906c78..f3158870 100644 --- a/src/class_singleWorker.py +++ b/src/class_singleWorker.py @@ -11,6 +11,7 @@ import time from binascii import hexlify, unhexlify from struct import pack from subprocess import call # nosec +import sqlite3 import defaults import helper_inbox @@ -111,10 +112,15 @@ class singleWorker(StoppableThread): # attach legacy header, always constant (msg/1/1) newack = b'\x00\x00\x00\x02\x01\x01' + oldack state.ackdataForWhichImWatching[bytes(newack)] = 0 - sqlExecute( + rowcount = sqlExecute( '''UPDATE sent SET ackdata=? WHERE ackdata=? AND folder = 'sent' ''', - newack, oldack + sqlite3.Binary(newack), sqlite3.Binary(oldack) ) + if rowcount < 1: + sqlExecute( + '''UPDATE sent SET ackdata=? WHERE ackdata=CAST(? AS TEXT) AND folder = 'sent' ''', + sqlite3.Binary(newack), oldack + ) del state.ackdataForWhichImWatching[oldack] # For the case if user deleted knownnodes @@ -596,11 +602,18 @@ class singleWorker(StoppableThread): )) continue - if not sqlExecute( + rowcount = sqlExecute( '''UPDATE sent SET status='doingbroadcastpow' ''' ''' WHERE ackdata=? AND status='broadcastqueued' ''' ''' AND folder='sent' ''', - ackdata): + sqlite3.Binary(ackdata)) + if rowcount < 1: + rowcount = sqlExecute( + '''UPDATE sent SET status='doingbroadcastpow' ''' + ''' WHERE ackdata=CAST(? AS TEXT) AND status='broadcastqueued' ''' + ''' AND folder='sent' ''', + ackdata) + if rowcount < 1: continue # At this time these pubkeys are 65 bytes long @@ -718,11 +731,17 @@ class singleWorker(StoppableThread): # Update the status of the message in the 'sent' table to have # a 'broadcastsent' status - sqlExecute( + rowcount = sqlExecute( '''UPDATE sent SET msgid=?, status=?, lastactiontime=? ''' ''' WHERE ackdata=? AND folder='sent' ''', - inventoryHash, dbstr('broadcastsent'), int(time.time()), ackdata + sqlite3.Binary(inventoryHash), dbstr('broadcastsent'), int(time.time()), sqlite3.Binary(ackdata) ) + if rowcount < 1: + sqlExecute( + '''UPDATE sent SET msgid=?, status=?, lastactiontime=? ''' + ''' WHERE ackdata=CAST(? AS TEXT) AND folder='sent' ''', + sqlite3.Binary(inventoryHash), 'broadcastsent', int(time.time()), ackdata + ) def sendMsg(self): """ @@ -1072,10 +1091,15 @@ class singleWorker(StoppableThread): if cond1 or cond2: # The demanded difficulty is more than # we are willing to do. - sqlExecute( + rowcount = sqlExecute( '''UPDATE sent SET status='toodifficult' ''' ''' WHERE ackdata=? AND folder='sent' ''', - ackdata) + sqlite3.Binary(ackdata)) + if rowcount < 1: + sqlExecute( + '''UPDATE sent SET status='toodifficult' ''' + ''' WHERE ackdata=CAST(? AS TEXT) AND folder='sent' ''', + ackdata) queues.UISignalQueue.put(( 'updateSentItemStatusByAckdata', ( ackdata, _translate( @@ -1235,10 +1259,15 @@ class singleWorker(StoppableThread): ) except: # noqa:E722 self.logger.warning("highlevelcrypto.encrypt didn't work") - sqlExecute( + rowcount = sqlExecute( '''UPDATE sent SET status='badkey' WHERE ackdata=? AND folder='sent' ''', - ackdata + sqlite3.Binary(ackdata) ) + if rowcount < 1: + sqlExecute( + '''UPDATE sent SET status='badkey' WHERE ackdata=CAST(? AS TEXT) AND folder='sent' ''', + ackdata + ) queues.UISignalQueue.put(( 'updateSentItemStatusByAckdata', ( ackdata, _translate( @@ -1338,12 +1367,19 @@ class singleWorker(StoppableThread): newStatus = 'msgsent' # wait 10% past expiration sleepTill = int(time.time() + TTL * 1.1) - sqlExecute( + rowcount = sqlExecute( '''UPDATE sent SET msgid=?, status=?, retrynumber=?, ''' ''' sleeptill=?, lastactiontime=? WHERE ackdata=? AND folder='sent' ''', - inventoryHash, dbstr(newStatus), retryNumber + 1, - sleepTill, int(time.time()), ackdata + sqlite3.Binary(inventoryHash), dbstr(newStatus), retryNumber + 1, + sleepTill, int(time.time()), sqlite3.Binary(ackdata) ) + if rowcount < 1: + sqlExecute( + '''UPDATE sent SET msgid=?, status=?, retrynumber=?, ''' + ''' sleeptill=?, lastactiontime=? WHERE ackdata=CAST(? AS TEXT) AND folder='sent' ''', + sqlite3.Binary(inventoryHash), newStatus, retryNumber + 1, + sleepTill, int(time.time()), ackdata + ) # If we are sending to ourselves or a chan, let's put # the message in our own inbox. diff --git a/src/class_smtpServer.py b/src/class_smtpServer.py index f753bd4e..40d1ed4a 100644 --- a/src/class_smtpServer.py +++ b/src/class_smtpServer.py @@ -12,6 +12,7 @@ import threading import time from email.header import decode_header from email.parser import Parser +import sqlite3 import queues from addresses import decodeAddress @@ -89,13 +90,13 @@ class smtpServerPyBitmessage(smtpd.SMTPServer): ackdata = genAckPayload(streamNumber, stealthLevel) sqlExecute( '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', - '', + sqlite3.Binary(b''), dbstr(toAddress), - ripe, + sqlite3.Binary(ripe), dbstr(fromAddress), dbstr(subject), dbstr(message), - ackdata, + sqlite3.Binary(ackdata), int(time.time()), # sentTime (this will never change) int(time.time()), # lastActionTime 0, # sleepTill time. This will get set when the POW gets done. diff --git a/src/class_sqlThread.py b/src/class_sqlThread.py index 846b3705..9b5e3a04 100644 --- a/src/class_sqlThread.py +++ b/src/class_sqlThread.py @@ -74,7 +74,7 @@ class sqlThread(threading.Thread): '''INSERT INTO subscriptions VALUES''' '''('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''') self.cur.execute( - '''CREATE TABLE settings (key blob, value blob, UNIQUE(key) ON CONFLICT REPLACE)''') + '''CREATE TABLE settings (key text, value blob, UNIQUE(key) ON CONFLICT REPLACE)''') self.cur.execute('''INSERT INTO settings VALUES('version','11')''') self.cur.execute('''INSERT INTO settings VALUES('lastvacuumtime',?)''', ( int(time.time()),)) diff --git a/src/helper_inbox.py b/src/helper_inbox.py index 1e490680..b981fd2b 100644 --- a/src/helper_inbox.py +++ b/src/helper_inbox.py @@ -1,5 +1,7 @@ """Helper Inbox performs inbox messages related operations""" +import sqlite3 + import queues from helper_sql import sqlExecute, sqlQuery from dbcompat import dbstr @@ -7,7 +9,7 @@ from dbcompat import dbstr def insert(t): """Perform an insert into the "inbox" table""" - u = [t[0], dbstr(t[1]), dbstr(t[2]), dbstr(t[3]), dbstr(t[4]), dbstr(t[5]), dbstr(t[6]), t[7], t[8], t[9]] + u = [sqlite3.Binary(t[0]), dbstr(t[1]), dbstr(t[2]), dbstr(t[3]), dbstr(t[4]), dbstr(t[5]), dbstr(t[6]), t[7], t[8], sqlite3.Binary(t[9])] sqlExecute('''INSERT INTO inbox VALUES (?,?,?,?,?,?,?,?,?,?)''', *u) # shouldn't emit changedInboxUnread and displayNewInboxMessage # at the same time @@ -16,22 +18,31 @@ def insert(t): def trash(msgid): """Mark a message in the `inbox` as `trash`""" - sqlExecute('''UPDATE inbox SET folder='trash' WHERE msgid=?''', msgid) + rowcount = sqlExecute('''UPDATE inbox SET folder='trash' WHERE msgid=?''', sqlite3.Binary(msgid)) + if rowcount < 1: + sqlExecute('''UPDATE inbox SET folder='trash' WHERE msgid=CAST(? AS TEXT)''', msgid) queues.UISignalQueue.put(('removeInboxRowByMsgid', msgid)) def delete(ack_data): """Permanent delete message from trash""" - sqlExecute("DELETE FROM inbox WHERE msgid = ?", ack_data) + rowcount = sqlExecute("DELETE FROM inbox WHERE msgid = ?", sqlite3.Binary(ack_data)) + if rowcount < 1: + sqlExecute("DELETE FROM inbox WHERE msgid = CAST(? AS TEXT)", ack_data) def undeleteMessage(msgid): """Undelte the message""" - sqlExecute('''UPDATE inbox SET folder='inbox' WHERE msgid=?''', msgid) + rowcount = sqlExecute('''UPDATE inbox SET folder='inbox' WHERE msgid=?''', sqlite3.Binary(msgid)) + if rowcount < 1: + sqlExecute('''UPDATE inbox SET folder='inbox' WHERE msgid=CAST(? AS TEXT)''', msgid) def isMessageAlreadyInInbox(sigHash): """Check for previous instances of this message""" queryReturn = sqlQuery( - '''SELECT COUNT(*) FROM inbox WHERE sighash=?''', sigHash) + '''SELECT COUNT(*) FROM inbox WHERE sighash=?''', sqlite3.Binary(sigHash)) + if len(queryReturn) < 1: + queryReturn = sqlQuery( + '''SELECT COUNT(*) FROM inbox WHERE sighash=CAST(? AS TEXT)''', sigHash) return queryReturn[0][0] != 0 diff --git a/src/helper_sent.py b/src/helper_sent.py index 2f24a619..14138d00 100644 --- a/src/helper_sent.py +++ b/src/helper_sent.py @@ -4,6 +4,7 @@ Insert values into sent table import time import uuid +import sqlite3 from addresses import decodeAddress from bmconfigparser import config from helper_ackPayload import genAckPayload @@ -39,7 +40,7 @@ def insert(msgid=None, toAddress='[Broadcast subscribers]', fromAddress=None, su ttl = ttl if ttl else config.getint('bitmessagesettings', 'ttl') - t = (msgid, dbstr(toAddress), ripe, dbstr(fromAddress), dbstr(subject), dbstr(message), ackdata, + t = (sqlite3.Binary(msgid), dbstr(toAddress), sqlite3.Binary(ripe), dbstr(fromAddress), dbstr(subject), dbstr(message), sqlite3.Binary(ackdata), sentTime, lastActionTime, sleeptill, dbstr(status), retryNumber, dbstr(folder), encoding, ttl) @@ -51,20 +52,30 @@ def insert(msgid=None, toAddress='[Broadcast subscribers]', fromAddress=None, su def delete(ack_data): """Perform Delete query""" - sqlExecute("DELETE FROM sent WHERE ackdata = ?", ack_data) + rowcount = sqlExecute("DELETE FROM sent WHERE ackdata = ?", sqlite3.Binary(ack_data)) + if rowcount < 1: + sqlExecute("DELETE FROM sent WHERE ackdata = CAST(? AS TEXT)", ack_data) def retrieve_message_details(ack_data): """Retrieving Message details""" data = sqlQuery( - "select toaddress, fromaddress, subject, message, received from inbox where msgid = ?", ack_data + "select toaddress, fromaddress, subject, message, received from inbox where msgid = ?", sqlite3.Binary(ack_data) ) + if len(data) < 1: + data = sqlQuery( + "select toaddress, fromaddress, subject, message, received from inbox where msgid = CAST(? AS TEXT)", ack_data + ) return data def trash(ackdata): """Mark a message in the `sent` as `trash`""" rowcount = sqlExecute( - '''UPDATE sent SET folder='trash' WHERE ackdata=?''', ackdata + '''UPDATE sent SET folder='trash' WHERE ackdata=?''', sqlite3.Binary(ackdata) ) + if rowcount < 1: + rowcount = sqlExecute( + '''UPDATE sent SET folder='trash' WHERE ackdata=CAST(? AS TEXT)''', ackdata + ) return rowcount diff --git a/src/helper_sql.py b/src/helper_sql.py index 8dee9e0c..cfacfde9 100644 --- a/src/helper_sql.py +++ b/src/helper_sql.py @@ -61,7 +61,7 @@ def sqlQuery(sql_statement, *args): return queryreturn -def sqlExecuteChunked(sql_statement, idCount, *args): +def sqlExecuteChunked(sql_statement, as_text, idCount, *args): """Execute chunked SQL statement to avoid argument limit""" # SQLITE_MAX_VARIABLE_NUMBER, # unfortunately getting/setting isn't exposed to python @@ -80,9 +80,14 @@ def sqlExecuteChunked(sql_statement, idCount, *args): chunk_slice = args[ i:i + sqlExecuteChunked.chunkSize - (len(args) - idCount) ] - sqlSubmitQueue.put( - sql_statement.format(','.join('?' * len(chunk_slice))) - ) + if as_text: + sqlSubmitQueue.put( + sql_statement.format(','.join('CAST(? AS TEXT)' * len(chunk_slice))) + ) + else: + sqlSubmitQueue.put( + sql_statement.format(','.join('?' * len(chunk_slice))) + ) # first static args, and then iterative chunk sqlSubmitQueue.put( args[0:len(args) - idCount] + chunk_slice diff --git a/src/network/bmobject.py b/src/network/bmobject.py index 35798bb9..67652001 100644 --- a/src/network/bmobject.py +++ b/src/network/bmobject.py @@ -7,7 +7,7 @@ import time import protocol import state import network.connectionpool # use long name to address recursive import -import dandelion +from network import dandelion from highlevelcrypto import calculateInventoryHash logger = logging.getLogger('default') diff --git a/src/network/bmproto.py b/src/network/bmproto.py index 8e3841a4..b3e3fe3c 100644 --- a/src/network/bmproto.py +++ b/src/network/bmproto.py @@ -17,7 +17,7 @@ from network import knownnodes import protocol import state import network.connectionpool # use long name to address recursive import -import dandelion +from network import dandelion from bmconfigparser import config from queues import invQueue, objectProcessorQueue, portCheckerQueue from randomtrackingdict import RandomTrackingDict diff --git a/src/network/dandelion.py b/src/network/dandelion.py index 0736a80a..d78cab39 100644 --- a/src/network/dandelion.py +++ b/src/network/dandelion.py @@ -8,7 +8,7 @@ from threading import RLock from time import time import six -from network import connectionpool +import network.connectionpool # use long name to address recursive import import state from queues import invQueue @@ -185,11 +185,11 @@ class Dandelion: # pylint: disable=old-style-class try: # random two connections self.stem = sample( - sorted(connectionpool.BMConnectionPool( + sorted(network.connectionpool.BMConnectionPool( ).outboundConnections.values()), MAX_STEMS) # not enough stems available except ValueError: - self.stem = connectionpool.BMConnectionPool( + self.stem = network.connectionpool.BMConnectionPool( ).outboundConnections.values() self.nodeMap = {} # hashMap stays to cater for pending stems diff --git a/src/network/downloadthread.py b/src/network/downloadthread.py index 34c4b5c3..0962ee14 100644 --- a/src/network/downloadthread.py +++ b/src/network/downloadthread.py @@ -10,7 +10,7 @@ import protocol from network import connectionpool from .objectracker import missingObjects from .threads import StoppableThread -import dandelion +from network import dandelion class DownloadThread(StoppableThread): diff --git a/src/network/invthread.py b/src/network/invthread.py index 8bc1f837..9705b79a 100644 --- a/src/network/invthread.py +++ b/src/network/invthread.py @@ -9,7 +9,7 @@ import addresses import protocol import state from network import connectionpool -import dandelion +from network import dandelion from queues import invQueue from .threads import StoppableThread diff --git a/src/network/objectracker.py b/src/network/objectracker.py index eccbaee3..be2b4219 100644 --- a/src/network/objectracker.py +++ b/src/network/objectracker.py @@ -6,7 +6,7 @@ from threading import RLock import six import network.connectionpool # use long name to address recursive import -import dandelion +from network import dandelion from randomtrackingdict import RandomTrackingDict haveBloom = False diff --git a/src/network/tcp.py b/src/network/tcp.py index 3b27c0f9..3dbc15d2 100644 --- a/src/network/tcp.py +++ b/src/network/tcp.py @@ -17,7 +17,7 @@ import l10n import protocol import state import network.connectionpool # use long name to address recursive import -import dandelion +from network import dandelion from bmconfigparser import config from highlevelcrypto import randomBytes from queues import invQueue, receiveDataQueue, UISignalQueue diff --git a/src/network/uploadthread.py b/src/network/uploadthread.py index e1e8d121..bd5f2d67 100644 --- a/src/network/uploadthread.py +++ b/src/network/uploadthread.py @@ -7,7 +7,7 @@ import helper_random import protocol import state from network import connectionpool -import dandelion +from network import dandelion from randomtrackingdict import RandomTrackingDict from .threads import StoppableThread diff --git a/src/protocol.py b/src/protocol.py index 125204fc..8fd6c8fd 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -13,6 +13,7 @@ import time from binascii import hexlify from struct import Struct, pack, unpack import six +import sqlite3 import defaults import highlevelcrypto @@ -562,7 +563,7 @@ def decryptAndCheckPubkeyPayload(data, address): hexlify(pubSigningKey), hexlify(pubEncryptionKey) ) - t = (dbstr(address), addressVersion, storedData, int(time.time()), dbstr('yes')) + t = (dbstr(address), addressVersion, sqlite3.Binary(storedData), int(time.time()), dbstr('yes')) sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t) return 'successful' except varintDecodeError: diff --git a/src/storage/sqlite.py b/src/storage/sqlite.py index db8e002a..9d1f32b0 100644 --- a/src/storage/sqlite.py +++ b/src/storage/sqlite.py @@ -110,6 +110,7 @@ class SqliteInventory(InventoryStorage): # always use the inventoryLock OUTSIDE of the sqlLock. with SqlBulkExecute() as sql: for objectHash, value in self._inventory.items(): + value = [value[0], value[1], sqlite3.Binary(value[2]), value[3], sqlite3.Binary(value[4])] sql.execute( 'INSERT INTO inventory VALUES (?, ?, ?, ?, ?, ?)', sqlite3.Binary(objectHash), *value) diff --git a/src/tests/core.py b/src/tests/core.py index 7c646b28..69d4e43d 100644 --- a/src/tests/core.py +++ b/src/tests/core.py @@ -16,6 +16,7 @@ import threading import time import unittest import six +import sqlite3 import protocol import state @@ -347,11 +348,17 @@ class TestCore(unittest.TestCase): subject=subject, message=message ) queryreturn = sqlQuery( - '''select msgid from sent where ackdata=?''', result) + '''select msgid from sent where ackdata=?''', sqlite3.Binary(result)) + if len(queryreturn) < 1: + queryreturn = sqlQuery( + '''select msgid from sent where ackdata=CAST(? AS TEXT)''', result) self.assertNotEqual(queryreturn[0][0] if queryreturn else b'', b'') column_type = sqlQuery( - '''select typeof(msgid) from sent where ackdata=?''', result) + '''select typeof(msgid) from sent where ackdata=?''', sqlite3.Binary(result)) + if len(column_type) < 1: + column_type = sqlQuery( + '''select typeof(msgid) from sent where ackdata=CAST(? AS TEXT)''', result) self.assertEqual(column_type[0][0] if column_type else '', 'blob') @unittest.skipIf(frozen, 'not packed test_pattern into the bundle') diff --git a/src/tests/test_helper_sql.py b/src/tests/test_helper_sql.py index 2e0a1776..a32f92c9 100644 --- a/src/tests/test_helper_sql.py +++ b/src/tests/test_helper_sql.py @@ -1,6 +1,7 @@ """Test cases for helper_sql""" import unittest +import sqlite3 try: # Python 3 @@ -49,8 +50,14 @@ class TestHelperSql(unittest.TestCase): rowcount = helper_sql.sqlExecute( "UPDATE sent SET status = 'msgqueued'" "WHERE ackdata = ? AND folder = 'sent'", - b"1710652313", + sqlite3.Binary(b"1710652313"), ) + if rowcount < 0: + rowcount = helper_sql.sqlExecute( + "UPDATE sent SET status = 'msgqueued'" + "WHERE ackdata = CAST(? AS TEXT) AND folder = 'sent'", + b"1710652313", + ) self.assertEqual(mock_sqlsubmitqueue_put.call_count, 3) self.assertEqual(rowcount, 1) @@ -80,7 +87,7 @@ class TestHelperSql(unittest.TestCase): for i in range(0, ID_COUNT): args.append("arg{}".format(i)) total_row_count_return = helper_sql.sqlExecuteChunked( - "INSERT INTO table VALUES {}", ID_COUNT, *args + "INSERT INTO table VALUES {}", False, ID_COUNT, *args ) self.assertEqual(TOTAL_ROW_COUNT, total_row_count_return) self.assertTrue(mock_sqlsubmitqueue_put.called) @@ -97,7 +104,7 @@ class TestHelperSql(unittest.TestCase): for i in range(0, ID_COUNT): args.append("arg{}".format(i)) total_row_count = helper_sql.sqlExecuteChunked( - "INSERT INTO table VALUES {}", ID_COUNT, *args + "INSERT INTO table VALUES {}", False, ID_COUNT, *args ) self.assertEqual(total_row_count, 0) self.assertFalse(mock_sqlsubmitqueue_put.called) @@ -112,7 +119,7 @@ class TestHelperSql(unittest.TestCase): ID_COUNT = 12 args = ["args0", "arg1"] total_row_count = helper_sql.sqlExecuteChunked( - "INSERT INTO table VALUES {}", ID_COUNT, *args + "INSERT INTO table VALUES {}", False, ID_COUNT, *args ) self.assertEqual(total_row_count, 0) self.assertFalse(mock_sqlsubmitqueue_put.called)