This is MiscStringUNIX.m in view mode; [Download] [Up]
// // MiscStringUNIX.m // Written by Don Yacktman Copyright (c) 1993 by Don Yacktman. // Version 1.95 All rights reserved. // This notice may not be removed from this source code. // // This object is included in the MiscKit by permission from the author // and its use is governed by the MiscKit license, found in the file // "LICENSE.rtf" in the MiscKit distribution. Please refer to that file // for a list of all applicable permissions and restrictions. // #import <misckit/MiscString.h> static char theMiscPathSeparator = '/'; static char theMiscExtensionSeparator = '.'; @implementation MiscString(UNIX) // This category includes methods to support various UNIX features, // such as file/path name parsing and encryption of passwords. + setPathSeparator:(char)c { theMiscPathSeparator = c; return self; } + setExtensionSeparator:(char)c { theMiscExtensionSeparator = c; return self; } + (char)extensionSeparator { return theMiscExtensionSeparator; } + (char)pathSeparator { return theMiscPathSeparator; } - encrypt:salt { // encrypt as a UNIX password using the MiscString "salt" as the salt... // see crypt(3) for more info // The cast prevents a warning: -stringValue returns a const char *. // Assuming crypt() doesn't change the salt, the cast is OK. char *strv; if ([salt respondsTo:@selector(stringValue)]) strv = (char *)[salt stringValue]; else return nil; if (!(buffer && strv)) return nil; if (!length || !strlen(strv)) return nil; return [[[self class] alloc] initString:crypt(buffer, strv)]; } - fileNameFromZone:(NXZone *)zone { return [self extractPart:MISC_STRING_LAST useAsDelimiter:theMiscPathSeparator caseSensitive:YES fromZone:zone]; } - fileName { return [self fileNameFromZone:[self zone]]; } - pathNameFromZone:(NXZone *)zone { id temp = [self left:[self rspotOf:theMiscPathSeparator] fromZone:zone]; if (temp) return temp; return [[self class] new]; } - pathName { return [self pathNameFromZone:[self zone]]; } - fileExtensionFromZone:(NXZone *)zone { id temp = [self fileNameFromZone:[self zone]]; id extension = [temp extractPart:MISC_STRING_LAST useAsDelimiter:theMiscExtensionSeparator caseSensitive:YES fromZone:zone]; if ([temp isEqual:extension] || (0 == [temp rspotOf:theMiscExtensionSeparator occurrenceNum:0 caseSensitive:YES])) [extension setStringValue:""]; [temp free]; return extension; } - fileExtension { return [self fileExtensionFromZone:[self zone]]; } - fileBasenameFromZone:(NXZone *)zone { id base, temp = [self fileNameFromZone:[self zone]]; int right = [temp rspotOf:theMiscExtensionSeparator occurrenceNum:0 caseSensitive:YES] - 1; if (right < 0) right = length - 1; base = [temp midFrom:0 to:right fromZone:zone]; [temp free]; return (base ? base : [[self class] new]); } - fileBasename { return [self fileBasenameFromZone:[self zone]]; } - addExtensionIfNeeded:(const char *)aString { id ourExtension; if (!aString) return nil; // maybe we should _strip_ extensions here ourExtension = [self fileExtension]; if ( [ourExtension length] == 0 || [ourExtension cmp:aString] != 0 ) { if ([self charAt:(length - 1)] != theMiscExtensionSeparator) [self addChar:theMiscExtensionSeparator]; [self cat:aString]; } [ourExtension free]; return self; } - replaceHomeWithTilde { id homestr = [[self class] newWithString:NXHomeDirectory()]; if (![self compareTo:homestr n:[homestr length]]) { [self replaceFrom:0 length:[homestr length] withChar:'~']; } else { id home2 = [homestr pathName]; if (![home2 length]) return self; if (![self compareTo:home2 n:[home2 length]]) { [self replaceFrom:0 length:[home2 length]+1 withChar:'~']; } [home2 free]; } [homestr free]; return self; } - replaceTildeWithHome { // ***** I'd like to see this do proper csh substitution rather than // just the simple implementation done here. -don id home = [[self class] newWithString:NXHomeDirectory()]; if (buffer[0] == '~') { if ((buffer[1] == theMiscPathSeparator) || (length == 1)) [self replaceFrom:0 length:1 withString:home]; else { // This assumption of all users in the same dir. is bad -don id home2 = [home pathName]; [home2 addChar:theMiscPathSeparator]; [self replaceFrom:0 length:1 withString:home2]; [home2 free]; } } [home free]; return self; } - (BOOL)isRelativePath // Returns YES if the path is non-empty and does NOT begin with pathSeparator. { id tempPath = [self pathName]; if ([tempPath length] && ([tempPath charAt:0] != theMiscPathSeparator)) { [tempPath free]; return YES; } [tempPath free]; return NO; } - (BOOL)isAbsolutePath // Returns YES if the path is non-empty and DOES begin with pathSeparator. { id tempPath = [self pathName]; if ([tempPath length] && ([tempPath charAt:0] == theMiscPathSeparator)) { [tempPath free]; return YES; } [tempPath free]; return NO; } - (BOOL)doesExistInFileSystem // Returns YES if the a file exists at our path, and is visible to the user // id of the process. A NO can mean any number of things, but a YES // definitely indicates that the file is there and visible. { struct stat statBuff; if (!buffer) return NO; if (stat([self stringValue], &statBuff) == -1) return NO; return YES; } - (BOOL)isFileOfType:(MiscFileType)fileType // Returns YES if the named file exists, and is visible to the user id of // the process and it is a file of type fileType. A NO can mean any number // of things, but a YES definitely indicates that the file is there and // visible and of the fileType type. { struct stat statBuff; if (!buffer) return NO; if (stat([self stringValue], &statBuff) == -1) return NO; return ((statBuff.st_mode & fileType) == fileType); } - pathComponentAt:(int)index { if ((index < 0) || (index >= [self numberOfPathComponents])) return [[self class] newWithString:""]; return [self extractPart:([self isAbsolutePath] ? (index + 1) : index) useAsDelimiter:theMiscPathSeparator caseSensitive:YES fromZone:[self zone]]; } - (int)numberOfPathComponents { return ([self numOfChar:theMiscPathSeparator] - ([self isAbsolutePath] ? 1 : 0)); } /* * Modified [-setDirectory:file:] and [-initDirectory:file:] to use the * official misc path separator, rather than a hard-coded '/'. BJM 7/9/94 */ - setDirectory:(const char *)dir file:(const char *)file { return [self setFromFormat:"%s%c%s", dir, theMiscPathSeparator, file]; } - initDirectory:(const char *)dir file:(const char *)file { return [self initFromFormat:"%s%c%s", dir, theMiscPathSeparator, file]; } - (int)system { return system([self stringValue]); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.