From d676ea3ec2997b4842ccbc847f774751eaf674f0 Mon Sep 17 00:00:00 2001 From: Kashiko Koibumi Date: Thu, 30 May 2024 18:13:15 +0900 Subject: [PATCH 1/3] quick workaround for BLOB as TEXT problem (#2247) --- src/api.py | 74 ++++++++++++--- src/bitmessagecurses/__init__.py | 41 ++++++-- src/bitmessagekivy/baseclass/maildetail.py | 7 +- src/bitmessageqt/__init__.py | 103 ++++++++++++++++----- src/bitmessageqt/account.py | 7 +- src/bitmessageqt/foldertree.py | 2 +- src/class_objectProcessor.py | 23 +++-- src/class_singleCleaner.py | 9 +- src/class_singleWorker.py | 62 ++++++++++--- src/class_smtpServer.py | 7 +- src/class_sqlThread.py | 2 +- src/helper_inbox.py | 22 ++++- src/helper_sent.py | 19 +++- src/helper_sql.py | 13 ++- src/protocol.py | 3 +- src/storage/sqlite.py | 1 + src/tests/core.py | 11 ++- src/tests/test_helper_sql.py | 15 ++- 18 files changed, 320 insertions(+), 101 deletions(-) diff --git a/src/api.py b/src/api.py index a444556951..87af4d3275 100644 --- a/src/api.py +++ b/src/api.py @@ -67,6 +67,7 @@ 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 @@ -953,20 +954,32 @@ def HandleGetInboxMessageById(self, hid, readStatus=None): 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])]} @@ -1035,8 +1048,14 @@ def HandleGetSentMessageById(self, hid): 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]) @@ -1072,8 +1091,14 @@ def HandleGetSentMessagesByAckData(self, ackData): 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": [ @@ -1093,7 +1118,9 @@ def HandleTrashMessage(self, msgid): # 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') @@ -1107,7 +1134,9 @@ def HandleTrashInboxMessage(self, msgid): 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') @@ -1217,7 +1246,10 @@ def HandleGetStatus(self, ackdata): 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] except IndexError: @@ -1354,7 +1386,9 @@ def HandleTrashSentMessageByAckDAta(self, ackdata): """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') @@ -1421,19 +1455,29 @@ def HandleGetMessageDataByDestinationHash(self, requestedHash): # 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 = (payload[readPosition:readPosition + 32], sqlite3.Binary(hash01)) + _, rowcount = sql.execute("UPDATE inventory SET tag=? WHERE hash=?", *t) + if rowcount < 1: + t = (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 64fd735b45..b87b9ddeff 100644 --- a/src/bitmessagecurses/__init__.py +++ b/src/bitmessagecurses/__init__.py @@ -17,6 +17,7 @@ import time from textwrap import fill from threading import Timer +import sqlite3 from dialog import Dialog import helper_sent @@ -358,7 +359,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 @@ -367,12 +370,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) @@ -396,7 +403,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: @@ -422,7 +431,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 @@ -432,7 +443,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," @@ -464,7 +477,12 @@ def handlech(c, stdscr): ret = sqlQuery( "SELECT message FROM sent WHERE subject=? AND ackdata=?", 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)", + sentbox[sentcur][4], + sentbox[sentcur][6]) if ret != []: for row in ret: data, = row @@ -476,10 +494,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=?", 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)", + 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 6ddf322d5e..3d57ce882c 100644 --- a/src/bitmessagekivy/baseclass/maildetail.py +++ b/src/bitmessagekivy/baseclass/maildetail.py @@ -7,6 +7,7 @@ import os from datetime import datetime +import sqlite3 from kivy.core.clipboard import Clipboard from kivy.clock import Clock @@ -111,7 +112,11 @@ def init_ui(self, dt=0): 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 40113b5ada..42ef6f8044 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -14,6 +14,7 @@ import time from datetime import datetime, timedelta from sqlite3 import register_adapter +import sqlite3 from PyQt4 import QtCore, QtGui from PyQt4.QtNetwork import QLocalSocket, QLocalServer @@ -2671,14 +2672,19 @@ def on_action_MarkAllRead(self): 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() @@ -2916,7 +2922,10 @@ def on_action_InboxMessageForceHtml(self): if not msgid: return 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: messageText, = row @@ -2946,7 +2955,7 @@ def on_action_InboxMarkUnread(self): # 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 @@ -2955,10 +2964,15 @@ def on_action_InboxMarkUnread(self): # 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() # tableWidget.selectRow(currentRow + 1) @@ -3038,8 +3052,12 @@ def on_action_InboxReply(self, reply_type=None): 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 @@ -3213,16 +3231,21 @@ def on_action_InboxTrash(self): )[::-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) + " 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) @@ -3241,16 +3264,20 @@ def on_action_TrashUndelete(self): )[::-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, as_text=True) tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1) tableWidget.setUpdatesEnabled(True) self.propagateUnreadCount() @@ -3270,7 +3297,10 @@ def on_action_InboxSaveMessageAs(self): # 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 @@ -3301,11 +3331,17 @@ def on_action_SentTrash(self): 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( @@ -3319,9 +3355,13 @@ def on_action_ForceSend(self): 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 @@ -4017,7 +4057,9 @@ def on_context_menuSent(self, point): # 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 if status == 'toodifficult': @@ -4119,8 +4161,15 @@ def tableWidgetInboxItemClicked(self): '''SELECT message FROM %s WHERE %s=?''' % ( ('sent', 'ackdata') if folder == 'sent' else ('inbox', 'msgid') - ), msgid + ), sqlite3.Binary(msgid) ) + if len(queryreturn) < 1: + 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] @@ -4138,10 +4187,16 @@ def tableWidgetInboxItemClicked(self): 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 8c82c6f64e..5c58b0ec0c 100644 --- a/src/bitmessageqt/account.py +++ b/src/bitmessageqt/account.py @@ -13,6 +13,7 @@ import re import sys import time +import sqlite3 from PyQt4 import QtGui @@ -201,13 +202,13 @@ def send(self): ackdata = genAckPayload(streamNumber, stealthLevel) sqlExecute( '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', - '', + sqlite3.Binary(''), self.toAddress, - ripe, + sqlite3.Binary(ripe), self.fromAddress, self.subject, 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/bitmessageqt/foldertree.py b/src/bitmessageqt/foldertree.py index c50b7d3d47..ea4333fb88 100644 --- a/src/bitmessageqt/foldertree.py +++ b/src/bitmessageqt/foldertree.py @@ -478,7 +478,7 @@ class MessageList_TimeWidget(BMTableWidgetItem): def __init__(self, label=None, unread=False, timestamp=None, msgid=''): super(MessageList_TimeWidget, self).__init__(label, unread) - self.setData(QtCore.Qt.UserRole, QtCore.QByteArray(msgid)) + self.setData(QtCore.Qt.UserRole, QtCore.QByteArray(bytes(msgid))) self.setData(TimestampRole, int(timestamp)) def __lt__(self, other): diff --git a/src/class_objectProcessor.py b/src/class_objectProcessor.py index 469ccbfab8..dc567d4b6e 100644 --- a/src/class_objectProcessor.py +++ b/src/class_objectProcessor.py @@ -12,6 +12,7 @@ import threading import time from binascii import hexlify +import sqlite3 import helper_bitcoin import helper_inbox @@ -121,7 +122,7 @@ def run(self): 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' @@ -143,9 +144,13 @@ def checkackdata(data): if data[readPosition:] in state.ackdataForWhichImWatching: logger.info('This object is an acknowledgement bound for me.') del state.ackdataForWhichImWatching[data[readPosition:]] - sqlExecute( + rowcount = sqlExecute( "UPDATE sent SET status='ackreceived', lastactiontime=?" - " WHERE ackdata=?", int(time.time()), data[readPosition:]) + " WHERE ackdata=?", int(time.time()), sqlite3.Binary(data[readPosition:])) + if rowcount < 1: + rowcount = sqlExecute( + "UPDATE sent SET status='ackreceived', lastactiontime=?" + " WHERE ackdata=CAST(? AS TEXT)", int(time.time()), data[readPosition:]) queues.UISignalQueue.put(( 'updateSentItemStatusByAckdata', ( data[readPosition:], @@ -333,13 +338,13 @@ def processpubkey(self, data): if queryreturn != []: logger.info( 'We HAVE used this pubkey personally. Updating time.') - t = (address, addressVersion, dataToStore, + t = (address, addressVersion, sqlite3.Binary(dataToStore), int(time.time()), 'yes') else: logger.info( 'We have NOT used this pubkey personally. Inserting' ' in database.') - t = (address, addressVersion, dataToStore, + t = (address, addressVersion, sqlite3.Binary(dataToStore), int(time.time()), 'no') sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t) self.possibleNewPubkey(address) @@ -395,13 +400,13 @@ def processpubkey(self, data): if queryreturn != []: logger.info( 'We HAVE used this pubkey personally. Updating time.') - t = (address, addressVersion, dataToStore, + t = (address, addressVersion, sqlite3.Binary(dataToStore), int(time.time()), 'yes') else: logger.info( 'We have NOT used this pubkey personally. Inserting' ' in database.') - t = (address, addressVersion, dataToStore, + t = (address, addressVersion, sqlite3.Binary(dataToStore), int(time.time()), 'no') sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t) self.possibleNewPubkey(address) @@ -592,7 +597,7 @@ def processmsg(self, data): '''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', fromAddress, sendersAddressVersionNumber, - decryptedData[:endOfThePublicKeyPosition], + sqlite3.Binary(decryptedData[:endOfThePublicKeyPosition]), int(time.time()), 'yes') @@ -929,7 +934,7 @@ def processbroadcast(self, data): sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', fromAddress, sendersAddressVersion, - decryptedData[:endOfPubkeyPosition], + sqlite3.Binary(decryptedData[:endOfPubkeyPosition]), int(time.time()), 'yes') diff --git a/src/class_singleCleaner.py b/src/class_singleCleaner.py index 06153dcf28..3f3c914029 100644 --- a/src/class_singleCleaner.py +++ b/src/class_singleCleaner.py @@ -22,6 +22,7 @@ import gc import os import time +import sqlite3 import queues import state @@ -177,9 +178,13 @@ def resendMsg(self, ackdata): '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 f2821f6570..60b18efa9c 100644 --- a/src/class_singleWorker.py +++ b/src/class_singleWorker.py @@ -11,6 +11,7 @@ from binascii import hexlify, unhexlify from struct import pack from subprocess import call # nosec +import sqlite3 import defaults import helper_inbox @@ -107,10 +108,15 @@ def run(self): # attach legacy header, always constant (msg/1/1) newack = '\x00\x00\x00\x02\x01\x01' + oldack state.ackdataForWhichImWatching[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 @@ -578,11 +584,18 @@ def sendBroadcast(self): )) 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 @@ -703,11 +716,17 @@ def sendBroadcast(self): # 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, 'broadcastsent', int(time.time()), ackdata + sqlite3.Binary(inventoryHash), '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): """Send a message-type object (assemble the object, perform PoW and put it to the inv announcement queue)""" @@ -1065,10 +1084,15 @@ def sendMsg(self): 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, @@ -1231,10 +1255,15 @@ def sendMsg(self): ) 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, @@ -1337,12 +1366,19 @@ def sendMsg(self): 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, newStatus, retryNumber + 1, - sleepTill, int(time.time()), ackdata + sqlite3.Binary(inventoryHash), 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 44ea7c9cc4..45dbb01e15 100644 --- a/src/class_smtpServer.py +++ b/src/class_smtpServer.py @@ -12,6 +12,7 @@ import time from email.header import decode_header from email.parser import Parser +import sqlite3 import queues from addresses import decodeAddress @@ -88,13 +89,13 @@ def send(self, fromAddress, toAddress, subject, message): ackdata = genAckPayload(streamNumber, stealthLevel) sqlExecute( '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', - '', + sqlite3.Binary(''), toAddress, - ripe, + sqlite3.Binary(ripe), fromAddress, subject, 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 7df9e253ac..a2eab64680 100644 --- a/src/class_sqlThread.py +++ b/src/class_sqlThread.py @@ -73,7 +73,7 @@ def run(self): # pylint: disable=too-many-locals, too-many-branches, too-many-s '''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 555795df19..b20edf944d 100644 --- a/src/helper_inbox.py +++ b/src/helper_inbox.py @@ -1,12 +1,15 @@ """Helper Inbox performs inbox messages related operations""" +import sqlite3 + import queues from helper_sql import sqlExecute, sqlQuery def insert(t): """Perform an insert into the "inbox" table""" - sqlExecute('''INSERT INTO inbox VALUES (?,?,?,?,?,?,?,?,?,?)''', *t) + u = [sqlite3.Binary(t[0]), t[1], t[2], t[3], t[4], t[5], 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 # queues.UISignalQueue.put(('changedInboxUnread', None)) @@ -14,22 +17,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 aa76e756a8..8dca93e974 100644 --- a/src/helper_sent.py +++ b/src/helper_sent.py @@ -4,6 +4,7 @@ import time import uuid +import sqlite3 from addresses import decodeAddress from bmconfigparser import config from helper_ackPayload import genAckPayload @@ -38,7 +39,7 @@ def insert(msgid=None, toAddress='[Broadcast subscribers]', fromAddress=None, su ttl = ttl if ttl else config.getint('bitmessagesettings', 'ttl') - t = (msgid, toAddress, ripe, fromAddress, subject, message, ackdata, + t = (sqlite3.Binary(msgid), toAddress, sqlite3.Binary(ripe), fromAddress, subject, message, sqlite3.Binary(ackdata), sentTime, lastActionTime, sleeptill, status, retryNumber, folder, encoding, ttl) @@ -50,20 +51,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 8dee9e0cb5..cfacfde943 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/protocol.py b/src/protocol.py index 7f9830e521..596e0647fa 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -12,6 +12,7 @@ import time from binascii import hexlify from struct import Struct, pack, unpack +import sqlite3 import defaults import highlevelcrypto @@ -558,7 +559,7 @@ def decryptAndCheckPubkeyPayload(data, address): hexlify(pubSigningKey), hexlify(pubEncryptionKey) ) - t = (address, addressVersion, storedData, int(time.time()), 'yes') + t = (address, addressVersion, sqlite3.Binary(storedData), int(time.time()), 'yes') sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t) return 'successful' except varintDecodeError: diff --git a/src/storage/sqlite.py b/src/storage/sqlite.py index eb5df098d8..aa97c52a01 100644 --- a/src/storage/sqlite.py +++ b/src/storage/sqlite.py @@ -107,6 +107,7 @@ def flush(self): # 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 f1a11a062d..aa42ada0bd 100644 --- a/src/tests/core.py +++ b/src/tests/core.py @@ -15,6 +15,7 @@ import threading import time import unittest +import sqlite3 import protocol import state @@ -345,11 +346,17 @@ def test_insert_method_msgid(self): 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 '', '') 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 '', 'text') @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 036bd2c945..50ffbc1309 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 @@ def test_sqlexecute(self, mock_sqlreturnqueue_get, mock_sqlsubmitqueue_put): rowcount = helper_sql.sqlExecute( "UPDATE sent SET status = 'msgqueued'" "WHERE ackdata = ? AND folder = 'sent'", - "1710652313", + sqlite3.Binary("1710652313"), ) + if rowcount < 0: + rowcount = helper_sql.sqlExecute( + "UPDATE sent SET status = 'msgqueued'" + "WHERE ackdata = CAST(? AS TEXT) AND folder = 'sent'", + "1710652313", + ) self.assertEqual(mock_sqlsubmitqueue_put.call_count, 3) self.assertEqual(rowcount, 1) @@ -80,7 +87,7 @@ def test_sqlexecute_chunked(self, mock_sqlreturnqueue_get, mock_sqlsubmitqueue_p 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 @@ def test_sqlexecute_chunked_with_idcount_zero( 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 @@ def test_sqlexecute_chunked_with_args_less( 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) From 07953592aa95df670f01b600ab904c39c8008374 Mon Sep 17 00:00:00 2001 From: Kashiko Koibumi Date: Thu, 30 May 2024 20:09:16 +0900 Subject: [PATCH 2/3] fix careless mistakes --- src/api.py | 4 ++-- src/bitmessageqt/__init__.py | 2 +- src/tests/core.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api.py b/src/api.py index 87af4d3275..80e9c24db4 100644 --- a/src/api.py +++ b/src/api.py @@ -1467,10 +1467,10 @@ def HandleGetMessageDataByDestinationHash(self, requestedHash): # Stream Number length readPosition += decodeVarint( payload[readPosition:readPosition + 10])[1] - t = (payload[readPosition:readPosition + 32], sqlite3.Binary(hash01)) + t = (sqlite3.Binary(payload[readPosition:readPosition + 32]), sqlite3.Binary(hash01)) _, rowcount = sql.execute("UPDATE inventory SET tag=? WHERE hash=?", *t) if rowcount < 1: - t = (payload[readPosition:readPosition + 32], hash01) + t = (sqlite3.Binary(payload[readPosition:readPosition + 32]), hash01) sql.execute("UPDATE inventory SET tag=? WHERE hash=CAST(? AS TEXT)", *t) queryreturn = sqlQuery( diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 42ef6f8044..add5fb959e 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -3277,7 +3277,7 @@ def on_action_TrashUndelete(self): if total_row_count < 1: sqlExecuteChunked( "UPDATE inbox SET folder='inbox' WHERE msgid IN({0})", - True, idCount, *inventoryHashesToTrash, as_text=True) + True, idCount, *inventoryHashesToTrash) tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1) tableWidget.setUpdatesEnabled(True) self.propagateUnreadCount() diff --git a/src/tests/core.py b/src/tests/core.py index aa42ada0bd..c0de4d3b27 100644 --- a/src/tests/core.py +++ b/src/tests/core.py @@ -357,7 +357,7 @@ def test_insert_method_msgid(self): 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 '', 'text') + self.assertEqual(column_type[0][0] if column_type else '', 'blob') @unittest.skipIf(frozen, 'not packed test_pattern into the bundle') def test_old_knownnodes_pickle(self): From 31dcbd6d5f12e4bac9935030c11eca2ea887e566 Mon Sep 17 00:00:00 2001 From: Kashiko Koibumi Date: Thu, 30 May 2024 20:59:59 +0900 Subject: [PATCH 3/3] add script to revert BLOB-keys into TEXT-keys --- revert_blob_to_text.sh | 3 +++ src/revert_blob_to_text.py | 52 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100755 revert_blob_to_text.sh create mode 100644 src/revert_blob_to_text.py diff --git a/revert_blob_to_text.sh b/revert_blob_to_text.sh new file mode 100755 index 0000000000..fbac98c183 --- /dev/null +++ b/revert_blob_to_text.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +python3 pybitmessage/revert_blob_to_text.py "$@" diff --git a/src/revert_blob_to_text.py b/src/revert_blob_to_text.py new file mode 100644 index 0000000000..bd38066d5b --- /dev/null +++ b/src/revert_blob_to_text.py @@ -0,0 +1,52 @@ +import helper_startup +import state +import shutil +import sqlite3 + +expected_ver = 11 + +print("Looking up database file..") +helper_startup.loadConfig() +db_path = state.appdata + "messages.dat" +print("Database path: {}".format(db_path)) +db_backup_path = db_path + ".blob-keys" +print("Backup path: {}".format(db_backup_path)) +shutil.copyfile(db_path, db_backup_path) +print("Copied to backup") + +print() + +print("Open the database") +conn = sqlite3.connect(db_path) +cur = conn.cursor() + +cur.execute("SELECT value FROM settings WHERE key='version';") +ver = int(cur.fetchall()[0][0]) +print("PyBitmessage database version: {}".format(ver)) +if ver != expected_ver: + print("Error: version must be {}".format(expected_ver)) + conn.close() + print("Quitting..") + quit() +print("Version OK") + +print() + +print("Converting..") +q = "UPDATE inbox SET msgid=CAST(msgid AS TEXT), sighash=CAST(sighash AS TEXT);" +print(q) +cur.execute(q) +q = "UPDATE pubkeys SET transmitdata=CAST(transmitdata AS TEXT);" +print(q) +cur.execute(q) +q = "UPDATE sent SET msgid=CAST(msgid AS TEXT), toripe=CAST(toripe AS TEXT), ackdata=CAST(ackdata AS TEXT);" +print(q) +cur.execute(q) + +print("Commiting..") +conn.commit() +print("Conversion done") + +print("Close the database") +conn.close() +print("Finished")