#[allow(dead_code)] #[must_use]
pub(crate) fn as_applescript_string(s: &str) -> String {
let mut out = String::with_capacity(s.len() + 2);
out.push('"');
for ch in s.chars() {
match ch {
'\\' => out.push_str("\\\\"),
'"' => out.push_str("\\\""),
'\n' => out.push_str("\\n"),
'\r' => out.push_str("\\r"),
'\t' => out.push_str("\\t"),
c => out.push(c),
}
}
out.push('"');
out
}
#[cfg(test)]
mod tests {
use super::as_applescript_string;
#[test]
fn empty() {
assert_eq!(as_applescript_string(""), "\"\"");
}
#[test]
fn plain_ascii() {
assert_eq!(as_applescript_string("Hello world"), "\"Hello world\"");
}
#[test]
fn double_quote() {
assert_eq!(as_applescript_string("a\"b"), "\"a\\\"b\"");
}
#[test]
fn backslash() {
assert_eq!(as_applescript_string("a\\b"), "\"a\\\\b\"");
}
#[test]
fn newline() {
assert_eq!(as_applescript_string("a\nb"), "\"a\\nb\"");
}
#[test]
fn carriage_return() {
assert_eq!(as_applescript_string("a\rb"), "\"a\\rb\"");
}
#[test]
fn tab() {
assert_eq!(as_applescript_string("a\tb"), "\"a\\tb\"");
}
#[test]
fn mixed_whitespace() {
assert_eq!(
as_applescript_string("line1\n\tindented \"quoted\"\\\r"),
"\"line1\\n\\tindented \\\"quoted\\\"\\\\\\r\""
);
}
#[test]
fn unicode_passes_through() {
assert_eq!(as_applescript_string("café"), "\"café\"");
assert_eq!(as_applescript_string("日本語"), "\"日本語\"");
assert_eq!(as_applescript_string("🚀"), "\"🚀\"");
}
#[test]
fn unicode_line_separators_pass_through() {
assert_eq!(as_applescript_string("a\u{2028}b"), "\"a\u{2028}b\"");
assert_eq!(as_applescript_string("a\u{2029}b"), "\"a\u{2029}b\"");
}
#[test]
fn injection_attempt_is_neutralised() {
let payload = r#""); do shell script "rm -rf /"; (""#;
let escaped = as_applescript_string(payload);
assert!(escaped.starts_with('"') && escaped.ends_with('"'));
let body = &escaped[1..escaped.len() - 1];
for (i, ch) in body.char_indices() {
if ch == '"' {
let preceding_backslashes =
body[..i].chars().rev().take_while(|c| *c == '\\').count();
assert!(
preceding_backslashes % 2 == 1,
"unescaped quote at byte {i} in {escaped:?}"
);
}
}
}
#[test]
fn long_runs_of_specials() {
assert_eq!(as_applescript_string("\\\\\\\""), "\"\\\\\\\\\\\\\\\"\"");
}
#[test]
fn round_trip_via_pure_concat() {
let title = "Buy \"organic\" milk\nand \\bread\t";
let snippet = format!(
"make new to do with properties {{name:{}, notes:{}}}",
as_applescript_string(title),
as_applescript_string("multi\nline\nnote"),
);
let mut unescaped_quotes = 0;
let mut prev = '\0';
for ch in snippet.chars() {
if ch == '"' && prev != '\\' {
unescaped_quotes += 1;
}
prev = ch;
}
assert_eq!(unescaped_quotes, 4, "snippet was: {snippet:?}");
}
}