Quick workaround for BLOB as TEXT problem (#2247) #2248

Open
kashikoibumi wants to merge 3 commits from kashikoibumi/strict-blob into v0.6
20 changed files with 376 additions and 102 deletions

3
revert_blob_to_text.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
python3 pybitmessage/revert_blob_to_text.py "$@"

View File

@ -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
@ -953,20 +954,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])]}
@ -1035,8 +1048,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])
@ -1072,8 +1091,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": [
@ -1093,7 +1118,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')
@ -1107,7 +1134,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')
@ -1217,7 +1246,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]
except IndexError:
@ -1354,7 +1386,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')
@ -1421,19 +1455,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
]}

View File

@ -17,6 +17,7 @@ import sys
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"

View File

@ -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

View File

@ -14,6 +14,7 @@ import threading
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 @@ 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()
@ -2916,7 +2922,10 @@ class MyForm(settingsmixin.SMainWindow):
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 @@ 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
@ -2955,10 +2964,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()
# tableWidget.selectRow(currentRow + 1)
@ -3038,8 +3052,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
@ -3213,16 +3231,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)
" 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 @@ 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()
@ -3270,7 +3297,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
@ -3301,11 +3331,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(
@ -3319,9 +3355,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
@ -4017,7 +4057,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
if status == 'toodifficult':
@ -4119,8 +4161,15 @@ class MyForm(settingsmixin.SMainWindow):
'''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 @@ 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())

View File

@ -13,6 +13,7 @@ import inspect
import re
import sys
import time
import sqlite3
from PyQt4 import QtGui
@ -201,13 +202,13 @@ class GatewayAccount(BMAccount):
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.

View File

@ -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):

View File

@ -12,6 +12,7 @@ import subprocess # nosec B404
import threading
import time
from binascii import hexlify
import sqlite3
import helper_bitcoin
import helper_inbox
@ -121,7 +122,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'
@ -143,9 +144,13 @@ class objectProcessor(threading.Thread):
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 @@ class objectProcessor(threading.Thread):
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 @@ class objectProcessor(threading.Thread):
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 @@ class objectProcessor(threading.Thread):
'''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
fromAddress,
sendersAddressVersionNumber,
decryptedData[:endOfThePublicKeyPosition],
sqlite3.Binary(decryptedData[:endOfThePublicKeyPosition]),
int(time.time()),
'yes')
@ -929,7 +934,7 @@ class objectProcessor(threading.Thread):
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
fromAddress,
sendersAddressVersion,
decryptedData[:endOfPubkeyPosition],
sqlite3.Binary(decryptedData[:endOfPubkeyPosition]),
int(time.time()),
'yes')

View File

@ -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
@ -177,9 +178,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',

View File

@ -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
@ -107,10 +108,15 @@ class singleWorker(StoppableThread):
# 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 @@ 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
@ -703,11 +716,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, '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 @@ 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,
@ -1231,10 +1255,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,
@ -1337,12 +1366,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, 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.

View File

@ -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
@ -88,13 +89,13 @@ class smtpServerPyBitmessage(smtpd.SMTPServer):
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.

View File

@ -73,7 +73,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()),))

View File

@ -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

View File

@ -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
@ -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

View File

@ -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

View File

@ -12,6 +12,7 @@ import sys
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:

View File

@ -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")

View File

@ -107,6 +107,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)

View File

@ -15,6 +15,7 @@ import sys
import threading
import time
import unittest
import sqlite3
import protocol
import state
@ -345,12 +346,18 @@ 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 '', '')
column_type = sqlQuery(
'''select typeof(msgid) from sent where ackdata=?''', result)
self.assertEqual(column_type[0][0] if column_type else '', 'text')
'''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')
def test_old_knownnodes_pickle(self):

View File

@ -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'",
"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 @@ 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)