Skip to content

Commit ec48802

Browse files
authored
Fix GitHub handle parsing and use better email address validation (typst#404)
1 parent a19cd87 commit ec48802

File tree

3 files changed

+12
-41
lines changed

3 files changed

+12
-41
lines changed

bundler/Cargo.lock

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bundler/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ publish = false
66

77
[dependencies]
88
anyhow = "1"
9+
email_address = { version = "0.2.4", default-features = false }
910
flate2 = "1"
1011
ignore = "0.4"
1112
rayon = "1.0"

bundler/src/author.rs

+4-41
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use anyhow::{bail, Context};
2+
use email_address::EmailAddress;
23
use unscanny::Scanner;
34

45
/// Validates the format of an author field. It can contain a name and, in angle
@@ -9,12 +10,12 @@ pub fn validate_author(name: &str) -> anyhow::Result<()> {
910
s.eat_until(|c| c == '<');
1011
if s.eat_if('<') {
1112
let contact = s.eat_until('>');
12-
if contact.starts_with('@') {
13-
validate_github_handle(contact).context("GitHub handle is invalid")?;
13+
if let Some(handle) = contact.strip_prefix('@') {
14+
validate_github_handle(handle).context("GitHub handle is invalid")?;
1415
} else if contact.starts_with("http") {
1516
validate_url(contact).context("URL is invalid")?;
1617
} else {
17-
validate_email(contact).context("email is invalid")?;
18+
let _addr: EmailAddress = contact.parse().context("email is invalid")?;
1819
}
1920
if !s.eat_if('>') {
2021
bail!("expected '>'");
@@ -56,49 +57,11 @@ fn validate_url(url: &str) -> anyhow::Result<()> {
5657
Ok(())
5758
}
5859

59-
/// Validates an email address.
60-
fn validate_email(email: &str) -> anyhow::Result<()> {
61-
if email.len() >= 254 {
62-
bail!("cannot be longer than 254 characters");
63-
}
64-
65-
let mut s = Scanner::new(email);
66-
let local = s.eat_until('@');
67-
let domain = s.eat_until('.');
68-
let tld = s.after();
69-
70-
if local.is_empty() {
71-
bail!("local part must not be empty");
72-
}
73-
74-
if domain.is_empty() {
75-
bail!("domain must not be empty");
76-
}
77-
78-
if tld.is_empty() {
79-
bail!("TLD must not be empty");
80-
}
81-
82-
if !local.chars().all(is_legal_in_email_local_part)
83-
|| !domain.chars().all(is_legal_in_url)
84-
|| !tld.chars().all(is_legal_in_url)
85-
{
86-
bail!("contains illegal characters");
87-
}
88-
89-
Ok(())
90-
}
91-
9260
/// Whether a character is legal in a URL.
9361
fn is_legal_in_url(c: char) -> bool {
9462
c.is_ascii_alphanumeric() || "-_.~:/?#[]@!$&'()*+,;=".contains(c)
9563
}
9664

97-
/// Whether a character is legal in the local part of an email.
98-
fn is_legal_in_email_local_part(c: char) -> bool {
99-
c.is_ascii_alphanumeric() || "!#$%&'*+-/=?^_`{|}~.".contains(c)
100-
}
101-
10265
#[cfg(test)]
10366
mod tests {
10467
use super::validate_author;

0 commit comments

Comments
 (0)