Don't store padding in db
Trim padding when storing and repad on the fly when retrieving.
This commit is contained in:
parent
c0e0d61dbf
commit
4e27e8d60b
|
@ -557,10 +557,19 @@ pub fn insert_message(
|
|||
if recent_posts >= RATE_LIMIT_POSTS {
|
||||
return Err(warp::reject::custom(Error::RateLimited));
|
||||
}
|
||||
|
||||
// Don't store useless padding; we'll repad (since it's needed for signature verification) when
|
||||
// we retrieve.
|
||||
let size = data.len();
|
||||
let trimmed = match data.iter().rposition(|&c| c != 0u8) {
|
||||
Some(last) => &data[0..last+1],
|
||||
None => &data
|
||||
};
|
||||
|
||||
// Insert the message
|
||||
let message = match tx.prepare_cached("INSERT INTO messages (room, user, data, signature) VALUES (?, ?, ?, ?) RETURNING *")
|
||||
let message = match tx.prepare_cached("INSERT INTO messages (room, user, data, data_size, signature) VALUES (?, ?, ?, ?, ?) RETURNING *")
|
||||
.map_err(db_error)?
|
||||
.query_row(params![room.id, user.id, data, signature], OldMessage::from_row) {
|
||||
.query_row(params![room.id, user.id, trimmed, size, signature], OldMessage::from_row) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
error!("Couldn't insert message: {}.", e);
|
||||
|
@ -670,7 +679,7 @@ pub fn delete_message(
|
|||
|
||||
require_authorization(conn, user, room, auth_req)?;
|
||||
|
||||
let mut del_st = conn.prepare_cached("UPDATE messages SET data = NULL, signature = NULL WHERE id = ?")
|
||||
let mut del_st = conn.prepare_cached("UPDATE messages SET data = NULL, data_size = NULL, signature = NULL WHERE id = ?")
|
||||
.map_err(db_error)?;
|
||||
|
||||
if let Err(e) = del_st.execute(params![id]) {
|
||||
|
@ -879,7 +888,7 @@ pub async fn ban(session_id: &str, delete_all: bool, user: &User, room: &Room) -
|
|||
let mut posts_removed = 0;
|
||||
let mut files_removed = 0;
|
||||
if delete_all {
|
||||
posts_removed += match tx.prepare_cached("UPDATE messages SET data = NULL, signature = NULL WHERE room = ? AND user = ?")
|
||||
posts_removed += match tx.prepare_cached("UPDATE messages SET data = NULL, data_size = NULL, signature = NULL WHERE room = ? AND user = ?")
|
||||
.map_err(db_error)?
|
||||
.execute(params![room.id, userid]) {
|
||||
Ok(count) => count,
|
||||
|
|
|
@ -56,7 +56,8 @@ pub struct OldMessage {
|
|||
|
||||
impl OldMessage {
|
||||
pub fn from_row(row: &rusqlite::Row) -> Result<OldMessage, rusqlite::Error> {
|
||||
let data: Option<Vec<u8>> = row.get(row.column_index("data")?)?;
|
||||
let mut data: Option<Vec<u8>> = row.get(row.column_index("data")?)?;
|
||||
repad(&mut data, row.get::<_, Option<usize>>(row.column_index("data_size")?)?);
|
||||
let session_id = match row.column_index("session_id") {
|
||||
Ok(index) => Some(row.get(index)?),
|
||||
Err(_) => None
|
||||
|
@ -98,9 +99,18 @@ pub struct Message {
|
|||
pub deleted: Option<bool>,
|
||||
}
|
||||
|
||||
fn repad(data: &mut Option<Vec<u8>>, size: Option<usize>) {
|
||||
if let Some(size) = size {
|
||||
if data.is_some() && data.as_ref().unwrap().len() < size {
|
||||
data.as_mut().unwrap().resize(size, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn from_row(row: &rusqlite::Row) -> Result<Message, rusqlite::Error> {
|
||||
let data: Option<Vec<u8>> = row.get(row.column_index("data")?)?;
|
||||
let mut data: Option<Vec<u8>> = row.get(row.column_index("data")?)?;
|
||||
repad(&mut data, row.get::<_, Option<usize>>(row.column_index("data_size")?)?);
|
||||
let deleted = if data.is_none() { Some(true) } else { None };
|
||||
let session_id = match row.column_index("session_id") {
|
||||
Ok(index) => Some(row.get(index)?),
|
||||
|
|
|
@ -66,7 +66,8 @@ CREATE TABLE messages (
|
|||
posted FLOAT NOT NULL DEFAULT ((julianday('now') - 2440587.5)*86400.0), /* unix epoch */
|
||||
edited FLOAT,
|
||||
updated INTEGER NOT NULL DEFAULT 0, /* set to the room's `updates` counter when posted/edited/deleted */
|
||||
data BLOB, /* Actual message content; set to null to delete a message */
|
||||
data BLOB, /* Actual message content, not including trailing padding; set to null to delete a message */
|
||||
data_size INTEGER, /* The message size, including trailing padding (needed because the signature is over the padded data) */
|
||||
signature BLOB /* Signature of `data` by `public_key`; set to null when deleting a message */
|
||||
);
|
||||
CREATE INDEX messages_room ON messages(room, posted);
|
||||
|
@ -184,7 +185,7 @@ SELECT messages.*, users.session_id FROM messages JOIN users ON messages.user =
|
|||
-- View of `messages` that is useful for manually inspecting table contents by only returning the
|
||||
-- length (rather than raw bytes) for data/signature.
|
||||
CREATE VIEW message_metadata AS
|
||||
SELECT id, room, user, session_id, posted, edited, updated, length(data) AS data_length, length(signature) as signature_length
|
||||
SELECT id, room, user, session_id, posted, edited, updated, length(data) AS data_unpadded, data_size, length(signature) as signature_length
|
||||
FROM message_details;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue