@@ -1767,29 +1767,39 @@ - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
1767
1767
// parse value
1768
1768
NSString *v = [arr objectAtIndex: 1 ];
1769
1769
1770
- // Ideally we don't decode anything here. The input parameters
1771
- // should be used as-in as there would be no reason for caller
1772
- // to encoder anything. For the line component it's a simple
1773
- // string, and the URL should already be a proper file:// URL
1774
- // with all the necessary characters (e.g. space) encoded and
1775
- // we can just pass it to NSURL as-in below.
1776
- // However, iTerm2 appears to encode the slashes as well
1777
- // resulting in URL that looks like
1778
- // file://%2Fsome%2Ffolder/file%20with%20space which is wrong
1779
- // as this doesn't form a valid URL. To accommodate that, we
1780
- // decode the URL, and later on manually parse it instead of
1781
- // relying on NSURL.
1782
- // See: https://github.com/macvim-dev/macvim/issues/1020.
1783
-
1784
- // BOOL decode = ![f isEqualToString:@"url"];
1785
- const BOOL decode = YES ;
1786
-
1787
- if (decode)
1788
- {
1770
+ // We need to decode the parameters here because most URL
1771
+ // parsers treat the query component as needing to be decoded
1772
+ // instead of treating it as is. It does mean that a link to
1773
+ // open file "/tmp/file name.txt" will be
1774
+ // mvim://open?url=file:///tmp/file%2520name.txt to encode a
1775
+ // URL of file:///tmp/file%20name.txt. This double-encoding is
1776
+ // intentional to follow the URL spec.
1789
1777
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11
1790
- v = [v stringByRemovingPercentEncoding ];
1778
+ v = [v stringByRemovingPercentEncoding ];
1791
1779
#else
1792
- v = [v stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
1780
+ v = [v stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
1781
+ #endif
1782
+
1783
+ if ([f isEqualToString: @" url" ]) {
1784
+ // Since the URL scheme uses a double-encoding due to a
1785
+ // file:// URL encoded in another mvim: one, existing tools
1786
+ // like iTerm2 could sometimes erroneously only do a single
1787
+ // encode. To maximize compatiblity, we re-encode invalid
1788
+ // characters if we detect them as they would not work
1789
+ // later on when we pass this string to URLWithString.
1790
+ //
1791
+ // E.g. mvim://open?uri=file:///foo%20bar => "file:///foo bar"
1792
+ // which is not a valid URL, so we re-encode it to
1793
+ // file:///foo%20bar here. The only important case is to
1794
+ // not touch the "%" character as it introduces ambiguity
1795
+ // and the re-encoding is a nice compatibility feature, but
1796
+ // the canonical form should be double-encoded, i.e.
1797
+ // mvim://open?uri=file:///foo%2520bar
1798
+ #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11
1799
+ NSMutableCharacterSet *charSet = [NSMutableCharacterSet characterSetWithCharactersInString: @" %" ];
1800
+ [charSet formUnionWithCharacterSet: NSCharacterSet .URLHostAllowedCharacterSet];
1801
+ [charSet formUnionWithCharacterSet: NSCharacterSet .URLPathAllowedCharacterSet];
1802
+ v = [v stringByAddingPercentEncodingWithAllowedCharacters: charSet];
1793
1803
#endif
1794
1804
}
1795
1805
@@ -1800,12 +1810,9 @@ - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
1800
1810
// Actually open the file.
1801
1811
NSString *file = [dict objectForKey: @" url" ];
1802
1812
if (file != nil ) {
1803
- // Instead of passing "file" to NSURL directly, we just manually
1804
- // parse the URL because the URL is already decoded and NSURL will
1805
- // get confused by special chars like spaces. See above
1806
- // explanation.
1807
- if ([file hasPrefix: @" file:///" ]) {
1808
- NSString *filePath = [file substringFromIndex: 7 ];
1813
+ NSURL *fileUrl = [NSURL URLWithString: file];
1814
+ if ([fileUrl isFileURL ]) {
1815
+ NSString *filePath = [fileUrl path ];
1809
1816
// Only opens files that already exist.
1810
1817
if ([[NSFileManager defaultManager ] fileExistsAtPath: filePath]) {
1811
1818
NSArray *filenames = [NSArray arrayWithObject: filePath];
@@ -1847,11 +1854,11 @@ - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
1847
1854
[alert addButtonWithTitle: NSLocalizedString(@" OK" ,
1848
1855
@" Dialog button" )];
1849
1856
1850
- [alert setMessageText: NSLocalizedString(@" Unknown File Protocol " ,
1851
- @" Unknown File Protocol dialog, title" )];
1857
+ [alert setMessageText: NSLocalizedString(@" Invalid File URL " ,
1858
+ @" Unknown Fie URL dialog, title" )];
1852
1859
[alert setInformativeText: [NSString stringWithFormat: NSLocalizedString(
1853
- @" Unknown protocol in \" %@ \" " ,
1854
- @" Unknown File Protocol dialog, text" ),
1860
+ @" Unknown file URL in \" %@ \" " ,
1861
+ @" Unknown file URL dialog, text" ),
1855
1862
file]];
1856
1863
1857
1864
[alert setAlertStyle: NSAlertStyleWarning];
0 commit comments