diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index 8f829300..532dbc96 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -221,6 +221,7 @@ 4CC6DB7A17D23719002C6091 /* KPKNode+IconImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC6DB7917D23719002C6091 /* KPKNode+IconImage.m */; }; 4CC6DB7D17D23DCE002C6091 /* KPKUTIs.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC6DB7C17D23DCE002C6091 /* KPKUTIs.m */; }; 4CC7EA1B17807E7E0089D4F3 /* HNHRoundedTextFieldCellHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7EA1A17807E7E0089D4F3 /* HNHRoundedTextFieldCellHelper.m */; }; + 4CC87EA31847FDDA005AA18D /* MPAutotypeParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC87EA21847FDDA005AA18D /* MPAutotypeParser.m */; }; 4CCEDE2A179F203B008402BE /* MPOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CCEDE29179F203B008402BE /* MPOutlineView.m */; }; 4CCEDE2E179F213B008402BE /* MPNotifications.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CCEDE2D179F213B008402BE /* MPNotifications.m */; }; 4CCEDE32179F5B6C008402BE /* KPKDataStreamReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CCEDE31179F5B6C008402BE /* KPKDataStreamReader.m */; }; @@ -673,6 +674,8 @@ 4CC6DB7C17D23DCE002C6091 /* KPKUTIs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KPKUTIs.m; sourceTree = ""; }; 4CC7EA1917807E7E0089D4F3 /* HNHRoundedTextFieldCellHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HNHRoundedTextFieldCellHelper.h; sourceTree = ""; }; 4CC7EA1A17807E7E0089D4F3 /* HNHRoundedTextFieldCellHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HNHRoundedTextFieldCellHelper.m; sourceTree = ""; }; + 4CC87EA11847FDDA005AA18D /* MPAutotypeParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAutotypeParser.h; sourceTree = ""; }; + 4CC87EA21847FDDA005AA18D /* MPAutotypeParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAutotypeParser.m; sourceTree = ""; }; 4CCA7EEC1797866F00B0B55E /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/GeneralSettings.strings; sourceTree = ""; }; 4CCA7EEE1797867200B0B55E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/GeneralSettings.strings; sourceTree = ""; }; 4CCEDE28179F203B008402BE /* MPOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPOutlineView.h; sourceTree = ""; }; @@ -1317,6 +1320,8 @@ 4C89F523182FB4740069C73C /* MPAutotypeCommand.m */, 4CE296171842A166005F01CE /* MPAutotypePaste.h */, 4CE296181842A166005F01CE /* MPAutotypePaste.m */, + 4CC87EA11847FDDA005AA18D /* MPAutotypeParser.h */, + 4CC87EA21847FDDA005AA18D /* MPAutotypeParser.m */, ); name = Autotype; sourceTree = ""; @@ -1901,6 +1906,7 @@ 4C61EA0316D2FD0800AC519E /* MPOutlineViewController.m in Sources */, 4C69A73A16D589DF00EC1B1A /* HNHGradientView.m in Sources */, 4C65C79C16DD283900E32CFF /* MPToolbarButton.m in Sources */, + 4CC87EA31847FDDA005AA18D /* MPAutotypeParser.m in Sources */, 4C431BCD16E2A82800700A81 /* MPPasteBoardController.m in Sources */, 4CE8246F16E2E93400573141 /* MPOverlayWindowController.m in Sources */, 4CE8247516E2F2B900573141 /* MPOverlayView.m in Sources */, diff --git a/MacPass/MPAutotypeCommand.h b/MacPass/MPAutotypeCommand.h index ae867804..3d202af5 100644 --- a/MacPass/MPAutotypeCommand.h +++ b/MacPass/MPAutotypeCommand.h @@ -8,6 +8,8 @@ #import +@class KPKEntry; + /** * The Autotype command reperesent a capsualted Action that was determined by interpreting * Autotype field for a given entry. This is a class cluster and schould be considered the sole @@ -16,8 +18,6 @@ @interface MPAutotypeCommand : NSObject @property (readonly, copy) NSString *commandString; - -+ (NSArray *)commandsForCommandString:(NSString *)commands; /** * Determines the Keycode for the given keyboard layout for the supplied character * @@ -37,9 +37,14 @@ */ - (void)sendPressKey:(CGKeyCode)keyCode modifierFlags:(CGEventFlags)flags; +/** + * Convenience message to be sent for executing a simple paste command + */ +- (void)sendPasteKeyCode; + /** * Exectues the Autotype Command. This will be called by the autotype daemon. */ -- (void)execute; +- (void)executeWithEntry:(KPKEntry *)entry; @end diff --git a/MacPass/MPAutotypeCommand.m b/MacPass/MPAutotypeCommand.m index 608d8c3a..d2b6d708 100644 --- a/MacPass/MPAutotypeCommand.m +++ b/MacPass/MPAutotypeCommand.m @@ -11,143 +11,8 @@ #import -/* - - Autotype workflow: - - run copy/paste with content - - special keys: - - Tab {TAB} - Enter {ENTER} or ~ - Arrow Up {UP} - Arrow Down {DOWN} - Arrow Left {LEFT} - Arrow Right {RIGHT} - Insert {INSERT} or {INS} - Delete {DELETE} or {DEL} - Home {HOME} - End {END} - Page Up {PGUP} - Page Down {PGDN} - Backspace {BACKSPACE}, {BS} or {BKSP} - Break {BREAK} - Caps-Lock {CAPSLOCK} - Escape {ESC} - Windows Key {WIN} (equ. to {LWIN}) - Windows Key: left, right {LWIN}, {RWIN} - Apps / Menu {APPS} - Help {HELP} - Numlock {NUMLOCK} - Print Screen {PRTSC} - Scroll Lock {SCROLLLOCK} - F1 - F16 {F1} - {F16} - Numeric Keypad + {ADD} - Numeric Keypad - {SUBTRACT} - Numeric Keypad * {MULTIPLY} - Numeric Keypad / {DIVIDE} - Numeric Keypad 0 to 9 {NUMPAD0} to {NUMPAD9} - Shift + - Ctrl ^ - Alt % - + {+} - ^ {^} - % {%} - ~ {~} - (, ) {(}, {)} - [, ] {[}, {]} - {, } {{}, {}} - - special commands: - - {DELAY X} Delays X milliseconds. - {CLEARFIELD} Clears the contents of the edit control that currently has the focus (only single-line edit controls). - {VKEY X} - */ - @implementation MPAutotypeCommand -+ (NSArray *)commandsForCommandString:(NSString *)commands { - NSUInteger commandIndex = 0; - CGEventFlags modiferKeys = 0; - while(commandIndex <= [commands length]) { - /* Modifier Keys - Shift + - Ctrl ^ - Alt % - Enter ~ // No modifier! - */ - NSString *currentCommans = [commands substringFromIndex:commandIndex]; - NSCharacterSet *modifierKeySet = [NSCharacterSet characterSetWithCharactersInString:@"+^%"]; - NSRange modifierRange = [currentCommans rangeOfCharacterFromSet:modifierKeySet options:NSCaseInsensitiveSearch range:NSMakeRange(0, 1)]; - if(modifierRange.length != 0 && modifierRange.location == 0) { - /* starts with a special key */ - if([currentCommans hasPrefix:@"+"]) { - modiferKeys |= kCGEventFlagMaskAlphaShift; - } - if([currentCommans hasPrefix:@"^"]) { - modiferKeys |= kCGEventFlagMaskControl; - } - if([currentCommans hasPrefix:@"%"]) { - modiferKeys = kCGEventFlagMaskAlternate; - } - /* move the index and continue */ - commandIndex++; - continue; - } - if([currentCommans hasPrefix:@"{"]) { - NSRange closeBracket = [currentCommans rangeOfString:@"}"]; - if(closeBracket.length == 0) { - NSLog(@"Syntax error in Autotype Sequence %@ at index: %ld", commands, commandIndex); - return nil; - } - } - /* Search on to another bracket or a special key */ - - /* Command Keys - Tab {TAB} - Enter {ENTER} or ~ - Arrow Up {UP} - Arrow Down {DOWN} - Arrow Left {LEFT} - Arrow Right {RIGHT} - Insert {INSERT} or {INS} - Delete {DELETE} or {DEL} - Home {HOME} - End {END} - Page Up {PGUP} - Page Down {PGDN} - Backspace {BACKSPACE}, {BS} or {BKSP} - Break {BREAK} - Caps-Lock {CAPSLOCK} - Escape {ESC} - Windows Key {WIN} (equ. to {LWIN}) - Windows Key: left, right {LWIN}, {RWIN} - Apps / Menu {APPS} - Help {HELP} - Numlock {NUMLOCK} - Print Screen {PRTSC} - Scroll Lock {SCROLLLOCK} - F1 - F16 {F1} - {F16} - Numeric Keypad + {ADD} - Numeric Keypad - {SUBTRACT} - Numeric Keypad * {MULTIPLY} - Numeric Keypad / {DIVIDE} - Numeric Keypad 0 to 9 {NUMPAD0} to {NUMPAD9} - + {+} - ^ {^} - % {%} - ~ {~} - (, ) {(}, {)} - [, ] {[}, {]} - {, } {{}, {}} - - */ - } - return nil; -} - - (void)sendPressKey:(CGKeyCode)keyCode modifierFlags:(CGEventFlags)flags { CGEventRef pressKey = CGEventCreateKeyboardEvent (NULL, keyCode, YES); CGEventRef releaseKey = CGEventCreateKeyboardEvent (NULL, keyCode, NO); @@ -260,8 +125,8 @@ return (CGKeyCode)virtualKeyCode; } - - -- (void)execute {} +- (void)executeWithEntry:(KPKEntry *)entry { + NSAssert(NO, @"Not Implemented"); +} @end diff --git a/MacPass/MPAutotypeParser.h b/MacPass/MPAutotypeParser.h new file mode 100644 index 00000000..fa4dd61f --- /dev/null +++ b/MacPass/MPAutotypeParser.h @@ -0,0 +1,15 @@ +// +// MPAutotypeParser.h +// MacPass +// +// Created by Michael Starke on 28/11/13. +// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved. +// + +#import + +@interface MPAutotypeParser : NSObject + ++ (NSArray *)commandsForCommandString:(NSString *)commands; + +@end diff --git a/MacPass/MPAutotypeParser.m b/MacPass/MPAutotypeParser.m new file mode 100644 index 00000000..24fae40c --- /dev/null +++ b/MacPass/MPAutotypeParser.m @@ -0,0 +1,163 @@ +// +// MPAutotypeParser.m +// MacPass +// +// Created by Michael Starke on 28/11/13. +// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved. +// + +#import "MPAutotypeParser.h" + +#import "NSString+Placeholder.h" + +NSString *const kMPAutotypeKeyShift = @"+"; +NSString *const kMPAutotypeKeyControl = @"^"; +NSString *const kMPAutotypeKeyAlt = @"%"; +NSString *const kMPAutotypeKeyEnter = @"~"; +NSString *const kMPAutptypeCommandEnter = @"{ENTER}"; + +@implementation MPAutotypeParser + +/* + Tab {TAB} + Enter {ENTER} or ~ + Arrow Up {UP} + Arrow Down {DOWN} + Arrow Left {LEFT} + Arrow Right {RIGHT} + Insert {INSERT} or {INS} + Delete {DELETE} or {DEL} + Home {HOME} + End {END} + Page Up {PGUP} + Page Down {PGDN} + Backspace {BACKSPACE}, {BS} or {BKSP} + Break {BREAK} + Caps-Lock {CAPSLOCK} + Escape {ESC} + Windows Key {WIN} (equ. to {LWIN}) + Windows Key: left, right {LWIN}, {RWIN} + Apps / Menu {APPS} + Help {HELP} + Numlock {NUMLOCK} + Print Screen {PRTSC} + Scroll Lock {SCROLLLOCK} + F1 - F16 {F1} - {F16} + Numeric Keypad + {ADD} + Numeric Keypad - {SUBTRACT} + Numeric Keypad * {MULTIPLY} + Numeric Keypad / {DIVIDE} + Numeric Keypad 0 to 9 {NUMPAD0} to {NUMPAD9} + Shift + + Ctrl ^ + Alt % + + {+} + ^ {^} + % {%} + ~ {~} + (, ) {(}, {)} + [, ] {[}, {]} + {, } {{}, {}} + + special commands: + + {DELAY X} Delays X milliseconds. + {CLEARFIELD} Clears the contents of the edit control that currently has the focus (only single-line edit controls). + {VKEY X} + */ ++ (NSArray *)commandsForCommandString:(NSString *)commands { + NSUInteger commandIndex = 0; + CGEventFlags modiferKeys = 0; + while(commandIndex <= [commands length]) { + /* Modifier Keys + Shift + + Ctrl ^ + Alt % + */ + NSString *currentCommands = [commands substringFromIndex:commandIndex]; + NSCharacterSet *modifierKeySet = [NSCharacterSet characterSetWithCharactersInString:@"+^%"]; + NSRange modifierRange = [currentCommands rangeOfCharacterFromSet:modifierKeySet options:NSCaseInsensitiveSearch range:NSMakeRange(0, 1)]; + if(modifierRange.length != 0 && modifierRange.location == 0) { + /* starts with a special key */ + if([currentCommands hasPrefix:kMPAutotypeKeyShift]) { + modiferKeys |= kCGEventFlagMaskAlphaShift; + } + if([currentCommands hasPrefix:kMPAutotypeKeyControl]) { + modiferKeys |= kCGEventFlagMaskControl; + } + if([currentCommands hasPrefix:kMPAutotypeKeyAlt]) { + modiferKeys = kCGEventFlagMaskAlternate; + } + /* move the index and continue */ + commandIndex++; + continue; + } + if([currentCommands hasPrefix:@"{"]) { + /* Commands reset the modifiers */ + modiferKeys = 0; + NSRange closeBracket = [currentCommands rangeOfString:@"}"]; + if(closeBracket.length == 0) { + NSLog(@"Syntax error in Autotype Sequence %@ at index: %ld", commands, commandIndex); + return nil; + } + NSString *singleCommand = [currentCommands substringWithRange:NSMakeRange(0, closeBracket.location)]; + + } + else { + + } + /* Search on to another bracket or a special key */ + + /* Command Keys + Tab {TAB} + Enter {ENTER} or ~ + Arrow Up {UP} + Arrow Down {DOWN} + Arrow Left {LEFT} + Arrow Right {RIGHT} + Insert {INSERT} or {INS} + Delete {DELETE} or {DEL} + Home {HOME} + End {END} + Page Up {PGUP} + Page Down {PGDN} + Backspace {BACKSPACE}, {BS} or {BKSP} + Break {BREAK} + Caps-Lock {CAPSLOCK} + Escape {ESC} + Windows Key {WIN} (equ. to {LWIN}) + Windows Key: left, right {LWIN}, {RWIN} + Apps / Menu {APPS} + Help {HELP} + Numlock {NUMLOCK} + Print Screen {PRTSC} + Scroll Lock {SCROLLLOCK} + F1 - F16 {F1} - {F16} + Numeric Keypad + {ADD} + Numeric Keypad - {SUBTRACT} + Numeric Keypad * {MULTIPLY} + Numeric Keypad / {DIVIDE} + Numeric Keypad 0 to 9 {NUMPAD0} to {NUMPAD9} + + {+} + ^ {^} + % {%} + ~ {~} + (, ) {(}, {)} + [, ] {[}, {]} + {, } {{}, {}} {LCURL}, {RCURL} + + */ + } + return nil; +} + ++ (NSString *)_normalizeCommands:(NSString *)commandString { + /* Cache normalized Commands? */ + NSMutableString *mutableCommand = [commandString mutableCopy]; + [mutableCommand replaceOccurrencesOfString:kMPAutotypeKeyEnter withString:kMPAutptypeCommandEnter options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mutableCommand length])]; + [mutableCommand replaceOccurrencesOfString:@"{{}" withString:@"{LCURL}" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mutableCommand length])]; + [mutableCommand replaceOccurrencesOfString:@"{}}" withString:@"{RCURL}" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mutableCommand length])]; + return nil; +} + +@end diff --git a/MacPass/MPAutotypePaste.m b/MacPass/MPAutotypePaste.m index 8b0bdb02..df160ca8 100644 --- a/MacPass/MPAutotypePaste.m +++ b/MacPass/MPAutotypePaste.m @@ -9,18 +9,26 @@ #import "MPAutotypePaste.h" #import "MPPasteBoardController.h" -#import +#import "NSString+Placeholder.h" @implementation MPAutotypePaste /** * Simple copy paste action */ -- (void)execute { +- (void)executeWithEntry:(KPKEntry *)entry { if([self.commandString length] > 0) { MPPasteBoardController *controller = [MPPasteBoardController defaultController]; - [controller copyObjects:@[self.commandString]]; - [self sendPressKey:kVK_ANSI_V modifierFlags:kCGEventFlagMaskCommand]; + if([self.commandString isPlaceholder]) { + BOOL didReplace; + NSString *evaluatedPlaceholder = [self.commandString evaluatePlaceholderWithEntry:entry didReplace:&didReplace]; + [controller copyObjects:@[evaluatedPlaceholder]]; + } + else { + [controller copyObjects:@[self.commandString]]; + } + /* Find the correct key code! */ + [self sendPasteKeyCode]; } }