369 lines
13 KiB
Plaintext
369 lines
13 KiB
Plaintext
output file "Password Generator"
|
|
include "Tlbx GameplayKit.incl"
|
|
|
|
begin enum
|
|
_mApplication
|
|
_mFile
|
|
_mEdit
|
|
end enum
|
|
|
|
begin enum 1
|
|
_iSeparator
|
|
_iPreferences
|
|
end enum
|
|
|
|
begin enum
|
|
_iCreate
|
|
_iSeparator2
|
|
_iSave
|
|
_iPrint
|
|
_iSeparator4
|
|
_iClose
|
|
end enum
|
|
|
|
_window = 1
|
|
begin enum output 1
|
|
_passwordScroll
|
|
_passwordView
|
|
_offscreenPrintView
|
|
_optionsHelp
|
|
_checkOmitIs
|
|
_checkOmitOs
|
|
_checkOmitSs
|
|
_checkOmit2s
|
|
_charactersLongLabel
|
|
_passwordLengthField
|
|
_pwAmountLabel
|
|
_pwAmountField
|
|
_seedLabel
|
|
_seedField
|
|
_helpBtn
|
|
_bottomLine
|
|
_saveBtn
|
|
_printBtn
|
|
_createPasswordsBtn
|
|
end enum
|
|
|
|
_helpPopover = 2
|
|
begin enum 1
|
|
_popoverLabel
|
|
end enum
|
|
|
|
_savePanel = 1
|
|
_pwLenAlert = 2
|
|
|
|
|
|
void local fn BuildMenus
|
|
// application
|
|
menu _mApplication, _iSeparator
|
|
menu _mApplication, _iPreferences,, @"Preferences…", @","
|
|
|
|
// file
|
|
menu _mFile, -1,, @"File"
|
|
menu _mFile, _iCreate,, @"Create passwords", @"p"
|
|
menu _mFile, _iSeparator2
|
|
menu _mFile, _iSave,, @"Save", @"s"
|
|
menu _mFile, _iPrint,, @"Print", @"p"
|
|
menu _mFile, _iSeparator4
|
|
menu _mFile, _iClose,, @"Close", @"w"
|
|
MenuItemSetAction( _mFile, _iClose, @"performClose:" )
|
|
|
|
editmenu _mEdit
|
|
end fn
|
|
|
|
void local fn BuildWindow
|
|
long tag
|
|
|
|
CGRect r = fn CGRectMake( 0, 0, 672, 460 )
|
|
window _window, @"Rosetta Code Password Generator", r//, NSWindowStyleMaskTitled + NSWindowStyleMaskClosable + NSWindowStyleMaskMiniaturizable
|
|
WindowSetContentMinSize( _window, fn CGSizeMake(310,386) )
|
|
|
|
r = fn CGRectMake( 20, 73, 515, 370 )
|
|
scrollview _passwordScroll, r, NSLineBorder,,_window
|
|
ViewSetAutoresizingMask( _passwordScroll, NSViewWidthSizable + NSViewHeightSizable )
|
|
|
|
textview _passwordView, r, _passwordScroll,, _window
|
|
TextViewSetTextContainerInset( _passwordView, fn CGSizeMake( 10, 15 ) )
|
|
TextSetFontWithName( _passwordView, @"Menlo", 13.0 )
|
|
|
|
r = fn CGRectMake( -600, -600, 450, 405 )
|
|
textview _offscreenPrintView, r,,, _window
|
|
TextSetFontWithName( _offscreenPrintView, @"Menlo", 13.0 )
|
|
TextSetColor( _offscreenPrintView, fn ColorBlack )
|
|
TextViewSetBackgroundColor( _offscreenPrintView, fn ColorWhite )
|
|
|
|
r = fn CGRectMake( 547, 424, 60, 16 )
|
|
textlabel _optionsHelp, @"Exclude:", r, _window
|
|
|
|
r = fn CGRectMake( 607, 425, 41, 14 )
|
|
button _checkOmitIs, YES, NSControlStateValueOff, @"Il1", r, NSButtonTypeSwitch
|
|
ViewSetToolTip( _checkOmitIs, @"Omit similar characters I, l and 1." )
|
|
r = fn CGRectOffset( r, 0, -24 )
|
|
button _checkOmitOs, YES ,NSControlStateValueOff, @"O0", r, NSButtonTypeSwitch
|
|
ViewSetToolTip( _checkOmitOs, @"Omit similar characters O and 0." )
|
|
r = fn CGRectOffset( r, 0, -24 )
|
|
button _checkOmitSs, YES, NSControlStateValueOff, @"5S", r, NSButtonTypeSwitch
|
|
ViewSetToolTip( _checkOmitSs, @"Omit similar characters 5 and S." )
|
|
r = fn CGRectOffset( r, 0, -24 )
|
|
button _checkOmit2s, YES, NSControlStateValueOff, @"2Z", r, NSButtonTypeSwitch
|
|
ViewSetToolTip( _checkOmit2s, @"Omit similar characters 2 and Z." )
|
|
|
|
r = fn CGRectMake( 549, 322, 103, 16 )
|
|
textlabel _charactersLongLabel, @"Chars (4-50)", r, _window
|
|
|
|
r = fn CGRectMake( 549, 298, 103, 21 )
|
|
textfield _passwordLengthField, YES, @"25", r,_window
|
|
TextFieldSetBordered( _passwordLengthField, YES )
|
|
ControlSetAlignment(_passwordLengthField, NSTextAlignmentCenter )
|
|
ControlSetFormat( _passwordLengthField, @"0123456789", YES, 2, 0 )
|
|
ViewSetToolTip( _passwordLengthField, @"Set password length from 4 to 50." )
|
|
|
|
r = fn CGRectMake( 549, 263, 103, 16 )
|
|
textlabel _pwAmountLabel, @"Passwords:", r, _window
|
|
|
|
r = fn CGRectMake( 549, 240, 103, 21 )
|
|
textfield _pwAmountField, YES, @"100", r,_window
|
|
TextFieldSetBordered( _pwAmountField, YES )
|
|
ControlSetAlignment( _pwAmountField, NSTextAlignmentCenter )
|
|
ControlSetFormat( _pwAmountField, @"0123456789", YES, 4, 0 )
|
|
ViewSetToolTip( _pwAmountField, @"Enter number of passwords to generate." )
|
|
|
|
r = fn CGRectMake( 549, 205, 103, 16 )
|
|
textlabel _seedLabel, @"Seed value:", r, _window
|
|
|
|
r = fn CGRectMake( 549, 182, 103, 21 )
|
|
textfield _seedField, YES, , r,_window
|
|
TextFieldSetBordered( _seedField, YES )
|
|
ControlSetAlignment(_seedField, NSTextAlignmentCenter )
|
|
ControlSetFormat( _seedField, @"0123456789", YES, 6, 0 )
|
|
ViewSetToolTip( _seedField, @"Enter optional random seed number." )
|
|
|
|
for tag = _optionsHelp to _seedField
|
|
ViewSetAutoresizingMask( tag, NSViewMinXMargin + NSViewMinYMargin )
|
|
next
|
|
|
|
r = fn CGRectMake( 631, 70, 25, 25 )
|
|
button _helpBtn, YES,,, r, NSButtonTypeMomentaryLight, NSBezelStyleHelpButton, _window
|
|
ViewSetToolTip( _helpBtn, @"Click for application help instructions." )
|
|
ViewSetAutoresizingMask( _helpBtn, NSViewMinXMargin + NSViewMaxYMargin )
|
|
|
|
r = fn CGRectMake( 20, 55, 632, 5 )
|
|
box _bottomline,, r, NSBoxSeparator
|
|
ViewSetAutoresizingMask( _bottomline, NSViewWidthSizable + NSViewMaxYMargin )
|
|
|
|
r = fn CGRectMake( 20, 15, 62, 32 )
|
|
button _printBtn, YES, , @"Print…", r, NSButtonTypeMomentaryLight, NSBezelStyleRegularSquare, _window
|
|
ViewSetAutoresizingMask( _printBtn, NSViewMaxXMargin + NSViewMaxYMargin )
|
|
|
|
r = fn CGRectMake( 91, 15, 62, 32 )
|
|
button _saveBtn, YES, , @"Save…", r, NSButtonTypeMomentaryLight, NSBezelStyleRegularSquare, _window
|
|
ViewSetAutoresizingMask( _saveBtn, NSViewMaxXMargin + NSViewMaxYMargin )
|
|
|
|
r = fn CGRectMake( 522, 15, 131, 32 )
|
|
button _createPasswordsBtn, YES, , @"Create passwords", r, NSButtonTypeMomentaryLight, NSBezelStyleRegularSquare, _window
|
|
ViewSetAutoresizingMask( _createPasswordsBtn, NSViewMinXMargin + NSViewMaxYMargin )
|
|
end fn
|
|
|
|
void local fn BuildPopover
|
|
CFStringRef helpText = @"This application generates randomized passwords from 4 to 50 characters in length. "
|
|
helpText = fn StringByAppendingString( helpText, @"Theoretically, the number generated is limited only by system memory.\n\n" )
|
|
helpText = fn StringByAppendingString( helpText, @"Passwords will contain at least one each of the following character types:\n" )
|
|
helpText = fn StringByAppendingString( helpText, @"\tLowercase letters\t\t: a -> z\n" )
|
|
helpText = fn StringByAppendingString( helpText, @"\tUppercase letters\t\t: A -> Z\n" )
|
|
helpText = fn StringByAppendingString( helpText, @"\tNumbers\t\t\t\t: 0 -> 9\n" )
|
|
helpText = fn StringByAppendingString( helpText, @"\tSpecial characters\t: !\"#$%&'()*+,-./:;<=>?@[]^_{|}~\n\n" )
|
|
helpText = fn StringByAppendingString( helpText, @"You can use checkboxes to exclude visually similar characters: Il1 O0 5S 2Z.\n\n" )
|
|
helpText = fn StringByAppendingString( helpText, @"This application offers two automatic levels of randomization. However you are " )
|
|
helpText = fn StringByAppendingString( helpText, @"welcome to enter a custom randomizer seed number in the box provided.\n\n" )
|
|
helpText = fn StringByAppendingString( helpText, @"Passwords can be copied to the pasteboard, saved to a text file, or printed." )
|
|
popover _helpPopover, (0,0,395,365), NSPopoverBehaviorTransient
|
|
textlabel _popoverLabel, helpText, (10,10,375,345)
|
|
end fn
|
|
|
|
void local fn OutOfBoundsAlert
|
|
CFStringRef alertStr = @"Passwords must be at least four characters long, but no more than 50 characters."
|
|
|
|
alert -_pwLenAlert,, @"Password length is out of bounds", alertStr, @"Okay", YES
|
|
AlertButtonSetKeyEquivalent( _pwLenAlert, 1, @"\e" )
|
|
AlertSetStyle( _pwLenAlert, NSAlertStyleWarning )
|
|
alert _pwLenAlert
|
|
end fn
|
|
|
|
|
|
local fn BuildPassword as CFStringRef
|
|
long i
|
|
CFArrayRef charArr = fn AppProperty( @"charArray" )
|
|
CFStringRef numbers = charArr[0]
|
|
CFStringRef uppercase = charArr[1]
|
|
CFStringRef lowercase = charArr[2]
|
|
CFStringRef symbols = charArr[3]
|
|
|
|
// Omit confusing letters selected by user, if any
|
|
if ( fn ButtonState( _checkOmitIs ) == NSControlStateValueOn )
|
|
numbers = fn StringByReplacingOccurrencesOfString( numbers, @"1", @"" )
|
|
uppercase = fn StringByReplacingOccurrencesOfString( uppercase, @"I", @"" )
|
|
lowercase = fn StringByReplacingOccurrencesOfString( lowercase, @"l", @"" )
|
|
end if
|
|
|
|
if ( fn ButtonState( _checkOmitOs ) == NSControlStateValueOn )
|
|
numbers = fn StringByReplacingOccurrencesOfString( numbers, @"0", @"" )
|
|
uppercase = fn StringByReplacingOccurrencesOfString( uppercase, @"O", @"" )
|
|
end if
|
|
|
|
if( fn ButtonState( _checkOmitSs ) == NSControlStateValueOn )
|
|
numbers = fn StringByReplacingOccurrencesOfString( numbers, @"5", @"" )
|
|
uppercase = fn StringByReplacingOccurrencesOfString( uppercase, @"S", @"" )
|
|
end if
|
|
|
|
if ( fn ButtonState( _checkOmit2s ) == NSControlStateValueOn )
|
|
numbers = fn StringByReplacingOccurrencesOfString( numbers, @"2", @"" )
|
|
uppercase = fn StringByReplacingOccurrencesOfString( uppercase, @"Z", @"" )
|
|
end if
|
|
|
|
// Build string pool from other character sets
|
|
CFStringRef allChars = fn StringWithFormat( @"%@%@%@%@", numbers, uppercase, lowercase, symbols )
|
|
|
|
// Begin construction password string with single random character from each character set
|
|
randomize
|
|
CFMutableStringRef pwStr = fn MutableStringWithCapacity(0)
|
|
CFStringRef rndNumberChar = fn StringWithFormat( @"%c", fn StringCharacterAtindex( numbers, rnd( len( numbers ) -1 ) ) )
|
|
CFStringRef rndUCaseChar = fn StringWithFormat( @"%c", fn StringCharacterAtindex( uppercase, rnd( len( uppercase ) -1 ) ) )
|
|
CFStringRef rndLCaseChar = fn StringWithFormat( @"%c", fn StringCharacterAtindex( lowercase, rnd( len( lowercase ) -1 ) ) )
|
|
CFStringRef rndSymbolChar = fn StringWithFormat( @"%c", fn StringCharacterAtindex( symbols, rnd( len( symbols ) -1 ) ) )
|
|
|
|
// Add first four randomized characters to password string
|
|
MutableStringAppendString( pwStr, fn StringWithFormat( @"%@%@%@%@", rndNumberChar, rndUCaseChar, rndLCaseChar, rndSymbolChar ) )
|
|
|
|
// Build array of characters for shuffling
|
|
CFMutableArrayRef mutArr = fn MutableArrayWithCapacity(0)
|
|
for i = 0 to len(allChars) - 1
|
|
unichar tempUni = fn StringCharacterAtIndex( allChars, i )
|
|
CFStringRef s = fn StringWithFormat( @"%c", tempUni )
|
|
MutableArrayInsertObjectAtIndex( mutArr, s, i )
|
|
next
|
|
|
|
// Shuffle character array for randomness
|
|
CFArrayRef rndStrArr = fn GKRandomSourceArrayByShufflingObjectsInArray( fn GKRandomSourceInit, mutArr )
|
|
CFStringRef rndStr = fn ArrayComponentsJoinedByString( rndStrArr, @"" )
|
|
|
|
long pwLength = fn StringIntegerValue( fn ControlStringValue( _passwordLengthField ) )
|
|
|
|
// Subtract 4 for mandatory charaacters already set
|
|
rndStr = fn StringSubstringToIndex( rndStr, pwLength - 4 )
|
|
MutableStringAppendString( pwStr, rndStr )
|
|
end fn = pwStr
|
|
|
|
|
|
void local fn RandomizeWithSeed
|
|
CFStringRef seedStr = fn ControlStringValue( _seedField )
|
|
|
|
if ( len(seedStr) > 0 )
|
|
long seedNum = fn StringIntegerValue( seedStr )
|
|
randomize seedNum
|
|
else
|
|
exit fn
|
|
end if
|
|
end fn
|
|
|
|
|
|
void local fn CreatePasswords
|
|
NSInteger i
|
|
CFMutableStringRef passwords = fn MutableStringWithCapacity(0)
|
|
long numberNeeded = fn StringIntegerValue( fn ControlStringValue( _pwAmountField ) )
|
|
|
|
// Get length of password designated by user
|
|
long pwLength = fn StringIntegerValue( fn ControlStringValue( _passwordLengthField ) )
|
|
|
|
if ( pwLength > 50 ) or ( pwLength < 4 )
|
|
fn OutOfBoundsAlert : exit fn
|
|
end if
|
|
|
|
fn RandomizeWithSeed
|
|
|
|
for i = 1 to numberNeeded
|
|
MutableStringAppendString( passwords, fn StringWithFormat( @"%4d. %@%@\n", i, fn BuildPassword, @"\n" ) )
|
|
next
|
|
TextSetString( _passwordView, passwords )
|
|
end fn
|
|
|
|
|
|
void local fn SaveFile
|
|
savepanel -_savePanel, @"Save file...", @"public.plain-text",,,, _true
|
|
SavePanelSetCanCreateDirectories( _savePanel, YES )
|
|
SavePanelSetAllowedFileTypes( _savePanel, @[@"txt"] )
|
|
SavePanelSetExtensionHidden( _savePanel, NO )
|
|
// Run savepanel; action captured in fn DoDialog
|
|
savepanel _savePanel
|
|
end fn
|
|
|
|
|
|
void local fn SetViewText( url as CFURLRef )
|
|
CFStringRef tempStr = fn StringWithContentsOfURL( url, NSUTF8StringEncoding, NULL )
|
|
WindowSetTitleWithRepresentedURL( _window, url )
|
|
TextSetString( _passwordView, tempStr )
|
|
end fn
|
|
|
|
|
|
void local fn PrintView( tag as long )
|
|
TextSetString( _offscreenPrintView, fn TextString( tag ) )
|
|
ViewPrint( _offscreenPrintView )
|
|
end fn
|
|
|
|
// Build character arrays at launch and save as application property
|
|
void local fn CreateCharactersDictionary
|
|
CFArrayRef charArray = @[¬
|
|
@"0123456789",¬
|
|
@"ABCDEFGHIJKLMNOPQRSTUVWXYZ",¬
|
|
@"abcdefghijklmnopqrstuvwxyz",¬
|
|
@"!\"#$%&'()*+,-./:;<=>?@[]^_{|}~"]
|
|
AppSetProperty( @"charArray", charArray )
|
|
end fn
|
|
|
|
|
|
void local fn DoAppEvent( ev as long )
|
|
select (ev)
|
|
case _appDidFinishLaunching
|
|
fn CreateCharactersDictionary
|
|
fn BuildMenus
|
|
fn BuildPopover
|
|
fn BuildWindow
|
|
case _appShouldTerminateAfterLastWindowClosed
|
|
AppEventSetBool(YES)
|
|
end select
|
|
end fn
|
|
|
|
|
|
void local fn DoMenu( menuID as long, itemID as long )
|
|
select (menuID)
|
|
case _mApplication
|
|
select (itemID)
|
|
case _iPreferences // show preferences window
|
|
end select
|
|
case _mFile
|
|
select (itemID)
|
|
case _iCreate : fn CreatePasswords
|
|
case _iSave : fn SaveFile
|
|
case _iPrint : fn PrintView( _passwordView )
|
|
end select
|
|
end select
|
|
end fn
|
|
|
|
|
|
void local fn DoDialog( ev as NSInteger, tag as NSInteger, wnd as NSInteger, obj as CFTypeRef )
|
|
select ( ev )
|
|
case _btnClick
|
|
select ( tag )
|
|
case _createPasswordsBtn : fn CreatePasswords
|
|
case _saveBtn : fn SaveFile
|
|
case _printBtn : fn PrintView( _passwordView )
|
|
case _helpBtn : PopoverShow( _helpPopover, CGRectZero, _helpBtn, CGRectMaxXEdge )
|
|
end select
|
|
end select
|
|
end fn
|
|
|
|
on appEvent fn DoAppEvent
|
|
on menu fn DoMenu
|
|
on dialog fn DoDialog
|
|
|
|
HandleEvents
|