From 24c8d8efc818223062e59c05d2e60bfd4942e315 Mon Sep 17 00:00:00 2001 From: Michael Starke Date: Tue, 12 Dec 2017 15:19:24 +0100 Subject: [PATCH] Pickcharparser now can handle non-default checkbox formats --- MacPass/MPPickcharsParser.h | 2 - MacPass/MPPickcharsParser.m | 138 +++++++++++++++++++++------ MacPass/MPPickcharsParser_Private.h | 1 - MacPassTests/MPTestPickcharsParser.m | 5 +- 4 files changed, 112 insertions(+), 34 deletions(-) diff --git a/MacPass/MPPickcharsParser.h b/MacPass/MPPickcharsParser.h index 659fd27a..401c2685 100644 --- a/MacPass/MPPickcharsParser.h +++ b/MacPass/MPPickcharsParser.h @@ -14,8 +14,6 @@ @property (readonly) BOOL convertToDownArrows; @property (readonly) NSUInteger pickCount; // count to pick - 0 if unlimted @property (readonly) NSUInteger checkboxOffset; -@property (readonly, copy) NSString *checkboxFormat; - /** Initializes the parser with the given option string. diff --git a/MacPass/MPPickcharsParser.m b/MacPass/MPPickcharsParser.m index a13feb3a..82491b75 100644 --- a/MacPass/MPPickcharsParser.m +++ b/MacPass/MPPickcharsParser.m @@ -15,7 +15,8 @@ typedef NS_ENUM(NSInteger, MPPickCharOffsetType) { MPPickCharOffsetTypeNone, - MPPickCharOffsetTypeCharacter, + MPPickCharOffsetTypeLowerCaseCharacter, + MPPickCharOffsetTypeUpperCaseCharacter, MPPickCharOffsetTypeNumber, }; @@ -25,12 +26,18 @@ struct MPPickCharOffset { }; typedef struct MPPickCharOffset MPPickCharOffset; -MPPickCharOffset MPMakePickCharCharacterOffset(NSUInteger offset) { - MPPickCharOffset offsetStruct = {MPPickCharOffsetTypeCharacter, offset}; +MPPickCharOffset MPMakePickCharUpperCaseCharacterOffset(unichar c) { + MPPickCharOffset offsetStruct = {MPPickCharOffsetTypeUpperCaseCharacter, c - 'A'}; return offsetStruct; } -MPPickCharOffset MPMakePickCharNumberOffset(NSUInteger offset) { - MPPickCharOffset offsetStruct = {MPPickCharOffsetTypeNumber, offset}; + +MPPickCharOffset MPMakePickCharLowerCaseCharacterOffset(unichar c) { + MPPickCharOffset offsetStruct = {MPPickCharOffsetTypeLowerCaseCharacter, c - 'a'}; + return offsetStruct; +} + +MPPickCharOffset MPMakePickCharNumberOffset(unichar c) { + MPPickCharOffset offsetStruct = {MPPickCharOffsetTypeNumber, c - '0'}; return offsetStruct; } @@ -39,6 +46,19 @@ MPPickCharOffset MPMakeInvalidPickCharOffset(void) { return offset; } +MPPickCharOffset MPMakePickCharOffset(unichar character) { + if(character >= '0' && character <= '9') { + return MPMakePickCharNumberOffset(character); + } + else if(character >= 'a' && character <= 'z') { + return MPMakePickCharLowerCaseCharacterOffset(character); + } + else if(character >= 'A' && character <= 'Z') { + return MPMakePickCharUpperCaseCharacterOffset(character); + } + return MPMakeInvalidPickCharOffset(); +} + BOOL MPIsValidPickCharOffset(MPPickCharOffset offset) { return (offset.type != MPPickCharOffsetTypeNone); } @@ -48,9 +68,22 @@ NSInteger numberOffset(MPPickCharOffset offset) { } NSInteger characterOffset(MPPickCharOffset offset) { - return (offset.type == MPPickCharOffsetTypeCharacter ? offset.offset : 0); + switch(offset.type) { + case MPPickCharOffsetTypeUpperCaseCharacter: + case MPPickCharOffsetTypeLowerCaseCharacter: + return offset.offset; + default: + return 0; + } } +typedef NSUInteger (^MPPickcharOffsetConverter)(NSInteger offset); + +@interface MPPickcharsParser () { + NSDictionary *_offsetConverter; +} +@end + @implementation MPPickcharsParser - (instancetype)init { @@ -65,6 +98,7 @@ NSInteger characterOffset(MPPickCharOffset offset) { _checkboxOffset = 0; _convertToDownArrows = NO; _hideCharacters = YES; + _offsetConverter = nil; [self _parseOptions:options]; } return self; @@ -75,23 +109,13 @@ NSInteger characterOffset(MPPickCharOffset offset) { return string; } NSMutableString *mutableString = [[NSMutableString alloc] init]; - BOOL isFirst = NO; for(NSString *substring in string.composedCharacters) { if(substring.length != 1) { NSLog(@"Pickchars: Unsupported character %@ for conversion to down arrows, skipping!", substring); continue; } - MPPickCharOffset offset = MPMakeInvalidPickCharOffset(); unichar character = [substring characterAtIndex:0]; - if(character >= '0' && character <= '9') { - offset = MPMakePickCharNumberOffset(character - '0'); - } - else if(character >= 'a' && character <= 'z') { - offset = MPMakePickCharCharacterOffset(character - 'a'); - } - else if(character >= 'A' && character <= 'Z') { - offset = MPMakePickCharCharacterOffset(character - 'A'); - } + MPPickCharOffset offset = MPMakePickCharOffset(character); [self _appendKeyCommandsForOffset:offset toString:mutableString]; } return [mutableString copy]; @@ -102,18 +126,13 @@ NSInteger characterOffset(MPPickCharOffset offset) { return; } NSUInteger actualOffset = self.checkboxOffset; - switch(offset.type) { - case MPPickCharOffsetTypeNumber: - actualOffset += offset.offset; - break; - case MPPickCharOffsetTypeCharacter: - actualOffset += offset.offset; - break; - case MPPickCharOffsetTypeNone: - default: - break; + MPPickcharOffsetConverter convertBlock = _offsetConverter[@(offset.type)]; + if(convertBlock) { + actualOffset += convertBlock(offset.offset); + } + else { + actualOffset += offset.offset; } - /* todo respect format definition */ while (actualOffset--) { [string appendString:kKPKAutotypeDown]; } @@ -201,7 +220,68 @@ NSInteger characterOffset(MPPickCharOffset offset) { return NO; } if(NSOrderedSame == [key compare:kKPKPlaceholderPickCharsOptionConvertFormat options:NSCaseInsensitiveSearch]) { - self.checkboxFormat = option; + if(option.length == 0) { + /* interpret no optoins as default too*/ + return YES; + } + /* parse range format */ + NSMutableDictionary *tmpOffsetMap = [[NSMutableDictionary alloc] init]; + NSUInteger index = 0; + NSUInteger collectedOffset = 0; + while(index < option.length) { + NSString *formatOption = [option substringWithRange:NSMakeRange(index, 1)]; + if([formatOption isEqualToString:@"0"]) { + if(tmpOffsetMap[@(MPPickCharOffsetTypeNumber)]) { + return NO; // double definition! + } + tmpOffsetMap[@(MPPickCharOffsetTypeNumber)] = ^NSInteger(NSUInteger offset) { + return offset + collectedOffset; + }; + collectedOffset += 10; + } + else if([formatOption isEqualToString:@"1"]) { + if(tmpOffsetMap[@(MPPickCharOffsetTypeNumber)]) { + return NO; // double definition! + } + tmpOffsetMap[@(MPPickCharOffsetTypeNumber)] = ^NSInteger(NSUInteger offset) { + NSInteger tmpOffset = offset - 1; + if(tmpOffset < 0) { + tmpOffset += 10; + } + return tmpOffset + collectedOffset; + }; + collectedOffset += 10; + } + else if([formatOption isEqualToString:@"a"]) { + if(tmpOffsetMap[@(MPPickCharOffsetTypeLowerCaseCharacter)]) { + return NO; // double definition! + } + + tmpOffsetMap[@(MPPickCharOffsetTypeLowerCaseCharacter)] = ^NSInteger(NSUInteger offset) { + return offset + collectedOffset; + }; + collectedOffset += 26; + } + else if([formatOption isEqualToString:@"A"]) { + if(tmpOffsetMap[@(MPPickCharOffsetTypeUpperCaseCharacter)]) { + return NO; // double definition! + } + + tmpOffsetMap[@(MPPickCharOffsetTypeUpperCaseCharacter)] = ^NSInteger(NSUInteger offset) { + return offset + collectedOffset; + }; + collectedOffset += 26; + } + else if([formatOption isEqualToString:@"?"]) { + /* just collect skips */ + collectedOffset++; + } + else { + return NO; + } + index++; + } + _offsetConverter = [tmpOffsetMap copy]; return YES; } return NO; diff --git a/MacPass/MPPickcharsParser_Private.h b/MacPass/MPPickcharsParser_Private.h index 3b611b14..90fd4e99 100644 --- a/MacPass/MPPickcharsParser_Private.h +++ b/MacPass/MPPickcharsParser_Private.h @@ -14,6 +14,5 @@ @property NSUInteger checkboxOffset; @property BOOL convertToDownArrows; @property BOOL hideCharacters; -@property (copy) NSString *checkboxFormat; @end diff --git a/MacPassTests/MPTestPickcharsParser.m b/MacPassTests/MPTestPickcharsParser.m index 9e633801..a75391a7 100644 --- a/MacPassTests/MPTestPickcharsParser.m +++ b/MacPassTests/MPTestPickcharsParser.m @@ -23,7 +23,9 @@ XCTAssertEqual(NO, parser.hideCharacters); XCTAssertEqual(YES, parser.convertToDownArrows); XCTAssertEqual(11, parser.checkboxOffset); - XCTAssertEqualObjects(@"0?aA", parser.checkboxFormat); + + NSString *result = [parser processPickedString:@"1B0f"]; + } @@ -33,7 +35,6 @@ XCTAssertEqual(YES, parser.hideCharacters); // option invalid, default is YES XCTAssertEqual(NO, parser.convertToDownArrows); // option was invalid, default is NO XCTAssertEqual(20, parser.checkboxOffset); - XCTAssertEqualObjects(@"0A", parser.checkboxFormat); } - (void)testConvertToDownArrows {