pub mod model;
use std::path::Path;
pub use sqlite_ext_ntqq_db::*;
use rusqlite::Connection;
use snafu::{ResultExt, Snafu};
use crate::ntqq;
pub fn try_decrypt_db(conn: &Connection, mut d: ntqq::DBDecryptInfo) -> crate::Result<()> {
let try_alg: [Option<String>; 2] = match d.cipher_hmac_algorithm.take() {
Some(algo) => [Some(algo), None],
None => ["HMAC_SHA256", "HMAC_SHA1"].map(|x| Some(x.to_string())),
};
for algo in try_alg.into_iter().flatten() {
log::info!("trying hmac algorithm: {}", algo);
d.cipher_hmac_algorithm = Some(algo);
let stmt = d.display_pragma_stmts().to_string();
conn.execute_batch(&stmt)
.context(SqliteSnafu { op: stmt })?;
let stmt = conn.prepare("SELECT count(*) FROM sqlite_master;");
match stmt {
Ok(mut stmt) => {
if stmt.exists([]).context(SqliteSnafu { op: "stmt.exists" })? {
log::info!("decryped successfully");
return Ok(());
}
}
Err(e) => {
log::info!("attempt failed: {}", e);
}
}
}
WrongDecryptInfoSnafu.fail().map_err(crate::Error::from)
}
pub fn export_to_plain(conn: &Connection, file: impl AsRef<Path>) -> crate::Result<()> {
let stmt = format!(
r#"ATTACH DATABASE '{}' AS plain KEY '';
SELECT sqlcipher_export('plain');
DETACH DATABASE plain;"#,
file.as_ref().display()
);
conn.execute_batch(&stmt)
.context(SqliteSnafu { op: stmt })?;
Ok(())
}
#[derive(Debug, Snafu)]
pub enum Error {
Sqlite { source: rusqlite::Error, op: String },
WrongDecryptInfo {},
}