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 import time
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from struct import pack, unpack from struct import pack, unpack
import sqlite3
import six import six
from six.moves import configparser, http_client, xmlrpc_server from six.moves import configparser, http_client, xmlrpc_server
@ -953,19 +954,31 @@ class BMRPCDispatcher(object):
23, 'Bool expected in readStatus, saw %s instead.' 23, 'Bool expected in readStatus, saw %s instead.'
% type(readStatus)) % type(readStatus))
queryreturn = sqlQuery( 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 # UPDATE is slow, only update if status is different
try: try:
if (queryreturn[0][0] == 1) != readStatus: if (queryreturn[0][0] == 1) != readStatus:
sqlExecute( rowcount = sqlExecute(
"UPDATE inbox set read = ? WHERE msgid=?", "UPDATE inbox set read = ? WHERE msgid=?",
readStatus, sqlite3.Binary(msgid))
if rowcount < 1:
rowcount = sqlExecute(
"UPDATE inbox set read = ? WHERE msgid=CAST(? AS TEXT)",
readStatus, msgid) readStatus, msgid)
queues.UISignalQueue.put(('changedInboxUnread', None)) queues.UISignalQueue.put(('changedInboxUnread', None))
except IndexError: except IndexError:
pass pass
queryreturn = sqlQuery( queryreturn = sqlQuery(
"SELECT msgid, toaddress, fromaddress, subject, received, message," "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: try:
return {"inboxMessage": [ return {"inboxMessage": [
@ -1035,6 +1048,12 @@ class BMRPCDispatcher(object):
queryreturn = sqlQuery( queryreturn = sqlQuery(
"SELECT msgid, toaddress, fromaddress, subject, lastactiontime," "SELECT msgid, toaddress, fromaddress, subject, lastactiontime,"
" message, encodingtype, status, ackdata FROM sent WHERE msgid=?", " message, encodingtype, status, ackdata FROM sent WHERE 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 msgid
) )
try: try:
@ -1072,7 +1091,13 @@ class BMRPCDispatcher(object):
queryreturn = sqlQuery( queryreturn = sqlQuery(
"SELECT msgid, toaddress, fromaddress, subject, lastactiontime," "SELECT msgid, toaddress, fromaddress, subject, lastactiontime,"
" message, encodingtype, status, ackdata FROM sent" " 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: try:
@ -1093,7 +1118,9 @@ class BMRPCDispatcher(object):
# Trash if in inbox table # Trash if in inbox table
helper_inbox.trash(msgid) helper_inbox.trash(msgid)
# Trash if in sent table # 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).' return 'Trashed message (assuming message existed).'
@command('trashInboxMessage') @command('trashInboxMessage')
@ -1107,7 +1134,9 @@ class BMRPCDispatcher(object):
def HandleTrashSentMessage(self, msgid): def HandleTrashSentMessage(self, msgid):
"""Trash sent message by msgid (encoded in hex).""" """Trash sent message by msgid (encoded in hex)."""
msgid = self._decode(msgid, "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).' return 'Trashed sent message (assuming message existed).'
@command('sendMessage') @command('sendMessage')
@ -1217,7 +1246,10 @@ class BMRPCDispatcher(object):
raise APIError(15, 'Invalid ackData object size.') raise APIError(15, 'Invalid ackData object size.')
ackdata = self._decode(ackdata, "hex") ackdata = self._decode(ackdata, "hex")
queryreturn = sqlQuery( 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: try:
return queryreturn[0][0] return queryreturn[0][0]
except IndexError: except IndexError:
@ -1354,7 +1386,9 @@ class BMRPCDispatcher(object):
"""Trash a sent message by ackdata (hex encoded)""" """Trash a sent message by ackdata (hex encoded)"""
# This API method should only be used when msgid is not available # This API method should only be used when msgid is not available
ackdata = self._decode(ackdata, "hex") 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).' return 'Trashed sent message (assuming message existed).'
@command('disseminatePubkey') @command('disseminatePubkey')
@ -1421,19 +1455,29 @@ class BMRPCDispatcher(object):
# use it we'll need to fill out a field in our inventory database # use it we'll need to fill out a field in our inventory database
# which is blank by default (first20bytesofencryptedmessage). # which is blank by default (first20bytesofencryptedmessage).
queryreturn = sqlQuery( queryreturn = sqlQuery(
"SELECT hash, payload FROM inventory WHERE tag = ''" "SELECT hash, payload FROM inventory WHERE tag = ?"
" and objecttype = 2") " 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: with SqlBulkExecute() as sql:
for hash01, payload in queryreturn: for hash01, payload in queryreturn:
readPosition = 16 # Nonce length + time length readPosition = 16 # Nonce length + time length
# Stream Number length # Stream Number length
readPosition += decodeVarint( readPosition += decodeVarint(
payload[readPosition:readPosition + 10])[1] payload[readPosition:readPosition + 10])[1]
t = (payload[readPosition:readPosition + 32], hash01) t = (sqlite3.Binary(payload[readPosition:readPosition + 32]), sqlite3.Binary(hash01))
sql.execute("UPDATE inventory SET tag=? WHERE hash=?", *t) _, 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( 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": [ return {"receivedMessageDatas": [
{'data': hexlify(payload)} for payload, in queryreturn {'data': hexlify(payload)} for payload, in queryreturn
]} ]}

View File

@ -17,6 +17,7 @@ import sys
import time import time
from textwrap import fill from textwrap import fill
from threading import Timer from threading import Timer
import sqlite3
from dialog import Dialog from dialog import Dialog
import helper_sent import helper_sent
@ -358,7 +359,9 @@ def handlech(c, stdscr):
inbox[inboxcur][1] + inbox[inboxcur][1] +
"\"") "\"")
data = "" # pyint: disable=redefined-outer-name 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 != []: if ret != []:
for row in ret: for row in ret:
data, = row data, = row
@ -367,12 +370,16 @@ def handlech(c, stdscr):
for i, item in enumerate(data.split("\n")): for i, item in enumerate(data.split("\n")):
msg += fill(item, replace_whitespace=False) + "\n" msg += fill(item, replace_whitespace=False) + "\n"
scrollbox(d, unicode(ascii(msg)), 30, 80) 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 inbox[inboxcur][7] = 1
else: else:
scrollbox(d, unicode("Could not fetch message.")) scrollbox(d, unicode("Could not fetch message."))
elif t == "2": # Mark unread 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 inbox[inboxcur][7] = 0
elif t == "3": # Reply elif t == "3": # Reply
curses.curs_set(1) curses.curs_set(1)
@ -396,7 +403,9 @@ def handlech(c, stdscr):
if not m[5][:4] == "Re: ": if not m[5][:4] == "Re: ":
subject = "Re: " + m[5] subject = "Re: " + m[5]
body = "" 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 != []: if ret != []:
body = "\n\n------------------------------------------------------\n" body = "\n\n------------------------------------------------------\n"
for row in ret: for row in ret:
@ -422,7 +431,9 @@ def handlech(c, stdscr):
r, t = d.inputbox("Filename", init=inbox[inboxcur][5] + ".txt") r, t = d.inputbox("Filename", init=inbox[inboxcur][5] + ".txt")
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
msg = "" 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 != []: if ret != []:
for row in ret: for row in ret:
msg, = row msg, = row
@ -432,7 +443,9 @@ def handlech(c, stdscr):
else: else:
scrollbox(d, unicode("Could not fetch message.")) scrollbox(d, unicode("Could not fetch message."))
elif t == "6": # Move to trash 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] del inbox[inboxcur]
scrollbox(d, unicode( scrollbox(d, unicode(
"Message moved to trash. There is no interface to view your trash," "Message moved to trash. There is no interface to view your trash,"
@ -464,6 +477,11 @@ def handlech(c, stdscr):
ret = sqlQuery( ret = sqlQuery(
"SELECT message FROM sent WHERE subject=? AND ackdata=?", "SELECT message FROM sent WHERE subject=? AND ackdata=?",
sentbox[sentcur][4], sentbox[sentcur][4],
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]) sentbox[sentcur][6])
if ret != []: if ret != []:
for row in ret: for row in ret:
@ -476,9 +494,14 @@ def handlech(c, stdscr):
else: else:
scrollbox(d, unicode("Could not fetch message.")) scrollbox(d, unicode("Could not fetch message."))
elif t == "2": # Move to trash elif t == "2": # Move to trash
sqlExecute( rowcount = sqlExecute(
"UPDATE sent SET folder='trash' WHERE subject=? AND ackdata=?", "UPDATE sent SET folder='trash' WHERE subject=? AND ackdata=?",
sentbox[sentcur][4], sentbox[sentcur][4],
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]) sentbox[sentcur][6])
del sentbox[sentcur] del sentbox[sentcur]
scrollbox(d, unicode( scrollbox(d, unicode(

View File

@ -7,6 +7,7 @@ Maildetail screen for inbox, sent, draft and trash.
import os import os
from datetime import datetime from datetime import datetime
import sqlite3
from kivy.core.clipboard import Clipboard from kivy.core.clipboard import Clipboard
from kivy.clock import Clock 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': elif self.kivy_state.detail_page_type == 'inbox':
data = sqlQuery( data = sqlQuery(
"select toaddress, fromaddress, subject, message, received from inbox" "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) self.assign_mail_details(data)
App.get_running_app().set_mail_detail_header() App.get_running_app().set_mail_detail_header()
except Exception as e: # pylint: disable=unused-variable except Exception as e: # pylint: disable=unused-variable

View File

@ -14,6 +14,7 @@ import threading
import time import time
from datetime import datetime, timedelta from datetime import datetime, timedelta
from sqlite3 import register_adapter from sqlite3 import register_adapter
import sqlite3
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from PyQt4.QtNetwork import QLocalSocket, QLocalServer from PyQt4.QtNetwork import QLocalSocket, QLocalServer
@ -2671,13 +2672,18 @@ class MyForm(settingsmixin.SMainWindow):
msgids = [] msgids = []
for i in range(0, idCount): 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()): for col in xrange(tableWidget.columnCount()):
tableWidget.item(i, col).setUnread(False) tableWidget.item(i, col).setUnread(False)
markread = sqlExecuteChunked( markread = sqlExecuteChunked(
"UPDATE inbox SET read = 1 WHERE msgid IN({0}) AND read=0", "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: if markread > 0:
@ -2916,7 +2922,10 @@ class MyForm(settingsmixin.SMainWindow):
if not msgid: if not msgid:
return return
queryreturn = sqlQuery( 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 != []: if queryreturn != []:
for row in queryreturn: for row in queryreturn:
messageText, = row messageText, = row
@ -2946,7 +2955,7 @@ class MyForm(settingsmixin.SMainWindow):
# modified = 0 # modified = 0
for row in tableWidget.selectedIndexes(): for row in tableWidget.selectedIndexes():
currentRow = row.row() currentRow = row.row()
msgid = tableWidget.item(currentRow, 3).data() msgid = sqlite3.Binary(tableWidget.item(currentRow, 3).data())
msgids.add(msgid) msgids.add(msgid)
# if not tableWidget.item(currentRow, 0).unread: # if not tableWidget.item(currentRow, 0).unread:
# modified += 1 # modified += 1
@ -2955,9 +2964,14 @@ class MyForm(settingsmixin.SMainWindow):
# for 1081 # for 1081
idCount = len(msgids) idCount = len(msgids)
# rowcount = # rowcount =
total_row_count = sqlExecuteChunked(
'''UPDATE inbox SET read=0 WHERE msgid IN ({0}) AND read=1''',
False, idCount, *msgids
)
if total_row_count < 1:
sqlExecuteChunked( sqlExecuteChunked(
'''UPDATE inbox SET read=0 WHERE msgid IN ({0}) AND read=1''', '''UPDATE inbox SET read=0 WHERE msgid IN ({0}) AND read=1''',
idCount, *msgids True, idCount, *msgids
) )
self.propagateUnreadCount() self.propagateUnreadCount()
@ -3038,8 +3052,12 @@ class MyForm(settingsmixin.SMainWindow):
currentInboxRow, column_from).address currentInboxRow, column_from).address
msgid = tableWidget.item(currentInboxRow, 3).data() msgid = tableWidget.item(currentInboxRow, 3).data()
queryreturn = sqlQuery( queryreturn = sqlQuery(
"SELECT message FROM inbox WHERE msgid=?", msgid "SELECT message FROM inbox WHERE msgid=?", sqlite3.Binary(msgid)
) or sqlQuery("SELECT message FROM sent WHERE ackdata=?", 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 != []: if queryreturn != []:
for row in queryreturn: for row in queryreturn:
messageAtCurrentInboxRow, = row messageAtCurrentInboxRow, = row
@ -3213,16 +3231,21 @@ class MyForm(settingsmixin.SMainWindow):
)[::-1]: )[::-1]:
for i in range(r.bottomRow() - r.topRow() + 1): for i in range(r.bottomRow() - r.topRow() + 1):
inventoryHashesToTrash.add( inventoryHashesToTrash.add(
tableWidget.item(r.topRow() + i, 3).data()) sqlite3.Binary(tableWidget.item(r.topRow() + i, 3).data()))
currentRow = r.topRow() currentRow = r.topRow()
self.getCurrentMessageTextedit().setText("") self.getCurrentMessageTextedit().setText("")
tableWidget.model().removeRows( tableWidget.model().removeRows(
r.topRow(), r.bottomRow() - r.topRow() + 1) r.topRow(), r.bottomRow() - r.topRow() + 1)
idCount = len(inventoryHashesToTrash) idCount = len(inventoryHashesToTrash)
total_row_count = sqlExecuteChunked(
("DELETE FROM inbox" if folder == "trash" or shifted else
"UPDATE inbox SET folder='trash', read=1") +
" WHERE msgid IN ({0})", False, idCount, *inventoryHashesToTrash)
if total_row_count < 1:
sqlExecuteChunked( sqlExecuteChunked(
("DELETE FROM inbox" if folder == "trash" or shifted else ("DELETE FROM inbox" if folder == "trash" or shifted else
"UPDATE inbox SET folder='trash', read=1") + "UPDATE inbox SET folder='trash', read=1") +
" WHERE msgid IN ({0})", idCount, *inventoryHashesToTrash) " WHERE msgid IN ({0})", True, idCount, *inventoryHashesToTrash)
tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1) tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1)
tableWidget.setUpdatesEnabled(True) tableWidget.setUpdatesEnabled(True)
self.propagateUnreadCount(folder) self.propagateUnreadCount(folder)
@ -3241,16 +3264,20 @@ class MyForm(settingsmixin.SMainWindow):
)[::-1]: )[::-1]:
for i in range(r.bottomRow() - r.topRow() + 1): for i in range(r.bottomRow() - r.topRow() + 1):
inventoryHashesToTrash.add( inventoryHashesToTrash.add(
tableWidget.item(r.topRow() + i, 3).data()) sqlite3.Binary(tableWidget.item(r.topRow() + i, 3).data()))
currentRow = r.topRow() currentRow = r.topRow()
self.getCurrentMessageTextedit().setText("") self.getCurrentMessageTextedit().setText("")
tableWidget.model().removeRows( tableWidget.model().removeRows(
r.topRow(), r.bottomRow() - r.topRow() + 1) r.topRow(), r.bottomRow() - r.topRow() + 1)
tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1) tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1)
idCount = len(inventoryHashesToTrash) idCount = len(inventoryHashesToTrash)
total_row_count = sqlExecuteChunked(
"UPDATE inbox SET folder='inbox' WHERE msgid IN({0})",
False, idCount, *inventoryHashesToTrash)
if total_row_count < 1:
sqlExecuteChunked( sqlExecuteChunked(
"UPDATE inbox SET folder='inbox' WHERE msgid IN({0})", "UPDATE inbox SET folder='inbox' WHERE msgid IN({0})",
idCount, *inventoryHashesToTrash) True, idCount, *inventoryHashesToTrash)
tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1) tableWidget.selectRow(0 if currentRow == 0 else currentRow - 1)
tableWidget.setUpdatesEnabled(True) tableWidget.setUpdatesEnabled(True)
self.propagateUnreadCount() self.propagateUnreadCount()
@ -3270,7 +3297,10 @@ class MyForm(settingsmixin.SMainWindow):
# Retrieve the message data out of the SQL database # Retrieve the message data out of the SQL database
msgid = tableWidget.item(currentInboxRow, 3).data() msgid = tableWidget.item(currentInboxRow, 3).data()
queryreturn = sqlQuery( 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 != []: if queryreturn != []:
for row in queryreturn: for row in queryreturn:
message, = row message, = row
@ -3301,10 +3331,16 @@ class MyForm(settingsmixin.SMainWindow):
while tableWidget.selectedIndexes() != []: while tableWidget.selectedIndexes() != []:
currentRow = tableWidget.selectedIndexes()[0].row() currentRow = tableWidget.selectedIndexes()[0].row()
ackdataToTrash = tableWidget.item(currentRow, 3).data() ackdataToTrash = tableWidget.item(currentRow, 3).data()
rowcount = sqlExecute(
"DELETE FROM sent" if folder == "trash" or shifted else
"UPDATE sent SET folder='trash'"
" WHERE ackdata = ?", sqlite3.Binary(ackdataToTrash)
)
if rowcount < 1:
sqlExecute( sqlExecute(
"DELETE FROM sent" if folder == "trash" or shifted else "DELETE FROM sent" if folder == "trash" or shifted else
"UPDATE sent SET folder='trash'" "UPDATE sent SET folder='trash'"
" WHERE ackdata = ?", ackdataToTrash " WHERE ackdata = CAST(? AS TEXT)", ackdataToTrash
) )
self.getCurrentMessageTextedit().setPlainText("") self.getCurrentMessageTextedit().setPlainText("")
tableWidget.removeRow(currentRow) tableWidget.removeRow(currentRow)
@ -3319,8 +3355,12 @@ class MyForm(settingsmixin.SMainWindow):
addressAtCurrentRow = self.ui.tableWidgetInbox.item( addressAtCurrentRow = self.ui.tableWidgetInbox.item(
currentRow, 0).data(QtCore.Qt.UserRole) currentRow, 0).data(QtCore.Qt.UserRole)
toRipe = decodeAddress(addressAtCurrentRow)[3] toRipe = decodeAddress(addressAtCurrentRow)[3]
sqlExecute( rowcount = sqlExecute(
'''UPDATE sent SET status='forcepow' WHERE toripe=? AND status='toodifficult' and folder='sent' ''', '''UPDATE sent SET status='forcepow' WHERE toripe=? AND status='toodifficult' and folder='sent' ''',
sqlite3.Binary(toRipe))
if rowcount < 1:
sqlExecute(
'''UPDATE sent SET status='forcepow' WHERE toripe=CAST(? AS TEXT) AND status='toodifficult' and folder='sent' ''',
toRipe) toRipe)
queryreturn = sqlQuery('''select ackdata FROM sent WHERE status='forcepow' ''') queryreturn = sqlQuery('''select ackdata FROM sent WHERE status='forcepow' ''')
for row in queryreturn: for row in queryreturn:
@ -4017,7 +4057,9 @@ class MyForm(settingsmixin.SMainWindow):
# menu option (Force Send) if it is. # menu option (Force Send) if it is.
if currentRow >= 0: if currentRow >= 0:
ackData = self.ui.tableWidgetInbox.item(currentRow, 3).data() 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: for row in queryreturn:
status, = row status, = row
if status == 'toodifficult': if status == 'toodifficult':
@ -4119,6 +4161,13 @@ class MyForm(settingsmixin.SMainWindow):
'''SELECT message FROM %s WHERE %s=?''' % ( '''SELECT message FROM %s WHERE %s=?''' % (
('sent', 'ackdata') if folder == 'sent' ('sent', 'ackdata') if folder == 'sent'
else ('inbox', 'msgid') else ('inbox', '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 ), msgid
) )
@ -4138,10 +4187,16 @@ class MyForm(settingsmixin.SMainWindow):
if tableWidget.item(currentRow, 0).unread is True: if tableWidget.item(currentRow, 0).unread is True:
self.updateUnreadStatus(tableWidget, currentRow, msgid) self.updateUnreadStatus(tableWidget, currentRow, msgid)
# propagate # propagate
if folder != 'sent' and sqlExecute( rowcount = sqlExecute(
'''UPDATE inbox SET read=1 WHERE msgid=? AND read=0''', '''UPDATE inbox SET read=1 WHERE msgid=? AND read=0''',
sqlite3.Binary(msgid)
)
if rowcount < 1:
rowcount = sqlExecute(
'''UPDATE inbox SET read=1 WHERE msgid=CAST(? AS TEXT) AND read=0''',
msgid msgid
) > 0: )
if folder != 'sent' and rowcount > 0:
self.propagateUnreadCount() self.propagateUnreadCount()
messageTextedit.setCurrentFont(QtGui.QFont()) messageTextedit.setCurrentFont(QtGui.QFont())

View File

@ -13,6 +13,7 @@ import inspect
import re import re
import sys import sys
import time import time
import sqlite3
from PyQt4 import QtGui from PyQt4 import QtGui
@ -201,13 +202,13 @@ class GatewayAccount(BMAccount):
ackdata = genAckPayload(streamNumber, stealthLevel) ackdata = genAckPayload(streamNumber, stealthLevel)
sqlExecute( sqlExecute(
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''',
'', sqlite3.Binary(''),
self.toAddress, self.toAddress,
ripe, sqlite3.Binary(ripe),
self.fromAddress, self.fromAddress,
self.subject, self.subject,
self.message, self.message,
ackdata, sqlite3.Binary(ackdata),
int(time.time()), # sentTime (this will never change) int(time.time()), # sentTime (this will never change)
int(time.time()), # lastActionTime int(time.time()), # lastActionTime
0, # sleepTill time. This will get set when the POW gets done. 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=''): def __init__(self, label=None, unread=False, timestamp=None, msgid=''):
super(MessageList_TimeWidget, self).__init__(label, unread) 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)) self.setData(TimestampRole, int(timestamp))
def __lt__(self, other): def __lt__(self, other):

View File

@ -12,6 +12,7 @@ import subprocess # nosec B404
import threading import threading
import time import time
from binascii import hexlify from binascii import hexlify
import sqlite3
import helper_bitcoin import helper_bitcoin
import helper_inbox import helper_inbox
@ -121,7 +122,7 @@ class objectProcessor(threading.Thread):
objectType, data = queues.objectProcessorQueue.get() objectType, data = queues.objectProcessorQueue.get()
sql.execute( sql.execute(
'INSERT INTO objectprocessorqueue VALUES (?,?)', 'INSERT INTO objectprocessorqueue VALUES (?,?)',
objectType, data) objectType, sqlite3.Binary(data))
numberOfObjectsThatWereInTheObjectProcessorQueue += 1 numberOfObjectsThatWereInTheObjectProcessorQueue += 1
logger.debug( logger.debug(
'Saved %s objects from the objectProcessorQueue to' 'Saved %s objects from the objectProcessorQueue to'
@ -143,9 +144,13 @@ class objectProcessor(threading.Thread):
if data[readPosition:] in state.ackdataForWhichImWatching: if data[readPosition:] in state.ackdataForWhichImWatching:
logger.info('This object is an acknowledgement bound for me.') logger.info('This object is an acknowledgement bound for me.')
del state.ackdataForWhichImWatching[data[readPosition:]] del state.ackdataForWhichImWatching[data[readPosition:]]
sqlExecute( rowcount = sqlExecute(
"UPDATE sent SET status='ackreceived', lastactiontime=?" "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(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
data[readPosition:], data[readPosition:],
@ -333,13 +338,13 @@ class objectProcessor(threading.Thread):
if queryreturn != []: if queryreturn != []:
logger.info( logger.info(
'We HAVE used this pubkey personally. Updating time.') 'We HAVE used this pubkey personally. Updating time.')
t = (address, addressVersion, dataToStore, t = (address, addressVersion, sqlite3.Binary(dataToStore),
int(time.time()), 'yes') int(time.time()), 'yes')
else: else:
logger.info( logger.info(
'We have NOT used this pubkey personally. Inserting' 'We have NOT used this pubkey personally. Inserting'
' in database.') ' in database.')
t = (address, addressVersion, dataToStore, t = (address, addressVersion, sqlite3.Binary(dataToStore),
int(time.time()), 'no') int(time.time()), 'no')
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t) sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
self.possibleNewPubkey(address) self.possibleNewPubkey(address)
@ -395,13 +400,13 @@ class objectProcessor(threading.Thread):
if queryreturn != []: if queryreturn != []:
logger.info( logger.info(
'We HAVE used this pubkey personally. Updating time.') 'We HAVE used this pubkey personally. Updating time.')
t = (address, addressVersion, dataToStore, t = (address, addressVersion, sqlite3.Binary(dataToStore),
int(time.time()), 'yes') int(time.time()), 'yes')
else: else:
logger.info( logger.info(
'We have NOT used this pubkey personally. Inserting' 'We have NOT used this pubkey personally. Inserting'
' in database.') ' in database.')
t = (address, addressVersion, dataToStore, t = (address, addressVersion, sqlite3.Binary(dataToStore),
int(time.time()), 'no') int(time.time()), 'no')
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t) sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
self.possibleNewPubkey(address) self.possibleNewPubkey(address)
@ -592,7 +597,7 @@ class objectProcessor(threading.Thread):
'''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', '''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
fromAddress, fromAddress,
sendersAddressVersionNumber, sendersAddressVersionNumber,
decryptedData[:endOfThePublicKeyPosition], sqlite3.Binary(decryptedData[:endOfThePublicKeyPosition]),
int(time.time()), int(time.time()),
'yes') 'yes')
@ -929,7 +934,7 @@ class objectProcessor(threading.Thread):
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
fromAddress, fromAddress,
sendersAddressVersion, sendersAddressVersion,
decryptedData[:endOfPubkeyPosition], sqlite3.Binary(decryptedData[:endOfPubkeyPosition]),
int(time.time()), int(time.time()),
'yes') 'yes')

View File

@ -22,6 +22,7 @@ It resends messages when there has been no response:
import gc import gc
import os import os
import time import time
import sqlite3
import queues import queues
import state import state
@ -177,9 +178,13 @@ class singleCleaner(StoppableThread):
'It has been a long time and we haven\'t heard an acknowledgement' 'It has been a long time and we haven\'t heard an acknowledgement'
' to our msg. Sending again.' ' to our msg. Sending again.'
) )
rowcount = sqlExecute(
"UPDATE sent SET status = 'msgqueued'"
" WHERE ackdata = ? AND folder = 'sent'", sqlite3.Binary(ackdata))
if rowcount < 1:
sqlExecute( sqlExecute(
"UPDATE sent SET status = 'msgqueued'" "UPDATE sent SET status = 'msgqueued'"
" WHERE ackdata = ? AND folder = 'sent'", ackdata) " WHERE ackdata = CAST(? AS TEXT) AND folder = 'sent'", ackdata)
queues.workerQueue.put(('sendmessage', '')) queues.workerQueue.put(('sendmessage', ''))
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', 'updateStatusBar',

View File

@ -11,6 +11,7 @@ import time
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from struct import pack from struct import pack
from subprocess import call # nosec from subprocess import call # nosec
import sqlite3
import defaults import defaults
import helper_inbox import helper_inbox
@ -107,9 +108,14 @@ class singleWorker(StoppableThread):
# attach legacy header, always constant (msg/1/1) # attach legacy header, always constant (msg/1/1)
newack = '\x00\x00\x00\x02\x01\x01' + oldack newack = '\x00\x00\x00\x02\x01\x01' + oldack
state.ackdataForWhichImWatching[newack] = 0 state.ackdataForWhichImWatching[newack] = 0
sqlExecute( rowcount = sqlExecute(
'''UPDATE sent SET ackdata=? WHERE ackdata=? AND folder = 'sent' ''', '''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] del state.ackdataForWhichImWatching[oldack]
@ -578,11 +584,18 @@ class singleWorker(StoppableThread):
)) ))
continue continue
if not sqlExecute( rowcount = sqlExecute(
'''UPDATE sent SET status='doingbroadcastpow' ''' '''UPDATE sent SET status='doingbroadcastpow' '''
''' WHERE ackdata=? AND status='broadcastqueued' ''' ''' WHERE ackdata=? AND status='broadcastqueued' '''
''' AND folder='sent' ''', ''' 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 continue
# At this time these pubkeys are 65 bytes long # At this time these pubkeys are 65 bytes long
@ -703,10 +716,16 @@ class singleWorker(StoppableThread):
# Update the status of the message in the 'sent' table to have # Update the status of the message in the 'sent' table to have
# a 'broadcastsent' status # a 'broadcastsent' status
sqlExecute( rowcount = sqlExecute(
'''UPDATE sent SET msgid=?, status=?, lastactiontime=? ''' '''UPDATE sent SET msgid=?, status=?, lastactiontime=? '''
''' WHERE ackdata=? AND folder='sent' ''', ''' 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): def sendMsg(self):
@ -1065,9 +1084,14 @@ class singleWorker(StoppableThread):
if cond1 or cond2: if cond1 or cond2:
# The demanded difficulty is more than # The demanded difficulty is more than
# we are willing to do. # we are willing to do.
sqlExecute( rowcount = sqlExecute(
'''UPDATE sent SET status='toodifficult' ''' '''UPDATE sent SET status='toodifficult' '''
''' WHERE ackdata=? AND folder='sent' ''', ''' WHERE ackdata=? AND folder='sent' ''',
sqlite3.Binary(ackdata))
if rowcount < 1:
sqlExecute(
'''UPDATE sent SET status='toodifficult' '''
''' WHERE ackdata=CAST(? AS TEXT) AND folder='sent' ''',
ackdata) ackdata)
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
@ -1231,8 +1255,13 @@ class singleWorker(StoppableThread):
) )
except: # noqa:E722 except: # noqa:E722
self.logger.warning("highlevelcrypto.encrypt didn't work") self.logger.warning("highlevelcrypto.encrypt didn't work")
sqlExecute( rowcount = sqlExecute(
'''UPDATE sent SET status='badkey' WHERE ackdata=? AND folder='sent' ''', '''UPDATE sent SET status='badkey' WHERE ackdata=? AND folder='sent' ''',
sqlite3.Binary(ackdata)
)
if rowcount < 1:
sqlExecute(
'''UPDATE sent SET status='badkey' WHERE ackdata=CAST(? AS TEXT) AND folder='sent' ''',
ackdata ackdata
) )
queues.UISignalQueue.put(( queues.UISignalQueue.put((
@ -1337,10 +1366,17 @@ class singleWorker(StoppableThread):
newStatus = 'msgsent' newStatus = 'msgsent'
# wait 10% past expiration # wait 10% past expiration
sleepTill = int(time.time() + TTL * 1.1) sleepTill = int(time.time() + TTL * 1.1)
sqlExecute( rowcount = sqlExecute(
'''UPDATE sent SET msgid=?, status=?, retrynumber=?, ''' '''UPDATE sent SET msgid=?, status=?, retrynumber=?, '''
''' sleeptill=?, lastactiontime=? WHERE ackdata=? AND folder='sent' ''', ''' sleeptill=?, lastactiontime=? WHERE ackdata=? AND folder='sent' ''',
inventoryHash, newStatus, retryNumber + 1, 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 sleepTill, int(time.time()), ackdata
) )

View File

@ -12,6 +12,7 @@ import threading
import time import time
from email.header import decode_header from email.header import decode_header
from email.parser import Parser from email.parser import Parser
import sqlite3
import queues import queues
from addresses import decodeAddress from addresses import decodeAddress
@ -88,13 +89,13 @@ class smtpServerPyBitmessage(smtpd.SMTPServer):
ackdata = genAckPayload(streamNumber, stealthLevel) ackdata = genAckPayload(streamNumber, stealthLevel)
sqlExecute( sqlExecute(
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''',
'', sqlite3.Binary(''),
toAddress, toAddress,
ripe, sqlite3.Binary(ripe),
fromAddress, fromAddress,
subject, subject,
message, message,
ackdata, sqlite3.Binary(ackdata),
int(time.time()), # sentTime (this will never change) int(time.time()), # sentTime (this will never change)
int(time.time()), # lastActionTime int(time.time()), # lastActionTime
0, # sleepTill time. This will get set when the POW gets done. 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''' '''INSERT INTO subscriptions VALUES'''
'''('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''') '''('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''')
self.cur.execute( 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('version','11')''')
self.cur.execute('''INSERT INTO settings VALUES('lastvacuumtime',?)''', ( self.cur.execute('''INSERT INTO settings VALUES('lastvacuumtime',?)''', (
int(time.time()),)) int(time.time()),))

View File

@ -1,12 +1,15 @@
"""Helper Inbox performs inbox messages related operations""" """Helper Inbox performs inbox messages related operations"""
import sqlite3
import queues import queues
from helper_sql import sqlExecute, sqlQuery from helper_sql import sqlExecute, sqlQuery
def insert(t): def insert(t):
"""Perform an insert into the "inbox" table""" """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 # shouldn't emit changedInboxUnread and displayNewInboxMessage
# at the same time # at the same time
# queues.UISignalQueue.put(('changedInboxUnread', None)) # queues.UISignalQueue.put(('changedInboxUnread', None))
@ -14,22 +17,31 @@ def insert(t):
def trash(msgid): def trash(msgid):
"""Mark a message in the `inbox` as `trash`""" """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)) queues.UISignalQueue.put(('removeInboxRowByMsgid', msgid))
def delete(ack_data): def delete(ack_data):
"""Permanent delete message from trash""" """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): def undeleteMessage(msgid):
"""Undelte the message""" """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): def isMessageAlreadyInInbox(sigHash):
"""Check for previous instances of this message""" """Check for previous instances of this message"""
queryReturn = sqlQuery( 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 return queryReturn[0][0] != 0

View File

@ -4,6 +4,7 @@ Insert values into sent table
import time import time
import uuid import uuid
import sqlite3
from addresses import decodeAddress from addresses import decodeAddress
from bmconfigparser import config from bmconfigparser import config
from helper_ackPayload import genAckPayload 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') 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, sentTime, lastActionTime, sleeptill, status, retryNumber, folder,
encoding, ttl) encoding, ttl)
@ -50,13 +51,19 @@ def insert(msgid=None, toAddress='[Broadcast subscribers]', fromAddress=None, su
def delete(ack_data): def delete(ack_data):
"""Perform Delete query""" """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): def retrieve_message_details(ack_data):
"""Retrieving Message details""" """Retrieving Message details"""
data = sqlQuery( 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 return data
@ -64,6 +71,10 @@ def retrieve_message_details(ack_data):
def trash(ackdata): def trash(ackdata):
"""Mark a message in the `sent` as `trash`""" """Mark a message in the `sent` as `trash`"""
rowcount = sqlExecute( 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 return rowcount

View File

@ -61,7 +61,7 @@ def sqlQuery(sql_statement, *args):
return queryreturn return queryreturn
def sqlExecuteChunked(sql_statement, idCount, *args): def sqlExecuteChunked(sql_statement, as_text, idCount, *args):
"""Execute chunked SQL statement to avoid argument limit""" """Execute chunked SQL statement to avoid argument limit"""
# SQLITE_MAX_VARIABLE_NUMBER, # SQLITE_MAX_VARIABLE_NUMBER,
# unfortunately getting/setting isn't exposed to python # unfortunately getting/setting isn't exposed to python
@ -80,6 +80,11 @@ def sqlExecuteChunked(sql_statement, idCount, *args):
chunk_slice = args[ chunk_slice = args[
i:i + sqlExecuteChunked.chunkSize - (len(args) - idCount) i:i + sqlExecuteChunked.chunkSize - (len(args) - idCount)
] ]
if as_text:
sqlSubmitQueue.put(
sql_statement.format(','.join('CAST(? AS TEXT)' * len(chunk_slice)))
)
else:
sqlSubmitQueue.put( sqlSubmitQueue.put(
sql_statement.format(','.join('?' * len(chunk_slice))) sql_statement.format(','.join('?' * len(chunk_slice)))
) )

View File

@ -12,6 +12,7 @@ import sys
import time import time
from binascii import hexlify from binascii import hexlify
from struct import Struct, pack, unpack from struct import Struct, pack, unpack
import sqlite3
import defaults import defaults
import highlevelcrypto import highlevelcrypto
@ -558,7 +559,7 @@ def decryptAndCheckPubkeyPayload(data, address):
hexlify(pubSigningKey), hexlify(pubEncryptionKey) 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) sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
return 'successful' return 'successful'
except varintDecodeError: 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. # always use the inventoryLock OUTSIDE of the sqlLock.
with SqlBulkExecute() as sql: with SqlBulkExecute() as sql:
for objectHash, value in self._inventory.items(): for objectHash, value in self._inventory.items():
value = [value[0], value[1], sqlite3.Binary(value[2]), value[3], sqlite3.Binary(value[4])]
sql.execute( sql.execute(
'INSERT INTO inventory VALUES (?, ?, ?, ?, ?, ?)', 'INSERT INTO inventory VALUES (?, ?, ?, ?, ?, ?)',
sqlite3.Binary(objectHash), *value) sqlite3.Binary(objectHash), *value)

View File

@ -15,6 +15,7 @@ import sys
import threading import threading
import time import time
import unittest import unittest
import sqlite3
import protocol import protocol
import state import state
@ -345,12 +346,18 @@ class TestCore(unittest.TestCase):
subject=subject, message=message subject=subject, message=message
) )
queryreturn = sqlQuery( 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 '', '') self.assertNotEqual(queryreturn[0][0] if queryreturn else '', '')
column_type = sqlQuery( column_type = sqlQuery(
'''select typeof(msgid) from sent where ackdata=?''', result) '''select typeof(msgid) from sent where ackdata=?''', sqlite3.Binary(result))
self.assertEqual(column_type[0][0] if column_type else '', 'text') 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') @unittest.skipIf(frozen, 'not packed test_pattern into the bundle')
def test_old_knownnodes_pickle(self): def test_old_knownnodes_pickle(self):

View File

@ -1,6 +1,7 @@
"""Test cases for helper_sql""" """Test cases for helper_sql"""
import unittest import unittest
import sqlite3
try: try:
# Python 3 # Python 3
@ -49,6 +50,12 @@ class TestHelperSql(unittest.TestCase):
rowcount = helper_sql.sqlExecute( rowcount = helper_sql.sqlExecute(
"UPDATE sent SET status = 'msgqueued'" "UPDATE sent SET status = 'msgqueued'"
"WHERE ackdata = ? AND folder = 'sent'", "WHERE ackdata = ? AND folder = 'sent'",
sqlite3.Binary("1710652313"),
)
if rowcount < 0:
rowcount = helper_sql.sqlExecute(
"UPDATE sent SET status = 'msgqueued'"
"WHERE ackdata = CAST(? AS TEXT) AND folder = 'sent'",
"1710652313", "1710652313",
) )
self.assertEqual(mock_sqlsubmitqueue_put.call_count, 3) self.assertEqual(mock_sqlsubmitqueue_put.call_count, 3)
@ -80,7 +87,7 @@ class TestHelperSql(unittest.TestCase):
for i in range(0, ID_COUNT): for i in range(0, ID_COUNT):
args.append("arg{}".format(i)) args.append("arg{}".format(i))
total_row_count_return = helper_sql.sqlExecuteChunked( 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.assertEqual(TOTAL_ROW_COUNT, total_row_count_return)
self.assertTrue(mock_sqlsubmitqueue_put.called) self.assertTrue(mock_sqlsubmitqueue_put.called)
@ -97,7 +104,7 @@ class TestHelperSql(unittest.TestCase):
for i in range(0, ID_COUNT): for i in range(0, ID_COUNT):
args.append("arg{}".format(i)) args.append("arg{}".format(i))
total_row_count = helper_sql.sqlExecuteChunked( 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.assertEqual(total_row_count, 0)
self.assertFalse(mock_sqlsubmitqueue_put.called) self.assertFalse(mock_sqlsubmitqueue_put.called)
@ -112,7 +119,7 @@ class TestHelperSql(unittest.TestCase):
ID_COUNT = 12 ID_COUNT = 12
args = ["args0", "arg1"] args = ["args0", "arg1"]
total_row_count = helper_sql.sqlExecuteChunked( 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.assertEqual(total_row_count, 0)
self.assertFalse(mock_sqlsubmitqueue_put.called) self.assertFalse(mock_sqlsubmitqueue_put.called)