in rust-query-crlite/src/main.rs [117:196]
fn update_db(
db_dir: &Path,
attachment_url: &str,
base_url: &str,
channel: &CRLiteFilterChannel,
) -> Result<(), CRLiteDBError> {
info!(
"Fetching cert-revocations records from remote settings {}",
base_url
);
let cert_rev_records: CertRevCollection =
reqwest::blocking::get(base_url.to_owned() + "cert-revocations/records")
.map_err(|_| CRLiteDBError::from("could not fetch remote settings collection"))?
.json()
.map_err(|_| CRLiteDBError::from("could not read remote settings data"))?;
let filters: Vec<&CertRevRecord> = cert_rev_records
.data
.iter()
.filter(|x| x.channel.unwrap_or_default() == *channel)
.collect();
if filters.iter().filter(|x| !x.incremental).count() != 1 {
return Err(CRLiteDBError::from(
"number of full filters found in remote settings is not 1",
));
}
let expected_filenames: HashSet<OsString> = filters
.iter()
.map(|x| x.attachment.filename.clone().into())
.collect();
// Remove any filter or delta files that are not listed in the collection
for dir_entry in std::fs::read_dir(db_dir)? {
let Ok(dir_entry) = dir_entry else { continue };
let dir_entry_path = dir_entry.path();
let extension = dir_entry_path
.extension()
.and_then(|os_str| os_str.to_str());
if (extension == Some("delta") || extension == Some("filter"))
&& !expected_filenames.contains(&dir_entry.file_name())
{
info!("Removing {:?}", dir_entry.file_name());
let _ = std::fs::remove_file(dir_entry_path);
}
}
for filter in filters {
let expected_digest = hex::decode(&filter.attachment.hash)
.map_err(|_| CRLiteDBError::from("filter digest corrupted"))?;
let path = db_dir.join(filter.attachment.filename.clone());
if path.exists() {
let digest = Sha256::digest(std::fs::read(&path)?);
if expected_digest == digest.as_slice() {
info!("Found existing copy of {}", filter.attachment.filename);
continue;
}
}
let filter_url = format!("{}{}", attachment_url, filter.attachment.location);
info!(
"Fetching {} from {}",
filter.attachment.filename, filter_url
);
let filter_bytes = &reqwest::blocking::get(filter_url)
.map_err(|_| CRLiteDBError::from("could not fetch filter"))?
.bytes()
.map_err(|_| CRLiteDBError::from("could not read filter"))?;
let digest = Sha256::digest(filter_bytes);
if expected_digest != digest.as_slice() {
return Err(CRLiteDBError::from("filter digest mismatch"));
}
std::fs::write(&path, filter_bytes)?;
}
Ok(())
}