mirror of
https://github.com/chatmail/core.git
synced 2026-05-17 05:46:30 +03:00
fix and improve sql escaping
This commit is contained in:
@@ -260,14 +260,15 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id(
|
|||||||
if sql::execute(
|
if sql::execute(
|
||||||
context,
|
context,
|
||||||
&context.sql,
|
&context.sql,
|
||||||
"INSERT INTO chats (type, name, param, blocked, grpid) VALUES(?, ?, ?, ?, ?)",
|
format!(
|
||||||
params![
|
"INSERT INTO chats (type, name, param, blocked, grpid) VALUES({}, '{}', '{}', {}, '{}')",
|
||||||
100,
|
100,
|
||||||
as_str(chat_name),
|
as_str(chat_name),
|
||||||
if contact_id == 1 { "K=1" } else { "" },
|
if contact_id == 1 { "K=1" } else { "" },
|
||||||
create_blocked,
|
create_blocked,
|
||||||
as_str((*contact).addr),
|
as_str((*contact).addr),
|
||||||
],
|
),
|
||||||
|
params![],
|
||||||
) {
|
) {
|
||||||
chat_id = sql::get_rowid(
|
chat_id = sql::get_rowid(
|
||||||
context,
|
context,
|
||||||
@@ -280,8 +281,8 @@ pub unsafe fn dc_create_or_lookup_nchat_by_contact_id(
|
|||||||
sql::execute(
|
sql::execute(
|
||||||
context,
|
context,
|
||||||
&context.sql,
|
&context.sql,
|
||||||
"INSERT INTO chats_contacts (chat_id, contact_id) VALUES(?, ?)",
|
format!("INSERT INTO chats_contacts (chat_id, contact_id) VALUES({}, {})", chat_id, contact_id),
|
||||||
params![chat_id, contact_id],
|
params![],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1766,8 +1767,12 @@ pub unsafe fn dc_set_chat_name(
|
|||||||
if sql::execute(
|
if sql::execute(
|
||||||
context,
|
context,
|
||||||
&context.sql,
|
&context.sql,
|
||||||
"UPDATE chats SET name=? WHERE id={};",
|
format!(
|
||||||
params![as_str(new_name), chat_id as i32],
|
"UPDATE chats SET name='{}' WHERE id={};",
|
||||||
|
as_str(new_name),
|
||||||
|
chat_id as i32
|
||||||
|
),
|
||||||
|
params![],
|
||||||
) {
|
) {
|
||||||
if dc_param_get_int((*chat).param, 'U' as i32, 0i32) == 0i32 {
|
if dc_param_get_int((*chat).param, 'U' as i32, 0i32) == 0i32 {
|
||||||
(*msg).type_0 = 10i32;
|
(*msg).type_0 = 10i32;
|
||||||
@@ -1909,8 +1914,11 @@ pub unsafe fn dc_forward_msgs(
|
|||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
.query_map(
|
.query_map(
|
||||||
"SELECT id FROM msgs WHERE id IN(?) ORDER BY timestamp,id",
|
format!(
|
||||||
params![as_str(idsstr)],
|
"SELECT id FROM msgs WHERE id IN({}) ORDER BY timestamp,id",
|
||||||
|
as_str(idsstr)
|
||||||
|
),
|
||||||
|
params![],
|
||||||
|row| row.get::<_, i32>(0),
|
|row| row.get::<_, i32>(0),
|
||||||
|ids| {
|
|ids| {
|
||||||
for id in ids {
|
for id in ids {
|
||||||
|
|||||||
@@ -27,19 +27,14 @@ pub unsafe fn dc_get_chatlist<'a>(
|
|||||||
query_str: *const libc::c_char,
|
query_str: *const libc::c_char,
|
||||||
query_id: uint32_t,
|
query_id: uint32_t,
|
||||||
) -> *mut dc_chatlist_t<'a> {
|
) -> *mut dc_chatlist_t<'a> {
|
||||||
let mut success: libc::c_int = 0i32;
|
let obj = dc_chatlist_new(context);
|
||||||
let obj: *mut dc_chatlist_t = dc_chatlist_new(context);
|
|
||||||
|
|
||||||
if !(0 == dc_chatlist_load_from_db(obj, listflags, query_str, query_id)) {
|
if 0 != dc_chatlist_load_from_db(obj, listflags, query_str, query_id) {
|
||||||
success = 1i32
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 != success {
|
dc_chatlist_unref(obj);
|
||||||
return obj;
|
return 0 as *mut dc_chatlist_t;
|
||||||
} else {
|
|
||||||
dc_chatlist_unref(obj);
|
|
||||||
return 0 as *mut dc_chatlist_t;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,8 +117,6 @@ unsafe fn dc_chatlist_load_from_db(
|
|||||||
query__: *const libc::c_char,
|
query__: *const libc::c_char,
|
||||||
query_contact_id: u32,
|
query_contact_id: u32,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
//clock_t start = clock();
|
|
||||||
|
|
||||||
if chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32 {
|
if chatlist.is_null() || (*chatlist).magic != 0xc4a71157u32 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -142,15 +135,27 @@ unsafe fn dc_chatlist_load_from_db(
|
|||||||
// for the deaddrop, however, they should really be hidden, however, _currently_ the deaddrop is not
|
// for the deaddrop, however, they should really be hidden, however, _currently_ the deaddrop is not
|
||||||
// shown at all permanent in the chatlist.
|
// shown at all permanent in the chatlist.
|
||||||
|
|
||||||
let process_fn = |row: &rusqlite::Row| {
|
let process_row = |row: &rusqlite::Row| Ok((row.get(0)?, row.get(1)?));
|
||||||
dc_array_add_id((*chatlist).chatNlastmsg_ids, row.get(0)?);
|
|
||||||
dc_array_add_id((*chatlist).chatNlastmsg_ids, row.get(1)?);
|
let process_rows = |rows: rusqlite::MappedRows<_>| {
|
||||||
|
for row in rows {
|
||||||
|
let (id1, id2) = row?;
|
||||||
|
|
||||||
|
dc_array_add_id((*chatlist).chatNlastmsg_ids, id1);
|
||||||
|
dc_array_add_id((*chatlist).chatNlastmsg_ids, id2);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
let success =
|
// nb: the query currently shows messages from blocked contacts in groups.
|
||||||
if query_contact_id != 0 {
|
// however, for normal-groups, this is okay as the message is also returned by dc_get_chat_msgs()
|
||||||
(*chatlist).context.sql.query_map(
|
// (otherwise it would be hard to follow conversations, wa and tg do the same)
|
||||||
|
// for the deaddrop, however, they should really be hidden, however, _currently_ the deaddrop is not
|
||||||
|
// shown at all permanent in the chatlist.
|
||||||
|
|
||||||
|
let success = if query_contact_id != 0 {
|
||||||
|
// show chats shared with a given contact
|
||||||
|
(*chatlist).context.sql.query_map(
|
||||||
"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \
|
"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \
|
||||||
ON c.id=m.chat_id \
|
ON c.id=m.chat_id \
|
||||||
AND m.timestamp=( SELECT MAX(timestamp) \
|
AND m.timestamp=( SELECT MAX(timestamp) \
|
||||||
@@ -159,74 +164,67 @@ unsafe fn dc_chatlist_load_from_db(
|
|||||||
AND c.blocked=0 AND c.id IN(SELECT chat_id FROM chats_contacts WHERE contact_id=?) \
|
AND c.blocked=0 AND c.id IN(SELECT chat_id FROM chats_contacts WHERE contact_id=?) \
|
||||||
GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
|
GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
|
||||||
params![query_contact_id as i32],
|
params![query_contact_id as i32],
|
||||||
process_fn,
|
process_row,
|
||||||
|res| res.collect::<rusqlite::Result<Vec<_>>>().map_err(Into::into),
|
process_rows,
|
||||||
)
|
)
|
||||||
} else if 0 != listflags & 0x1 {
|
} else if 0 != listflags & 0x1 {
|
||||||
|
// show archived chats
|
||||||
|
(*chatlist).context.sql.query_map(
|
||||||
|
"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \
|
||||||
|
ON c.id=m.chat_id \
|
||||||
|
AND m.timestamp=( SELECT MAX(timestamp) \
|
||||||
|
FROM msgs WHERE chat_id=c.id \
|
||||||
|
AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \
|
||||||
|
AND c.blocked=0 AND c.archived=1 GROUP BY c.id \
|
||||||
|
ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
|
||||||
|
params![],
|
||||||
|
process_row,
|
||||||
|
process_rows,
|
||||||
|
)
|
||||||
|
} else if query__.is_null() {
|
||||||
|
// show normal chatlist
|
||||||
|
if 0 == listflags & 0x2 {
|
||||||
|
let last_deaddrop_fresh_msg_id = get_last_deaddrop_fresh_msg((*chatlist).context);
|
||||||
|
if last_deaddrop_fresh_msg_id > 0 {
|
||||||
|
dc_array_add_id((*chatlist).chatNlastmsg_ids, 1);
|
||||||
|
dc_array_add_id((*chatlist).chatNlastmsg_ids, last_deaddrop_fresh_msg_id);
|
||||||
|
}
|
||||||
|
add_archived_link_item = 1;
|
||||||
|
}
|
||||||
|
(*chatlist).context.sql.query_map(
|
||||||
|
"SELECT c.id, m.id FROM chats c \
|
||||||
|
LEFT JOIN msgs m \
|
||||||
|
ON c.id=m.chat_id \
|
||||||
|
AND m.timestamp=( SELECT MAX(timestamp) \
|
||||||
|
FROM msgs WHERE chat_id=c.id \
|
||||||
|
AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \
|
||||||
|
AND c.blocked=0 AND c.archived=0 \
|
||||||
|
GROUP BY c.id \
|
||||||
|
ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
|
||||||
|
params![],
|
||||||
|
process_row,
|
||||||
|
process_rows,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
let query = to_string(query__).trim().to_string();
|
||||||
|
if query.is_empty() {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
let strLikeCmd = format!("%{}%", query);
|
||||||
(*chatlist).context.sql.query_map(
|
(*chatlist).context.sql.query_map(
|
||||||
"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \
|
"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \
|
||||||
ON c.id=m.chat_id \
|
ON c.id=m.chat_id \
|
||||||
AND m.timestamp=( SELECT MAX(timestamp) \
|
AND m.timestamp=( SELECT MAX(timestamp) \
|
||||||
FROM msgs WHERE chat_id=c.id \
|
FROM msgs WHERE chat_id=c.id \
|
||||||
AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \
|
AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \
|
||||||
AND c.blocked=0 AND c.archived=1 GROUP BY c.id \
|
AND c.blocked=0 AND c.name LIKE ? \
|
||||||
ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
|
GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
|
||||||
params![],
|
params![strLikeCmd],
|
||||||
process_fn,
|
process_row,
|
||||||
|res| {
|
process_rows,
|
||||||
res.collect::<rusqlite::Result<Vec<_>>>()
|
|
||||||
.map_err(Into::into)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
} else if query__.is_null() {
|
}
|
||||||
if 0 == listflags & 0x2 {
|
};
|
||||||
let last_deaddrop_fresh_msg_id = get_last_deaddrop_fresh_msg((*chatlist).context);
|
|
||||||
if last_deaddrop_fresh_msg_id > 0 {
|
|
||||||
dc_array_add_id((*chatlist).chatNlastmsg_ids, 1);
|
|
||||||
dc_array_add_id((*chatlist).chatNlastmsg_ids, last_deaddrop_fresh_msg_id);
|
|
||||||
}
|
|
||||||
add_archived_link_item = 1;
|
|
||||||
}
|
|
||||||
(*chatlist).context.sql.query_map(
|
|
||||||
"SELECT c.id, m.id FROM chats c \
|
|
||||||
LEFT JOIN msgs m \
|
|
||||||
ON c.id=m.chat_id \
|
|
||||||
AND m.timestamp=( SELECT MAX(timestamp) \
|
|
||||||
FROM msgs WHERE chat_id=c.id \
|
|
||||||
AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \
|
|
||||||
AND c.blocked=0 AND c.archived=0 \
|
|
||||||
GROUP BY c.id \
|
|
||||||
ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
|
|
||||||
params![],
|
|
||||||
process_fn,
|
|
||||||
|res| {
|
|
||||||
res.collect::<rusqlite::Result<Vec<_>>>()
|
|
||||||
.map_err(Into::into)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let query = to_string(query__).trim().to_string();
|
|
||||||
if query.is_empty() {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
let strLikeCmd = format!("%{}%", query);
|
|
||||||
(*chatlist).context.sql.query_map(
|
|
||||||
"SELECT c.id, m.id FROM chats c LEFT JOIN msgs m \
|
|
||||||
ON c.id=m.chat_id \
|
|
||||||
AND m.timestamp=( SELECT MAX(timestamp) \
|
|
||||||
FROM msgs WHERE chat_id=c.id \
|
|
||||||
AND (hidden=0 OR (hidden=1 AND state=19))) WHERE c.id>9 \
|
|
||||||
AND c.blocked=0 AND c.name LIKE ? \
|
|
||||||
GROUP BY c.id ORDER BY IFNULL(m.timestamp,0) DESC, m.id DESC;",
|
|
||||||
params![strLikeCmd],
|
|
||||||
process_fn,
|
|
||||||
|res| {
|
|
||||||
res.collect::<rusqlite::Result<Vec<_>>>()
|
|
||||||
.map_err(Into::into)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if 0 != add_archived_link_item && dc_get_archived_cnt((*chatlist).context) > 0 {
|
if 0 != add_archived_link_item && dc_get_archived_cnt((*chatlist).context) > 0 {
|
||||||
if dc_array_get_cnt((*chatlist).chatNlastmsg_ids) == 0 && 0 != listflags & 0x4 {
|
if dc_array_get_cnt((*chatlist).chatNlastmsg_ids) == 0 && 0 != listflags & 0x4 {
|
||||||
@@ -236,9 +234,18 @@ unsafe fn dc_chatlist_load_from_db(
|
|||||||
dc_array_add_id((*chatlist).chatNlastmsg_ids, 6 as uint32_t);
|
dc_array_add_id((*chatlist).chatNlastmsg_ids, 6 as uint32_t);
|
||||||
dc_array_add_id((*chatlist).chatNlastmsg_ids, 0 as uint32_t);
|
dc_array_add_id((*chatlist).chatNlastmsg_ids, 0 as uint32_t);
|
||||||
}
|
}
|
||||||
(*chatlist).cnt = dc_array_get_cnt((*chatlist).chatNlastmsg_ids).wrapping_div(2);
|
(*chatlist).cnt = dc_array_get_cnt((*chatlist).chatNlastmsg_ids) / 2;
|
||||||
|
|
||||||
success.is_ok() as libc::c_int
|
match success {
|
||||||
|
Ok(_) => 1,
|
||||||
|
Err(err) => {
|
||||||
|
error!(
|
||||||
|
(*chatlist).context,
|
||||||
|
0, "chatlist: failed to load from database: {:?}", err
|
||||||
|
);
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context functions to work with chatlist
|
// Context functions to work with chatlist
|
||||||
|
|||||||
@@ -1361,9 +1361,12 @@ unsafe fn create_or_lookup_adhoc_group(
|
|||||||
if dc_array_get_cnt(chat_ids) > 0 {
|
if dc_array_get_cnt(chat_ids) > 0 {
|
||||||
chat_ids_str = dc_array_get_string(chat_ids, b",\x00" as *const u8 as *const _);
|
chat_ids_str = dc_array_get_string(chat_ids, b",\x00" as *const u8 as *const _);
|
||||||
let res = context.sql.query_row(
|
let res = context.sql.query_row(
|
||||||
"SELECT c.id, c.blocked FROM chats c \
|
format!(
|
||||||
LEFT JOIN msgs m ON m.chat_id=c.id WHERE c.id IN(?) ORDER BY m.timestamp DESC, m.id DESC LIMIT 1;",
|
"SELECT c.id, c.blocked FROM chats c \
|
||||||
params![as_str(chat_ids_str)],
|
LEFT JOIN msgs m ON m.chat_id=c.id WHERE c.id IN({}) ORDER BY m.timestamp DESC, m.id DESC LIMIT 1;",
|
||||||
|
as_str(chat_ids_str),
|
||||||
|
),
|
||||||
|
params![],
|
||||||
|row| {
|
|row| {
|
||||||
Ok((row.get::<_, i32>(0)?, row.get::<_, i32>(1)?))
|
Ok((row.get::<_, i32>(0)?, row.get::<_, i32>(1)?))
|
||||||
}
|
}
|
||||||
@@ -1477,8 +1480,11 @@ unsafe fn create_adhoc_grp_id(context: &Context, member_ids: *mut dc_array_t) ->
|
|||||||
let members = context
|
let members = context
|
||||||
.sql
|
.sql
|
||||||
.query_map(
|
.query_map(
|
||||||
"SELECT addr FROM contacts WHERE id IN(?) AND id!=1",
|
format!(
|
||||||
params![as_str(member_ids_str)],
|
"SELECT addr FROM contacts WHERE id IN({}) AND id!=1",
|
||||||
|
as_str(member_ids_str)
|
||||||
|
),
|
||||||
|
params![],
|
||||||
|row| row.get::<_, String>(0),
|
|row| row.get::<_, String>(0),
|
||||||
|rows| {
|
|rows| {
|
||||||
let mut addrs = rows.collect::<Result<Vec<_>, _>>()?;
|
let mut addrs = rows.collect::<Result<Vec<_>, _>>()?;
|
||||||
@@ -1535,8 +1541,11 @@ unsafe fn search_chat_ids_by_contact_ids(
|
|||||||
dc_array_get_string(contact_ids, b",\x00" as *const u8 as *const libc::c_char);
|
dc_array_get_string(contact_ids, b",\x00" as *const u8 as *const libc::c_char);
|
||||||
|
|
||||||
context.sql.query_map(
|
context.sql.query_map(
|
||||||
"SELECT DISTINCT cc.chat_id, cc.contact_id FROM chats_contacts cc LEFT JOIN chats c ON c.id=cc.chat_id WHERE cc.chat_id IN(SELECT chat_id FROM chats_contacts WHERE contact_id IN(?)) AND c.type=120 AND cc.contact_id!=1 ORDER BY cc.chat_id, cc.contact_id;",
|
format!(
|
||||||
params![as_str(contact_ids_str)],
|
"SELECT DISTINCT cc.chat_id, cc.contact_id FROM chats_contacts cc LEFT JOIN chats c ON c.id=cc.chat_id WHERE cc.chat_id IN(SELECT chat_id FROM chats_contacts WHERE contact_id IN({})) AND c.type=120 AND cc.contact_id!=1 ORDER BY cc.chat_id, cc.contact_id;",
|
||||||
|
as_str(contact_ids_str)
|
||||||
|
),
|
||||||
|
params![],
|
||||||
|row| Ok((row.get::<_, i32>(0)?, row.get::<_, i32>(1)?)),
|
|row| Ok((row.get::<_, i32>(0)?, row.get::<_, i32>(1)?)),
|
||||||
|rows| {
|
|rows| {
|
||||||
let mut last_chat_id = 0;
|
let mut last_chat_id = 0;
|
||||||
@@ -1634,9 +1643,12 @@ unsafe fn check_verified_properties(
|
|||||||
let ok = context
|
let ok = context
|
||||||
.sql
|
.sql
|
||||||
.query_map(
|
.query_map(
|
||||||
"SELECT c.addr, LENGTH(ps.verified_key_fingerprint) FROM contacts c \
|
format!(
|
||||||
LEFT JOIN acpeerstates ps ON c.addr=ps.addr WHERE c.id IN(?) ",
|
"SELECT c.addr, LENGTH(ps.verified_key_fingerprint) FROM contacts c \
|
||||||
params![&to_ids_str],
|
LEFT JOIN acpeerstates ps ON c.addr=ps.addr WHERE c.id IN({}) ",
|
||||||
|
&to_ids_str,
|
||||||
|
),
|
||||||
|
params![],
|
||||||
|row| Ok((row.get::<_, String>(0)?, row.get::<_, i32>(1)?)),
|
|row| Ok((row.get::<_, String>(0)?, row.get::<_, i32>(1)?)),
|
||||||
|rows| {
|
|rows| {
|
||||||
for row in rows {
|
for row in rows {
|
||||||
|
|||||||
89
src/sql.rs
89
src/sql.rs
@@ -98,7 +98,13 @@ impl Sql {
|
|||||||
/// Prepares and executes the statement and maps a function over the resulting rows.
|
/// Prepares and executes the statement and maps a function over the resulting rows.
|
||||||
/// Then executes the second function over the returned iterator and returns the
|
/// Then executes the second function over the returned iterator and returns the
|
||||||
/// result of that function.
|
/// result of that function.
|
||||||
pub fn query_map<T, P, F, G, H>(&self, sql: &str, params: P, f: F, mut g: G) -> Result<H>
|
pub fn query_map<T, P, F, G, H>(
|
||||||
|
&self,
|
||||||
|
sql: impl AsRef<str>,
|
||||||
|
params: P,
|
||||||
|
f: F,
|
||||||
|
mut g: G,
|
||||||
|
) -> Result<H>
|
||||||
where
|
where
|
||||||
P: IntoIterator,
|
P: IntoIterator,
|
||||||
P::Item: rusqlite::ToSql,
|
P::Item: rusqlite::ToSql,
|
||||||
@@ -106,7 +112,8 @@ impl Sql {
|
|||||||
G: FnMut(rusqlite::MappedRows<F>) -> Result<H>,
|
G: FnMut(rusqlite::MappedRows<F>) -> Result<H>,
|
||||||
{
|
{
|
||||||
self.with_conn(|conn| {
|
self.with_conn(|conn| {
|
||||||
let mut stmt = conn.prepare(sql)?;
|
eprintln!("query_map {}", sql.as_ref());
|
||||||
|
let mut stmt = conn.prepare(sql.as_ref())?;
|
||||||
let res = stmt.query_map(params, f)?;
|
let res = stmt.query_map(params, f)?;
|
||||||
g(res)
|
g(res)
|
||||||
})
|
})
|
||||||
@@ -126,13 +133,13 @@ impl Sql {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query_row<T, P, F>(&self, sql: &str, params: P, f: F) -> Result<T>
|
pub fn query_row<T, P, F>(&self, sql: impl AsRef<str>, params: P, f: F) -> Result<T>
|
||||||
where
|
where
|
||||||
P: IntoIterator,
|
P: IntoIterator,
|
||||||
P::Item: rusqlite::ToSql,
|
P::Item: rusqlite::ToSql,
|
||||||
F: FnOnce(&rusqlite::Row) -> rusqlite::Result<T>,
|
F: FnOnce(&rusqlite::Row) -> rusqlite::Result<T>,
|
||||||
{
|
{
|
||||||
self.with_conn(|conn| conn.query_row(sql, params, f).map_err(Into::into))
|
self.with_conn(|conn| conn.query_row(sql.as_ref(), params, f).map_err(Into::into))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn table_exists(&self, name: impl AsRef<str>) -> bool {
|
pub fn table_exists(&self, name: impl AsRef<str>) -> bool {
|
||||||
@@ -210,12 +217,12 @@ fn open(
|
|||||||
sql.execute(
|
sql.execute(
|
||||||
"CREATE TABLE contacts (\
|
"CREATE TABLE contacts (\
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT, \
|
id INTEGER PRIMARY KEY AUTOINCREMENT, \
|
||||||
name TEXT DEFAULT \'\', \
|
name TEXT DEFAULT '', \
|
||||||
addr TEXT DEFAULT \'\' COLLATE NOCASE, \
|
addr TEXT DEFAULT '' COLLATE NOCASE, \
|
||||||
origin INTEGER DEFAULT 0, \
|
origin INTEGER DEFAULT 0, \
|
||||||
blocked INTEGER DEFAULT 0, \
|
blocked INTEGER DEFAULT 0, \
|
||||||
last_seen INTEGER DEFAULT 0, \
|
last_seen INTEGER DEFAULT 0, \
|
||||||
param TEXT DEFAULT \'\');",
|
param TEXT DEFAULT '');",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
@@ -228,21 +235,21 @@ fn open(
|
|||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"INSERT INTO contacts (id,name,origin) VALUES \
|
"INSERT INTO contacts (id,name,origin) VALUES \
|
||||||
(1,\'self\',262144), (2,\'device\',262144), (3,\'rsvd\',262144), \
|
(1,'self',262144), (2,'device',262144), (3,'rsvd',262144), \
|
||||||
(4,\'rsvd\',262144), (5,\'rsvd\',262144), (6,\'rsvd\',262144), \
|
(4,'rsvd',262144), (5,'rsvd',262144), (6,'rsvd',262144), \
|
||||||
(7,\'rsvd\',262144), (8,\'rsvd\',262144), (9,\'rsvd\',262144);",
|
(7,'rsvd',262144), (8,'rsvd',262144), (9,'rsvd',262144);",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"CREATE TABLE chats (\
|
"CREATE TABLE chats (\
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT, \
|
id INTEGER PRIMARY KEY AUTOINCREMENT, \
|
||||||
type INTEGER DEFAULT 0, \
|
type INTEGER DEFAULT 0, \
|
||||||
name TEXT DEFAULT \'\', \
|
name TEXT DEFAULT '', \
|
||||||
draft_timestamp INTEGER DEFAULT 0, \
|
draft_timestamp INTEGER DEFAULT 0, \
|
||||||
draft_txt TEXT DEFAULT \'\', \
|
draft_txt TEXT DEFAULT '', \
|
||||||
blocked INTEGER DEFAULT 0, \
|
blocked INTEGER DEFAULT 0, \
|
||||||
grpid TEXT DEFAULT \'\', \
|
grpid TEXT DEFAULT '', \
|
||||||
param TEXT DEFAULT \'\');",
|
param TEXT DEFAULT '');",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute("CREATE INDEX chats_index1 ON chats (grpid);", params![])?;
|
sql.execute("CREATE INDEX chats_index1 ON chats (grpid);", params![])?;
|
||||||
@@ -256,16 +263,16 @@ fn open(
|
|||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"INSERT INTO chats (id,type,name) VALUES \
|
"INSERT INTO chats (id,type,name) VALUES \
|
||||||
(1,120,\'deaddrop\'), (2,120,\'rsvd\'), (3,120,\'trash\'), \
|
(1,120,'deaddrop'), (2,120,'rsvd'), (3,120,'trash'), \
|
||||||
(4,120,\'msgs_in_creation\'), (5,120,\'starred\'), (6,120,\'archivedlink\'), \
|
(4,120,'msgs_in_creation'), (5,120,'starred'), (6,120,'archivedlink'), \
|
||||||
(7,100,\'rsvd\'), (8,100,\'rsvd\'), (9,100,\'rsvd\');",
|
(7,100,'rsvd'), (8,100,'rsvd'), (9,100,'rsvd');",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"CREATE TABLE msgs (\
|
"CREATE TABLE msgs (\
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT, \
|
id INTEGER PRIMARY KEY AUTOINCREMENT, \
|
||||||
rfc724_mid TEXT DEFAULT \'\', \
|
rfc724_mid TEXT DEFAULT '', \
|
||||||
server_folder TEXT DEFAULT \'\', \
|
server_folder TEXT DEFAULT '', \
|
||||||
server_uid INTEGER DEFAULT 0, \
|
server_uid INTEGER DEFAULT 0, \
|
||||||
chat_id INTEGER DEFAULT 0, \
|
chat_id INTEGER DEFAULT 0, \
|
||||||
from_id INTEGER DEFAULT 0, \
|
from_id INTEGER DEFAULT 0, \
|
||||||
@@ -275,9 +282,9 @@ fn open(
|
|||||||
state INTEGER DEFAULT 0, \
|
state INTEGER DEFAULT 0, \
|
||||||
msgrmsg INTEGER DEFAULT 1, \
|
msgrmsg INTEGER DEFAULT 1, \
|
||||||
bytes INTEGER DEFAULT 0, \
|
bytes INTEGER DEFAULT 0, \
|
||||||
txt TEXT DEFAULT \'\', \
|
txt TEXT DEFAULT '', \
|
||||||
txt_raw TEXT DEFAULT \'\', \
|
txt_raw TEXT DEFAULT '', \
|
||||||
param TEXT DEFAULT \'\');",
|
param TEXT DEFAULT '');",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute("CREATE INDEX msgs_index1 ON msgs (rfc724_mid);", params![])?;
|
sql.execute("CREATE INDEX msgs_index1 ON msgs (rfc724_mid);", params![])?;
|
||||||
@@ -286,9 +293,9 @@ fn open(
|
|||||||
sql.execute("CREATE INDEX msgs_index4 ON msgs (state);", params![])?;
|
sql.execute("CREATE INDEX msgs_index4 ON msgs (state);", params![])?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"INSERT INTO msgs (id,msgrmsg,txt) VALUES \
|
"INSERT INTO msgs (id,msgrmsg,txt) VALUES \
|
||||||
(1,0,\'marker1\'), (2,0,\'rsvd\'), (3,0,\'rsvd\'), \
|
(1,0,'marker1'), (2,0,'rsvd'), (3,0,'rsvd'), \
|
||||||
(4,0,\'rsvd\'), (5,0,\'rsvd\'), (6,0,\'rsvd\'), (7,0,\'rsvd\'), \
|
(4,0,'rsvd'), (5,0,'rsvd'), (6,0,'rsvd'), (7,0,'rsvd'), \
|
||||||
(8,0,\'rsvd\'), (9,0,\'daymarker\');",
|
(8,0,'rsvd'), (9,0,'daymarker');",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
@@ -298,7 +305,7 @@ fn open(
|
|||||||
desired_timestamp INTEGER DEFAULT 0, \
|
desired_timestamp INTEGER DEFAULT 0, \
|
||||||
action INTEGER, \
|
action INTEGER, \
|
||||||
foreign_id INTEGER, \
|
foreign_id INTEGER, \
|
||||||
param TEXT DEFAULT \'\');",
|
param TEXT DEFAULT '');",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
@@ -338,7 +345,7 @@ fn open(
|
|||||||
|
|
||||||
if dbversion < 1 {
|
if dbversion < 1 {
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"CREATE TABLE leftgrps ( id INTEGER PRIMARY KEY, grpid TEXT DEFAULT \'\');",
|
"CREATE TABLE leftgrps ( id INTEGER PRIMARY KEY, grpid TEXT DEFAULT '');",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
@@ -350,7 +357,7 @@ fn open(
|
|||||||
}
|
}
|
||||||
if dbversion < 2 {
|
if dbversion < 2 {
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"ALTER TABLE contacts ADD COLUMN authname TEXT DEFAULT \'\';",
|
"ALTER TABLE contacts ADD COLUMN authname TEXT DEFAULT '';",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
dbversion = 2;
|
dbversion = 2;
|
||||||
@@ -360,7 +367,7 @@ fn open(
|
|||||||
sql.execute(
|
sql.execute(
|
||||||
"CREATE TABLE keypairs (\
|
"CREATE TABLE keypairs (\
|
||||||
id INTEGER PRIMARY KEY, \
|
id INTEGER PRIMARY KEY, \
|
||||||
addr TEXT DEFAULT \'\' COLLATE NOCASE, \
|
addr TEXT DEFAULT '' COLLATE NOCASE, \
|
||||||
is_default INTEGER DEFAULT 0, \
|
is_default INTEGER DEFAULT 0, \
|
||||||
private_key, \
|
private_key, \
|
||||||
public_key, \
|
public_key, \
|
||||||
@@ -374,7 +381,7 @@ fn open(
|
|||||||
sql.execute(
|
sql.execute(
|
||||||
"CREATE TABLE acpeerstates (\
|
"CREATE TABLE acpeerstates (\
|
||||||
id INTEGER PRIMARY KEY, \
|
id INTEGER PRIMARY KEY, \
|
||||||
addr TEXT DEFAULT \'\' COLLATE NOCASE, \
|
addr TEXT DEFAULT '' COLLATE NOCASE, \
|
||||||
last_seen INTEGER DEFAULT 0, \
|
last_seen INTEGER DEFAULT 0, \
|
||||||
last_seen_autocrypt INTEGER DEFAULT 0, \
|
last_seen_autocrypt INTEGER DEFAULT 0, \
|
||||||
public_key, \
|
public_key, \
|
||||||
@@ -450,11 +457,11 @@ fn open(
|
|||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"ALTER TABLE acpeerstates ADD COLUMN public_key_fingerprint TEXT DEFAULT \'\';",
|
"ALTER TABLE acpeerstates ADD COLUMN public_key_fingerprint TEXT DEFAULT '';",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"ALTER TABLE acpeerstates ADD COLUMN gossip_key_fingerprint TEXT DEFAULT \'\';",
|
"ALTER TABLE acpeerstates ADD COLUMN gossip_key_fingerprint TEXT DEFAULT '';",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
@@ -471,7 +478,7 @@ fn open(
|
|||||||
}
|
}
|
||||||
if dbversion < 39 {
|
if dbversion < 39 {
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"CREATE TABLE tokens ( id INTEGER PRIMARY KEY, namespc INTEGER DEFAULT 0, foreign_id INTEGER DEFAULT 0, token TEXT DEFAULT \'\', timestamp INTEGER DEFAULT 0);",
|
"CREATE TABLE tokens ( id INTEGER PRIMARY KEY, namespc INTEGER DEFAULT 0, foreign_id INTEGER DEFAULT 0, token TEXT DEFAULT '', timestamp INTEGER DEFAULT 0);",
|
||||||
params![]
|
params![]
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
@@ -479,7 +486,7 @@ fn open(
|
|||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
"ALTER TABLE acpeerstates ADD COLUMN verified_key_fingerprint TEXT DEFAULT \'\';",
|
"ALTER TABLE acpeerstates ADD COLUMN verified_key_fingerprint TEXT DEFAULT '';",
|
||||||
params![],
|
params![],
|
||||||
)?;
|
)?;
|
||||||
sql.execute(
|
sql.execute(
|
||||||
@@ -513,7 +520,7 @@ fn open(
|
|||||||
set_config_int(context, sql, "dbversion", 41);
|
set_config_int(context, sql, "dbversion", 41);
|
||||||
}
|
}
|
||||||
if dbversion < 42 {
|
if dbversion < 42 {
|
||||||
sql.execute("UPDATE msgs SET txt=\'\' WHERE type!=10", params![])?;
|
sql.execute("UPDATE msgs SET txt='' WHERE type!=10", params![])?;
|
||||||
dbversion = 42;
|
dbversion = 42;
|
||||||
set_config_int(context, sql, "dbversion", 42);
|
set_config_int(context, sql, "dbversion", 42);
|
||||||
}
|
}
|
||||||
@@ -661,7 +668,7 @@ fn open(
|
|||||||
let repl_from = dc_ensure_no_slash_safe(&repl_from);
|
let repl_from = dc_ensure_no_slash_safe(&repl_from);
|
||||||
sql.execute(
|
sql.execute(
|
||||||
&format!(
|
&format!(
|
||||||
"UPDATE msgs SET param=replace(param, \'f={}/\', \'f=$BLOBDIR/\')",
|
"UPDATE msgs SET param=replace(param, 'f={}/', 'f=$BLOBDIR/')",
|
||||||
repl_from
|
repl_from
|
||||||
),
|
),
|
||||||
NO_PARAMS,
|
NO_PARAMS,
|
||||||
@@ -669,7 +676,7 @@ fn open(
|
|||||||
|
|
||||||
sql.execute(
|
sql.execute(
|
||||||
&format!(
|
&format!(
|
||||||
"UPDATE chats SET param=replace(param, \'i={}/\', \'i=$BLOBDIR/\');",
|
"UPDATE chats SET param=replace(param, 'i={}/', 'i=$BLOBDIR/');",
|
||||||
repl_from
|
repl_from
|
||||||
),
|
),
|
||||||
NO_PARAMS,
|
NO_PARAMS,
|
||||||
@@ -762,7 +769,13 @@ where
|
|||||||
match sql.execute(querystr.as_ref(), params) {
|
match sql.execute(querystr.as_ref(), params) {
|
||||||
Ok(_) => true,
|
Ok(_) => true,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(context, 0, "execute failed: {:?}", err);
|
error!(
|
||||||
|
context,
|
||||||
|
0,
|
||||||
|
"execute failed: {:?} for {}",
|
||||||
|
err,
|
||||||
|
querystr.as_ref()
|
||||||
|
);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user