Skip to content

Instantly share code, notes, and snippets.

@tjw
Created May 28, 2013 22:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tjw/5666537 to your computer and use it in GitHub Desktop.
Save tjw/5666537 to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
#include <sys/stat.h>
/*
clang -Wall -O2 -fobjc-arc directory-url-unencoded.m -o directory-url-unencoded -framework Foundation
*/
int main(int argc, char *argv[])
{
NSString *tmpDir = NSTemporaryDirectory();
NSLog(@"working in %@ ...", tmpDir);
if (chdir([tmpDir UTF8String]) < 0) {
perror([tmpDir UTF8String]);
return 1;
}
// Rather than letting invalid UTF-8 make its way to the filesystem, this will actually create '%FF.ext' on the filesystem. Nice!
const char directoryName[] = {(char)0xff, '.', 'e', 'x', 't', '\0'};
if (mkdir(directoryName, 0700) < 0 && errno != EEXIST) {
perror(directoryName);
return 1;
}
// Sadly, this doesn't perform the same mapping, reporting nil instead of '%FF.ext'.
NSString *directoryNameString = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:directoryName length:strlen(directoryName)];
NSLog(@"directoryNameString = %@", directoryNameString);
// This properly escapes the % in the directory name.
NSURL *parentDirectoryURL = [[NSURL fileURLWithPath:tmpDir] URLByAppendingPathComponent:@"%FF.ext" isDirectory:YES];
NSLog(@"parentDirectoryURL = %@", parentDirectoryURL);
assert([[parentDirectoryURL absoluteString] rangeOfString:@"%25FF"].location != NSNotFound);
// We still have a properly escaped % in the directory name
NSURL *fileURL = [parentDirectoryURL URLByAppendingPathComponent:@"file"];
NSLog(@"fileURL = %@", fileURL);
assert([[fileURL absoluteString] rangeOfString:@"%25FF"].location != NSNotFound);
[[NSData data] writeToURL:fileURL options:0 error:NULL];
// Now things start to go off the rails. NSFileManager or NSURL incorrectly decodes the %25FF into %FF in the URLs for the child URLs.
NSArray *childrenURLs = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:parentDirectoryURL includingPropertiesForKeys:nil options:0 error:NULL];
assert([childrenURLs count] == 1);
NSLog(@"childrenURLs = %@", childrenURLs);
for (NSURL *childURL in childrenURLs) {
NSLog(@"childURL = %@", childURL);
// ... until finally we can't get the last path component (since the path is no longer a valid UTF-8 string).
NSString *filename = [childURL lastPathComponent];
NSLog(@"filename = %@", filename);
assert([filename isEqual:@"file"]);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment