@@ -11,6 +11,7 @@ use syntect::parsing::SyntaxSet;
1111use syntect:: highlighting:: ThemeSet ;
1212use syntect:: html:: highlighted_html_for_string;
1313use regex;
14+ use percent_encoding:: percent_decode_str;
1415
1516
1617// Security constants
@@ -129,6 +130,31 @@ fn create_secure_regex(pattern: &str) -> Result<regex::Regex, String> {
129130 . map_err ( |e| format ! ( "Failed to create regex: {}" , e) )
130131}
131132
133+ // Decode file:// URL using percent_encoding crate (already included via Tauri dependencies)
134+ // Supports UTF-8 multi-byte characters including Chinese characters
135+ fn decode_file_url ( url_str : & str ) -> String {
136+ // Step 1: Decode URL-encoded string to UTF-8 using percent_encoding crate
137+ // This automatically handles UTF-8 multi-byte characters (including Chinese)
138+ let decoded_url = percent_decode_str ( url_str)
139+ . decode_utf8_lossy ( )
140+ . to_string ( ) ;
141+
142+ // Step 2: Now handle file:// prefix and format on the decoded string
143+ let mut path = decoded_url. trim_start_matches ( "file://" ) . to_string ( ) ;
144+
145+ // Handle file:/// or file://localhost/ formats
146+ // macOS typically uses file:///absolute/path format (three slashes)
147+ if path. starts_with ( "//" ) {
148+ // file:////path -> /path (remove extra slashes)
149+ path = path. trim_start_matches ( "//" ) . to_string ( ) ;
150+ } else if path. starts_with ( "localhost/" ) {
151+ // file://localhost/path -> path
152+ path = path. trim_start_matches ( "localhost/" ) . to_string ( ) ;
153+ }
154+
155+ path
156+ }
157+
132158// Security validation functions
133159fn validate_file_path ( file_path : & str ) -> Result < PathBuf , String > {
134160 let path = Path :: new ( file_path) ;
@@ -746,10 +772,9 @@ pub fn run() {
746772 let app_handle = _app_handle;
747773 // Find the first markdown file in the opened URLs
748774 for url in urls {
749- // Convert URL to string and handle file:// URLs
750775 let url_str = url. as_str ( ) ;
751776 let file_path = if url_str. starts_with ( "file://" ) {
752- url_str . trim_start_matches ( "file://" ) . to_string ( )
777+ decode_file_url ( url_str )
753778 } else {
754779 url_str. to_string ( )
755780 } ;
@@ -766,6 +791,9 @@ pub fn run() {
766791
767792 // Also try to emit the event to the frontend if it's ready
768793 let _ = app_handle. emit ( "file-opened-via-os" , & validated_str) ;
794+ } else {
795+ // Add error log for debugging
796+ eprintln ! ( "Failed to validate file path: {}" , file_path) ;
769797 }
770798 break ;
771799 }
0 commit comments