home *** CD-ROM | disk | FTP | other *** search
- //
- // MiscStringUNIX.m
- // Written by Don Yacktman (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
- {
- if (!aString) return nil; // maybe we should _strip_ extensions here
- if (![self endcmp:aString]) return self;
- if ([self charAt:(length - 1)] != theMiscExtensionSeparator)
- [self addCharToEndOfString:theMiscExtensionSeparator];
- [self cat:aString];
- 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));
- }
-
- - setDirectory:(const char *)dir file:(const char *)file
- {
- return [self setFromFormat:"%s/%s", dir, file];
- }
-
- - initDirectory:(const char *)dir file:(const char *)file
- {
- return [self initFromFormat:"%s/%s", dir, file];
- }
-
- @end
-