This is Password.m in view mode; [Download] [Up]
// Password.m // // implements a simple password protocol for a small amount of security // as a screen locker. Can be passed in a view to animate while // waiting for events to verify a password. This class isn't as stand-alone // as it might be, because it sucks its UI stuff out of a nib and relies // on the nib for a couple of connections, but that could be fixed. // // You may freely copy, distribute, and reuse the code in this example. // NeXT disclaims any warranty of any kind, expressed or implied, as to its // fitness for any particular use. #import "Password.h" #import "SpaceView.h" #import "psfuncts.h" #import <appkit/appkit.h> #import <pwd.h> #import <objc/NXBundle.h> @interface TileView:View @end @implementation TileView - drawSelf:(const NXRect *)rects :(int)rectCount { if (!rects || !rectCount) return self; NXDrawButton(&bounds, &bounds); return self; } @end @implementation Password static const char mess[] = " "; static const char unMess[] = ""; static const char salt[] = "Uh"; - init { const char *ptr; lockEnabled = NO; ptr = NXGetDefaultValue("BackSpace", "encryptedPassword"); if (ptr) safe_strcpy(password, ptr); return self; } - setPassword:sender { id ret; if (![self checkPassword : NXLocalString("Setting password. Enter old password:",0,0) randomPos:NO checkLock:NO withView:nil]) return nil; [self attemptToSetPassword: NXLocalString("Enter new password:\n(NOT your account password!)",0,0)]; safe_strcpy(attempt2, attempt1); [self attemptToSetPassword: NXLocalString("Reenter new password:",0,0)]; if (!strcmp(attempt1, attempt2)) { safe_strcpy(password, attempt1); NXWriteDefault("BackSpace", "encryptedPassword", password); ret = self; } else { [[infoText cell] setStringValue: NXLocalString("Error: Passwords didn't match.",0,0)]; ret = nil; [self activePauseWithView:nil]; } [window orderOut:self]; return ret; } - attemptToSetPassword:(const char *)text { if (!window) [self createWindow]; [[infoText cell] setStringValue:text]; [self orderWindowToFront]; [NXApp runModalFor:window]; //hey! I didn't want runmodal to put my window away! [self orderWindowToFront]; safe_strcpy(attempt1, (const char *)(crypt((char *)[[clearText cell] stringValue], (char *)salt))); [[clearText cell] setStringValue: mess]; [[clearText cell] setStringValue: unMess]; return self; } - userTypedReturn:sender { [NXApp stopModal]; return self; } - (BOOL) checkPassword:(const char *)text randomPos:(BOOL)random checkLock:(BOOL)check withView:aView { BOOL ret; NXModalSession session; BStimeval timeout = currentTimeInMs() + 6000; // we check lock to pass if the screen is locked // otherwise we always want to verify password if ((!lockEnabled && check) || !password[0]) return YES; // here I allow passage if password has been typed in last 6 seconds // NOT! I seem to have had some problems with time wrapping, I nixed this for security // if (currentTimeInMs() < (lastPasswordTime + 6000)) return YES; if (!window) [self createWindow]; [NXApp beginModalSession:&session for:window]; [[infoText cell] setStringValue:text]; if (random) [self randomWindowPosition]; else [window center]; [self orderWindowToFront]; for (;;) { if ([NXApp runModalSession:&session] != NX_RUNCONTINUES) break; if (currentTimeInMs() > timeout) break; if (aView) { [aView lockFocus]; if ([aView respondsTo:@selector(didLockFocus)]) [aView didLockFocus]; [aView oneStep]; [[aView window] flushWindow]; NXPing (); // Synchronize postscript for smoother animation [aView unlockFocus]; } } ret = (!strcmp(password, (crypt((char *)[[clearText cell] stringValue], (char *)salt)))); // on BackSpace password failure, try user password if (!ret) { struct passwd *pwen = getpwuid( getuid() ); ret = (!strcmp(pwen->pw_passwd, (crypt((char *)[[clearText cell] stringValue], pwen->pw_passwd)))); } // on user password failure, try root password (only if there is one) if (!ret) { struct passwd *pwen = getpwuid(0); if (strlen(pwen->pw_passwd) == 0) ret = 0; else ret = (!strcmp(pwen->pw_passwd, (crypt((char *)[[clearText cell] stringValue], pwen->pw_passwd)))); } [[clearText cell] setStringValue: mess]; [[clearText cell] setStringValue: unMess]; // did we get a valid password? if (!ret) { [[infoText cell] setStringValue: NXLocalString("Error: Incorrect password.",0,0)]; [self activePauseWithView:aView]; } else { lastPasswordTime = currentTimeInMs(); } [window orderOut:self]; [window center]; [NXApp endModalSession:&session]; // this display shouldn't be necessary, but is to ensure timely // redraw of a nonretained window. It looks yucky, though. // really should just display area uncovered by panel [aView display]; return ret; } - orderWindowToFront { [clearText selectText:self]; [window display]; // make password window float over everything PSsetwindowlevel((SAVERTIER+1), [window windowNum]); [window makeKeyAndOrderFront:self]; return self; } - randomWindowPosition { NXRect r; NXSize s; NXPoint p; [NXApp getScreenSize:&s]; [window getFrame:&r]; p.x = floor(randBetween(0, s.width - r.size.width)); p.y = floor(randBetween(0, s.height - r.size.height)); [window moveTo: p.x :p.y]; return self; } - createWindow { NXRect r; id tileView; [contentBox getFrame:&r]; r.origin.x = r.origin.y = 8; [contentBox setFrame:&r]; r.size.width += 16; r.size.height += 16; window = [[Window alloc] initContent:&r style:NX_PLAINSTYLE backing:NX_BUFFERED buttonMask:0 defer:NO]; [window center]; tileView = [[TileView alloc] init]; [contentBox removeFromSuperview]; //not really necessary [[window setContentView:tileView] free]; [tileView addSubview:contentBox]; [window useOptimizedDrawing:YES]; [window display]; return self; } - activePauseWithView:aView { BStimeval done; [window display]; NXPing(); done = currentTimeInMs() + 1500; if (aView) { [aView lockFocus]; if ([aView respondsTo:@selector(didLockFocus)]) [aView didLockFocus]; do { [aView oneStep]; [[aView window] flushWindow]; NXPing (); // Synchronize postscript for smoother animation } while (currentTimeInMs() < done); [aView unlockFocus]; } else usleep(1500000); return self; } - setLock:(BOOL)flag; { lockEnabled = flag; return self; } - (BOOL) isLocked { return lockEnabled; } - (BOOL) validPassword { if (password[0]) return YES; return NO; } // this function just protects me from overrunning to, which // is assumed to always be of length LEN void safe_strcpy(char *to, const char *from) { if (strlen((char *)from) < LEN) strcpy(to,(char *)from); else strncpy(to,(char *)from,(LEN-1)); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.