fix(security): fix percent_decode to handle multi-byte UTF-8 properly
The previous implementation decoded percent-encoded bytes one at a time and cast each to char, which produces invalid characters for multi-byte UTF-8 sequences (e.g. Chinese filenames). Fixed to accumulate raw bytes first and convert to String at the end with proper UTF-8 validation.
This commit is contained in:
@@ -1624,29 +1624,29 @@ fn file_mkdir_route(
|
||||
}
|
||||
|
||||
fn percent_decode(s: &str) -> String {
|
||||
let mut result = String::with_capacity(s.len());
|
||||
let mut bytes = Vec::with_capacity(s.len());
|
||||
let mut chars = s.bytes();
|
||||
while let Some(b) = chars.next() {
|
||||
if b == b'%' {
|
||||
let h = chars.next().unwrap_or(0);
|
||||
let l = chars.next().unwrap_or(0);
|
||||
let hex = [h, l];
|
||||
if let Ok(s) = std::str::from_utf8(&hex) {
|
||||
if let Ok(val) = u8::from_str_radix(s, 16) {
|
||||
result.push(val as char);
|
||||
if let Ok(hex_str) = std::str::from_utf8(&hex) {
|
||||
if let Ok(val) = u8::from_str_radix(hex_str, 16) {
|
||||
bytes.push(val);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
result.push('%');
|
||||
result.push(h as char);
|
||||
result.push(l as char);
|
||||
bytes.push(b'%');
|
||||
bytes.push(h);
|
||||
bytes.push(l);
|
||||
} else if b == b'+' {
|
||||
result.push(' ');
|
||||
bytes.push(b' ');
|
||||
} else {
|
||||
result.push(b as char);
|
||||
bytes.push(b);
|
||||
}
|
||||
}
|
||||
result
|
||||
String::from_utf8(bytes).unwrap_or_else(|e| String::from_utf8_lossy(e.as_bytes()).into_owned())
|
||||
}
|
||||
|
||||
fn list_video_files(dir: &Path) -> Vec<VideoFileInfo> {
|
||||
|
||||
Reference in New Issue
Block a user