Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions src/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -907,11 +907,10 @@ impl Chat {

// the whole list of messages referenced may be huge;
// only use the oldest and and the parent message
let parent_references = if let Some(n) = parent_references.find(' ') {
&parent_references[0..n]
} else {
&parent_references
};
let parent_references = parent_references
.find(' ')
.and_then(|n| parent_references.get(..n))
.unwrap_or(&parent_references);

if !parent_references.is_empty() && !parent_rfc724_mid.is_empty() {
// angle brackets are added by the mimefactory later
Expand Down
2 changes: 0 additions & 2 deletions src/configure/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//! Email accounts autoconfiguration process module

#![forbid(clippy::indexing_slicing)]

mod auto_mozilla;
mod auto_outlook;
mod read_url;
Expand Down
2 changes: 0 additions & 2 deletions src/contact.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
//! Contacts module

#![forbid(clippy::indexing_slicing)]

use async_std::path::PathBuf;
use deltachat_derive::*;
use itertools::Itertools;
Expand Down
12 changes: 7 additions & 5 deletions src/dc_receive_imf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,7 @@ async fn create_adhoc_grp_id(context: &Context, member_ids: &[u32]) -> String {
hex_hash(&members)
}

#[allow(clippy::indexing_slicing)]
fn hex_hash(s: impl AsRef<str>) -> String {
let bytes = s.as_ref().as_bytes();
let result = Sha256::digest(bytes);
Expand Down Expand Up @@ -1564,7 +1565,7 @@ async fn search_chat_ids_by_contact_ids(
matches = 0;
mismatches = 0;
}
if matches < contact_ids.len() && contact_id == contact_ids[matches] {
if contact_ids.get(matches) == Some(&contact_id) {
matches += 1;
} else {
mismatches += 1;
Expand Down Expand Up @@ -1692,10 +1693,11 @@ async fn check_verified_properties(

fn set_better_msg(mime_parser: &mut MimeMessage, better_msg: impl AsRef<str>) {
let msg = better_msg.as_ref();
if !msg.is_empty() && !mime_parser.parts.is_empty() {
let part = &mut mime_parser.parts[0];
if part.typ == Viewtype::Text {
part.msg = msg.to_string();
if !msg.is_empty() {
if let Some(part) = mime_parser.parts.get_mut(0) {
if part.typ == Viewtype::Text {
part.msg = msg.to_string();
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/dc_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub(crate) fn dc_exactly_one_bit_set(v: i32) -> bool {

/// Shortens a string to a specified length and adds "[...]" to the
/// end of the shortened string.
#[allow(clippy::indexing_slicing)]
pub(crate) fn dc_truncate(buf: &str, approx_chars: usize) -> Cow<str> {
let ellipse = "[...]";

Expand Down Expand Up @@ -54,6 +55,7 @@ const COLORS: [u32; 16] = [
0xf2_30_30, 0x39_b2_49, 0xbb_24_3b, 0x96_40_78, 0x66_87_4f, 0x30_8a_b9, 0x12_7e_d0, 0xbe_45_0c,
];

#[allow(clippy::indexing_slicing)]
pub(crate) fn dc_str_to_color(s: impl AsRef<str>) -> u32 {
let str_lower = s.as_ref().to_lowercase();
let mut checksum = 0;
Expand Down Expand Up @@ -198,7 +200,7 @@ fn encode_66bits_as_base64(v1: u32, v2: u32, fill: u32) -> String {
pub(crate) fn dc_create_outgoing_rfc724_mid(grpid: Option<&str>, from_addr: &str) -> String {
let hostname = from_addr
.find('@')
.map(|k| &from_addr[k..])
.and_then(|k| from_addr.get(k..))
.unwrap_or("@nohost");
match grpid {
Some(grpid) => format!("Gr.{}.{}{}", grpid, dc_create_id(), hostname),
Expand Down
32 changes: 16 additions & 16 deletions src/e2ee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,24 +187,23 @@ fn get_autocrypt_mime<'a, 'b>(mail: &'a ParsedMail<'b>) -> Result<&'a ParsedMail
"Not a multipart/encrypted message: {}",
mail.ctype.mimetype
);
ensure!(
mail.subparts.len() == 2,
"Invalid Autocrypt Level 1 Mime Parts"
);

ensure!(
mail.subparts[0].ctype.mimetype == "application/pgp-encrypted",
"Invalid Autocrypt Level 1 version part: {:?}",
mail.subparts[0].ctype,
);
if let [first_part, second_part] = &mail.subparts[..] {
ensure!(
first_part.ctype.mimetype == "application/pgp-encrypted",
"Invalid Autocrypt Level 1 version part: {:?}",
first_part.ctype,
);

ensure!(
mail.subparts[1].ctype.mimetype == "application/octet-stream",
"Invalid Autocrypt Level 1 encrypted part: {:?}",
mail.subparts[1].ctype
);
ensure!(
second_part.ctype.mimetype == "application/octet-stream",
"Invalid Autocrypt Level 1 encrypted part: {:?}",
second_part.ctype
);

Ok(&mail.subparts[1])
Ok(second_part)
} else {
bail!("Invalid Autocrypt Level 1 Mime Parts")
}
}

async fn decrypt_if_autocrypt_message<'a>(
Expand Down Expand Up @@ -267,6 +266,7 @@ async fn decrypt_part(
Ok(None)
}

#[allow(clippy::indexing_slicing)]
fn has_decrypted_pgp_armor(input: &[u8]) -> bool {
if let Some(index) = input.iter().position(|b| *b > b' ') {
if input.len() - index > 26 {
Expand Down
2 changes: 0 additions & 2 deletions src/imap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
//! uses [async-email/async-imap](https://github.com/async-email/async-imap)
//! to implement connect, fetch, delete functionality with standard IMAP servers.

#![forbid(clippy::indexing_slicing)]

use std::collections::BTreeMap;

use async_imap::{
Expand Down
11 changes: 6 additions & 5 deletions src/imex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,11 @@ async fn do_initiate_key_transfer(context: &Context) -> Result<String> {
///
/// The `passphrase` must be at least 2 characters long.
pub async fn render_setup_file(context: &Context, passphrase: &str) -> Result<String> {
ensure!(
passphrase.len() >= 2,
"Passphrase must be at least 2 chars long."
);
let passphrase_begin = if let Some(passphrase_begin) = passphrase.get(..2) {
passphrase_begin
} else {
bail!("Passphrase must be at least 2 chars long.");
};
let private_key = SignedSecretKey::load_self(context).await?;
let ac_headers = match context.get_config_bool(Config::E2eeEnabled).await {
false => None,
Expand All @@ -196,7 +197,7 @@ pub async fn render_setup_file(context: &Context, passphrase: &str) -> Result<St
"Passphrase-Format: numeric9x4\r\n",
"Passphrase-Begin: {}"
),
&passphrase[..2]
passphrase_begin
);
let pgp_msg = encr.replace("-----BEGIN PGP MESSAGE-----", &replacement);

Expand Down
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#![forbid(unsafe_code)]
#![deny(clippy::correctness, missing_debug_implementations, clippy::all)]
#![deny(
clippy::correctness,
missing_debug_implementations,
clippy::all,
clippy::indexing_slicing
)]
#![allow(clippy::match_bool)]

#[macro_use]
Expand Down
69 changes: 34 additions & 35 deletions src/mimeparser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ impl MimeMessage {
///
/// Delta Chat sends attachments, such as images, in two-part messages, with the first message
/// containing an explanation. If such a message is detected, first part can be safely dropped.
#[allow(clippy::indexing_slicing)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be possible to replace the two parts[0] calls further down with textpart?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, borrow checker fails.

fn squash_attachment_parts(&mut self) {
if let [textpart, filepart] = &self.parts[..] {
let need_drop = {
Expand Down Expand Up @@ -272,34 +273,34 @@ impl MimeMessage {
fn parse_attachments(&mut self) {
// Attachment messages should be squashed into a single part
// before calling this function.
if self.parts.len() == 1 {
if self.parts[0].typ == Viewtype::Audio
&& self.get(HeaderDef::ChatVoiceMessage).is_some()
{
let part_mut = &mut self.parts[0];
part_mut.typ = Viewtype::Voice;
if self.parts.len() != 1 {
return;
}

if let Some(mut part) = self.parts.pop() {
if part.typ == Viewtype::Audio && self.get(HeaderDef::ChatVoiceMessage).is_some() {
part.typ = Viewtype::Voice;
}
if self.parts[0].typ == Viewtype::Image {
if part.typ == Viewtype::Image {
if let Some(value) = self.get(HeaderDef::ChatContent) {
if value == "sticker" {
let part_mut = &mut self.parts[0];
part_mut.typ = Viewtype::Sticker;
part.typ = Viewtype::Sticker;
}
}
}
let part = &self.parts[0];
if part.typ == Viewtype::Audio
|| part.typ == Viewtype::Voice
|| part.typ == Viewtype::Video
{
if let Some(field_0) = self.get(HeaderDef::ChatDuration) {
let duration_ms = field_0.parse().unwrap_or_default();
if duration_ms > 0 && duration_ms < 24 * 60 * 60 * 1000 {
let part_mut = &mut self.parts[0];
part_mut.param.set_int(Param::Duration, duration_ms);
part.param.set_int(Param::Duration, duration_ms);
}
}
}

self.parts.push(part);
}
}

Expand All @@ -321,12 +322,11 @@ impl MimeMessage {
}
}
if prepend_subject {
let subj = if let Some(n) = subject.find('[') {
&subject[0..n]
} else {
subject
}
.trim();
let subj = subject
.find('[')
.and_then(|n| subject.get(..n))
.unwrap_or(subject)
.trim();

if !subj.is_empty() {
for part in self.parts.iter_mut() {
Expand Down Expand Up @@ -384,8 +384,7 @@ impl MimeMessage {
Some(AvatarAction::Delete)
} else {
let mut i = 0;
while i != self.parts.len() {
let part = &mut self.parts[i];
while let Some(part) = self.parts.get_mut(i) {
if let Some(part_filename) = &part.org_filename {
if part_filename == &header_value {
if let Some(blob) = part.param.get(Param::File) {
Expand Down Expand Up @@ -770,16 +769,11 @@ impl MimeMessage {
}

pub fn repl_msg_by_error(&mut self, error_msg: impl AsRef<str>) {
if self.parts.is_empty() {
return;
if let Some(part) = self.parts.first_mut() {
part.typ = Viewtype::Text;
part.msg = format!("[{}]", error_msg.as_ref());
self.parts.truncate(1);
}

let part = &mut self.parts[0];
part.typ = Viewtype::Text;
part.msg = format!("[{}]", error_msg.as_ref());
self.parts.truncate(1);

assert_eq!(self.parts.len(), 1);
}

pub fn get_rfc724_mid(&self) -> Option<String> {
Expand Down Expand Up @@ -830,7 +824,11 @@ impl MimeMessage {
report: &mailparse::ParsedMail<'_>,
) -> Result<Option<Report>> {
// parse as mailheaders
let report_body = report.subparts[1].get_body_raw()?;
let report_body = if let Some(subpart) = report.subparts.get(1) {
subpart.get_body_raw()?
} else {
bail!("Report does not have second MIME part");
};
let (report_fields, _) = mailparse::parse_headers(&report_body)?;

// must be present
Expand Down Expand Up @@ -908,6 +906,7 @@ impl MimeMessage {
/// Some providers like GMX and Yahoo do not send standard NDNs (Non Delivery notifications).
/// If you improve heuristics here you might also have to change prefetch_should_download() in imap/mod.rs.
/// Also you should add a test in dc_receive_imf.rs (there already are lots of test_parse_ndn_* tests).
#[allow(clippy::indexing_slicing)]
async fn heuristically_parse_ndn(&mut self, context: &Context) -> Option<()> {
let maybe_ndn = if let Some(from) = self.get(HeaderDef::From_) {
let from = from.to_ascii_lowercase();
Expand Down Expand Up @@ -966,11 +965,10 @@ impl MimeMessage {
if let Some(failure_report) = &self.failure_report {
let error = parts.iter().find(|p| p.typ == Viewtype::Text).map(|p| {
let msg = &p.msg;
match msg.find("\n--- ") {
Some(footer_start) => &msg[..footer_start],
None => msg,
}
.trim()
msg.find("\n--- ")
.and_then(|footer_start| msg.get(..footer_start))
.unwrap_or(msg)
.trim()
});
message::handle_ndn(context, failure_report, error).await
}
Expand Down Expand Up @@ -1036,6 +1034,7 @@ pub(crate) struct FailureReport {
pub failed_recipient: Option<String>,
}

#[allow(clippy::indexing_slicing)]
pub(crate) fn parse_message_ids(ids: &str) -> Result<Vec<String>> {
// take care with mailparse::msgidparse() that is pretty untolerant eg. wrt missing `<` or `>`
let mut msgids = Vec::new();
Expand Down
2 changes: 1 addition & 1 deletion src/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl str::FromStr for Params {
let key = key.unwrap_or_default().trim();
let value = value.unwrap_or_default().trim();

if let Some(key) = Param::from_u8(key.as_bytes()[0]) {
if let Some(key) = key.as_bytes().first().and_then(|key| Param::from_u8(*key)) {
inner.insert(key, value.to_string());
} else {
bail!("Unknown key: {}", key);
Expand Down
12 changes: 7 additions & 5 deletions src/pgp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,11 +365,13 @@ pub async fn symm_decrypt<T: std::io::Read + std::io::Seek>(
let decryptor = enc_msg.decrypt_with_password(|| passphrase)?;

let msgs = decryptor.collect::<pgp::errors::Result<Vec<_>>>()?;
ensure!(!msgs.is_empty(), "No valid messages found");

match msgs[0].get_content()? {
Some(content) => Ok(content),
None => bail!("Decrypted message is empty"),
if let Some(msg) = msgs.first() {
match msg.get_content()? {
Some(content) => Ok(content),
None => bail!("Decrypted message is empty"),
}
} else {
bail!("No valid messages found")
}
})
.await
Expand Down
Loading