diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/SPTextView.h | 16 | ||||
-rw-r--r-- | Source/SPTextView.m | 172 | ||||
-rw-r--r-- | Source/SPUserManager.h | 3 | ||||
-rw-r--r-- | Source/SPUserManager.m | 87 |
4 files changed, 169 insertions, 109 deletions
diff --git a/Source/SPTextView.h b/Source/SPTextView.h index 07e42e43..4289bd40 100644 --- a/Source/SPTextView.h +++ b/Source/SPTextView.h @@ -38,6 +38,18 @@ @class SPCopyTable; @class NoodleLineNumberView; +typedef struct { + NSInteger location; // snippet location + NSInteger length; // snippet length + NSInteger task; // snippet task : -1 not valid, 0 select snippet +} SnippetControlInfo; + +typedef struct { + NSInteger snippet; // mirrored snippet index + NSInteger location; // mirrored snippet location + NSInteger length; // mirrored snippet length +} MirrorControlInfo; + @interface SPTextView : NSTextView <NSTextStorageDelegate> { IBOutlet SPDatabaseDocument *tableDocumentInstance; @@ -71,8 +83,8 @@ SPMySQLConnection *mySQLConnection; NSInteger mySQLmajorVersion; - NSInteger snippetControlArray[20][3]; - NSInteger snippetMirroredControlArray[20][3]; + SnippetControlInfo snippetControlArray[20]; + MirrorControlInfo snippetMirroredControlArray[20]; NSInteger snippetControlCounter; NSInteger snippetControlMax; NSInteger currentSnippetIndex; diff --git a/Source/SPTextView.m b/Source/SPTextView.m index 970869c1..3c6d7b53 100644 --- a/Source/SPTextView.m +++ b/Source/SPTextView.m @@ -1552,18 +1552,20 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS NSInteger i, j, k, deltaLength; NSRange mirroredRange; + SnippetControlInfo *currentSnippetRef = &snippetControlArray[currentSnippetIndex]; // Go through each defined mirrored snippet and update it for(i=0; i<=mirroredCounter; i++) { - if(snippetMirroredControlArray[i][0] == currentSnippetIndex) { + MirrorControlInfo *mirrorRef = &snippetMirroredControlArray[i]; + if(mirrorRef->snippet == currentSnippetIndex) { - deltaLength = snippetControlArray[currentSnippetIndex][1]-snippetMirroredControlArray[i][2]; + deltaLength = currentSnippetRef->length - mirrorRef->length; - mirroredRange = NSMakeRange(snippetMirroredControlArray[i][1], snippetMirroredControlArray[i][2]); + mirroredRange = NSMakeRange(mirrorRef->location, mirrorRef->length); NSString *mirroredString = nil; // For safety reasons @try{ - mirroredString = [[self string] substringWithRange:NSMakeRange(snippetControlArray[currentSnippetIndex][0], snippetControlArray[currentSnippetIndex][1])]; + mirroredString = [[self string] substringWithRange:NSMakeRange(currentSnippetRef->location, currentSnippetRef->length)]; } @catch(id ae) { NSLog(@"Error while parsing for mirrored snippets. %@", [ae description]); @@ -1576,26 +1578,26 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS [self shouldChangeTextInRange:mirroredRange replacementString:mirroredString]; [self replaceCharactersInRange:mirroredRange withString:mirroredString]; - snippetMirroredControlArray[i][2] = snippetControlArray[currentSnippetIndex][1]; + mirrorRef->length = currentSnippetRef->length; // If a completion list is open adjust the theCharRange and theParseRange if a mirrored snippet // was updated which is located before the initial position - if(completionIsOpen && snippetMirroredControlArray[i][1] < (NSInteger)completionParseRangeLocation) + if(completionIsOpen && mirrorRef->location < (NSInteger)completionParseRangeLocation) [completionPopup adjustWorkingRangeByDelta:deltaLength]; // Adjust all other snippets accordingly for(j=0; j<=snippetControlMax; j++) { - if(snippetControlArray[j][0] > -1) { - if(snippetControlArray[j][0]+snippetControlArray[j][1]>=snippetMirroredControlArray[i][1]) { - snippetControlArray[j][0] += deltaLength; + if(snippetControlArray[j].location > -1) { + if(snippetControlArray[j].location+snippetControlArray[j].length >= mirrorRef->location) { + snippetControlArray[j].location += deltaLength; } } } // Adjust all mirrored snippets accordingly for(k=0; k<=mirroredCounter; k++) { if(i != k) { - if(snippetMirroredControlArray[k][1] > snippetMirroredControlArray[i][1]) { - snippetMirroredControlArray[k][1] += deltaLength; + if(snippetMirroredControlArray[k].location > mirrorRef->location) { + snippetMirroredControlArray[k].location += deltaLength; } } } @@ -1625,15 +1627,16 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS // Place the caret at the end of the query favorite snippet // and finish snippet editing if(currentSnippetIndex == snippetControlMax) { - [self setSelectedRange:NSMakeRange(snippetControlArray[snippetControlMax][0] + snippetControlArray[snippetControlMax][1], 0)]; + [self setSelectedRange:NSMakeRange(snippetControlArray[snippetControlMax].location + snippetControlArray[snippetControlMax].length, 0)]; [self endSnippetSession]; return; } - if(currentSnippetIndex >= 0 && currentSnippetIndex < 20) { - if(snippetControlArray[currentSnippetIndex][2] == 0) { + if(currentSnippetIndex >= 0 && currentSnippetIndex < COUNT_OF(snippetControlArray)) { + SnippetControlInfo *currentSnippetRef = &snippetControlArray[currentSnippetIndex]; + if(currentSnippetRef->task == 0) { - NSRange r1 = NSMakeRange(snippetControlArray[currentSnippetIndex][0], snippetControlArray[currentSnippetIndex][1]); + NSRange r1 = NSMakeRange(currentSnippetRef->location, currentSnippetRef->length); NSRange r2; // Ensure the selection for nested snippets if it is at very end of the text buffer @@ -1718,13 +1721,9 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS mirroredCounter = -1; // reset snippet array - for(i=0; i<20; i++) { - snippetControlArray[i][0] = -1; // snippet location - snippetControlArray[i][1] = -1; // snippet length - snippetControlArray[i][2] = -1; // snippet task : -1 not valid, 0 select snippet - snippetMirroredControlArray[i][0] = -1; // mirrored snippet index - snippetMirroredControlArray[i][1] = -1; // mirrored snippet location - snippetMirroredControlArray[i][2] = -1; // mirrored snippet length + for(i=0; i<COUNT_OF(snippetControlArray); i++) { + snippetControlArray[i] = (SnippetControlInfo){ -1, -1, -1}; + snippetMirroredControlArray[i] = (MirrorControlInfo){-1, -1, -1}; } if(theSnippet == nil || ![theSnippet length]) return; @@ -1861,24 +1860,25 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS [snip flushCachedRegexData]; // Store found snippet range - snippetControlArray[snipCnt][0] = snipRange.location + targetRange.location; - snippetControlArray[snipCnt][1] = [theHintString length]; - snippetControlArray[snipCnt][2] = 0; + snippetControlArray[snipCnt].location = snipRange.location + targetRange.location; + snippetControlArray[snipCnt].length = [theHintString length]; + snippetControlArray[snipCnt].task = 0; [theHintString release]; // Adjust successive snippets - for(i=0; i<20; i++) - if(snippetControlArray[i][0] > -1 && i != snipCnt && snippetControlArray[i][0] > snippetControlArray[snipCnt][0]) - snippetControlArray[i][0] -= 3+((snipCnt>9)?2:1); + for(i=0; i<COUNT_OF(snippetControlArray); i++) + if(snippetControlArray[i].location > -1 && i != snipCnt && snippetControlArray[i].location > snippetControlArray[snipCnt].location) + snippetControlArray[i].location -= 3+((snipCnt>9)?2:1); } // Parse for mirrored snippets while([snip isMatchedByRegex:mirror_re]) { mirroredCounter++; - if(mirroredCounter > 19) { - NSLog(@"Only 20 mirrored snippet placeholders allowed."); + if(mirroredCounter >= COUNT_OF(snippetMirroredControlArray)) { + NSLog(@"Only %lu mirrored snippet placeholders allowed.",COUNT_OF(snippetMirroredControlArray)); + mirroredCounter--; //go back by one or the code below will do an out-of-bounds array access NSBeep(); break; } else { @@ -1897,14 +1897,14 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS [snip flushCachedRegexData]; // Store found mirrored snippet range - snippetMirroredControlArray[mirroredCounter][0] = snipCnt; - snippetMirroredControlArray[mirroredCounter][1] = snipRange.location + targetRange.location; - snippetMirroredControlArray[mirroredCounter][2] = 0; + snippetMirroredControlArray[mirroredCounter].snippet = snipCnt; + snippetMirroredControlArray[mirroredCounter].location = snipRange.location + targetRange.location; + snippetMirroredControlArray[mirroredCounter].length = 0; // Adjust successive snippets - for(i=0; i<20; i++) - if(snippetControlArray[i][0] > -1 && snippetControlArray[i][0] > snippetMirroredControlArray[mirroredCounter][1]) - snippetControlArray[i][0] -= 1+((snipCnt>9)?2:1); + for(i=0; i<COUNT_OF(snippetControlArray); i++) + if(snippetControlArray[i].location > -1 && snippetControlArray[i].location > snippetMirroredControlArray[mirroredCounter].location) + snippetControlArray[i].location -= 1+((snipCnt>9)?2:1); [snip flushCachedRegexData]; } @@ -1912,28 +1912,29 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS // Preset mirrored snippets with according snippet content if(mirroredCounter > -1) { for(i=0; i<=mirroredCounter; i++) { - if(snippetControlArray[snippetMirroredControlArray[i][0]][0] > -1 && snippetControlArray[snippetMirroredControlArray[i][0]][1] > 0) { - [snip replaceCharactersInRange:NSMakeRange(snippetMirroredControlArray[i][1]-targetRange.location, snippetMirroredControlArray[i][2]) - withString:[snip substringWithRange:NSMakeRange(snippetControlArray[snippetMirroredControlArray[i][0]][0]-targetRange.location, snippetControlArray[snippetMirroredControlArray[i][0]][1])]]; - snippetMirroredControlArray[i][2] = snippetControlArray[snippetMirroredControlArray[i][0]][1]; + MirrorControlInfo *mirrorRef = &snippetMirroredControlArray[i]; + SnippetControlInfo *snippetRef = &snippetControlArray[mirrorRef->snippet]; + if(snippetRef->location > -1 && snippetRef->length > 0) { + NSRange copyToRange = NSMakeRange(mirrorRef->location-targetRange.location, mirrorRef->length); + NSRange copyFromRange = NSMakeRange(snippetRef->location-targetRange.location, snippetRef->length); + [snip replaceCharactersInRange:copyToRange withString:[snip substringWithRange:copyFromRange]]; + mirrorRef->length = snippetRef->length; } // Adjust successive snippets - for(j=0; j<20; j++) - if(snippetControlArray[j][0] > -1 && snippetControlArray[j][0] > snippetMirroredControlArray[i][1]) - snippetControlArray[j][0] += snippetControlArray[snippetMirroredControlArray[i][0]][1]; + for(j=0; j<COUNT_OF(snippetControlArray); j++) + if(snippetControlArray[j].location > -1 && snippetControlArray[j].location > mirrorRef->location) + snippetControlArray[j].location += snippetRef->length; // Adjust successive mirrored snippets for(j=0; j<=mirroredCounter; j++) - if(snippetMirroredControlArray[j][1] > snippetMirroredControlArray[i][1]) - snippetMirroredControlArray[j][1] += snippetControlArray[snippetMirroredControlArray[i][0]][1]; + if(snippetMirroredControlArray[j].location > mirrorRef->location) + snippetMirroredControlArray[j].location += snippetRef->length; } } if(snippetControlCounter > -1) { // Store the end for tab out snippetControlMax++; - snippetControlArray[snippetControlMax][0] = targetRange.location + [snip length]; - snippetControlArray[snippetControlMax][1] = 0; - snippetControlArray[snippetControlMax][2] = 0; + snippetControlArray[snippetControlMax] = (SnippetControlInfo){targetRange.location + [snip length], 0, 0}; } // unescape escaped snippets and re-adjust successive snippet locations : \${1:a} → ${1:a} @@ -1945,13 +1946,13 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS NSInteger loc = escapeRange.location + targetRange.location; [snip flushCachedRegexData]; for(i=0; i<=snippetControlMax; i++) - if(snippetControlArray[i][0] > -1 && snippetControlArray[i][0] > loc) - snippetControlArray[i][0]--; + if(snippetControlArray[i].location > -1 && snippetControlArray[i].location > loc) + snippetControlArray[i].location--; // Adjust mirrored snippets if(mirroredCounter > -1) for(i=0; i<=mirroredCounter; i++) - if(snippetMirroredControlArray[i][0] > -1 && snippetMirroredControlArray[i][1] > loc) - snippetMirroredControlArray[i][1]--; + if(snippetMirroredControlArray[i].snippet > -1 && snippetMirroredControlArray[i].location > loc) + snippetMirroredControlArray[i].location--; } } @@ -1980,8 +1981,8 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS if(snippetControlCounter > -1) { // Find and select first defined snippet currentSnippetIndex = 0; - // Look for next defined snippet since snippet numbers must not serial like 1, 5, and 12 e.g. - while(snippetControlArray[currentSnippetIndex][0] == -1 && currentSnippetIndex < 20) + // Look for next defined snippet since snippet numbers might not be serial like 1, 5, and 12 e.g. + while(snippetControlArray[currentSnippetIndex].location == -1 && currentSnippetIndex < COUNT_OF(snippetControlArray)) currentSnippetIndex++; [self selectCurrentSnippet]; } @@ -2026,9 +2027,9 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS for(i=0; i<=snippetControlMax; i++) { j++; foundSnippetIndices[j] = 0; - if(snippetControlArray[i][0] != -1 - && caretPos >= snippetControlArray[i][0] - && caretPos <= snippetControlArray[i][0] + snippetControlArray[i][1]) { + if(snippetControlArray[i].location != -1 + && caretPos >= snippetControlArray[i].location + && caretPos <= snippetControlArray[i].location + snippetControlArray[i].length) { foundSnippetIndices[j] = 1; if(i == currentSnippetIndex) @@ -2049,11 +2050,11 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS if(foundSnippetIndices[i] == 1) { if(curIndex == -1) { curIndex = i; - smallestLength = snippetControlArray[i][1]; + smallestLength = snippetControlArray[i].length; } else { - if(smallestLength > snippetControlArray[i][1]) { + if(smallestLength > snippetControlArray[i].length) { curIndex = i; - smallestLength = snippetControlArray[i][1]; + smallestLength = snippetControlArray[i].length; } } } @@ -2192,13 +2193,13 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS currentSnippetIndex--; - // Look for previous defined snippet since snippet numbers must not serial like 1, 5, and 12 e.g. - while(snippetControlArray[currentSnippetIndex][0] == -1 && currentSnippetIndex > -2) + // Look for previous defined snippet since snippet numbers might not be serial like 1, 5, and 12 e.g. + while(snippetControlArray[currentSnippetIndex].location == -1 && currentSnippetIndex > -2) currentSnippetIndex--; if(currentSnippetIndex < 0) { currentSnippetIndex = 0; - while(snippetControlArray[currentSnippetIndex][0] == -1 && currentSnippetIndex < 20) + while(snippetControlArray[currentSnippetIndex].location == -1 && currentSnippetIndex < COUNT_OF(snippetControlArray)) currentSnippetIndex++; NSBeep(); } @@ -2210,8 +2211,8 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS currentSnippetIndex++; - // Look for next defined snippet since snippet numbers must not serial like 1, 5, and 12 e.g. - while(snippetControlArray[currentSnippetIndex][0] == -1 && currentSnippetIndex < 20) + // Look for next defined snippet since snippet numbers might not be serial like 1, 5, and 12 e.g. + while(snippetControlArray[currentSnippetIndex].location == -1 && currentSnippetIndex < COUNT_OF(snippetControlArray)) currentSnippetIndex++; if(currentSnippetIndex > snippetControlMax) { // for safety reasons @@ -2978,7 +2979,7 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS // Is the caret still inside a snippet if([self checkForCaretInsideSnippet]) { for(NSInteger i=0; i<snippetControlMax; i++) { - if(snippetControlArray[i][0] > -1) { + if(snippetControlArray[i].location > -1) { // choose the colors for the snippet parts if(i == currentSnippetIndex) { [[NSColor colorWithCalibratedRed:1.0f green:0.6f blue:0.0f alpha:0.4f] setFill]; @@ -2987,7 +2988,7 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS [[NSColor colorWithCalibratedRed:1.0f green:0.8f blue:0.2f alpha:0.2f] setFill]; [[NSColor colorWithCalibratedRed:1.0f green:0.8f blue:0.2f alpha:0.5f] setStroke]; } - NSBezierPath *snippetPath = [self roundedBezierPathAroundRange: NSMakeRange(snippetControlArray[i][0],snippetControlArray[i][1]) ]; + NSBezierPath *snippetPath = [self roundedBezierPathAroundRange: NSMakeRange(snippetControlArray[i].location,snippetControlArray[i].length) ]; [snippetPath fill]; [snippetPath stroke]; } @@ -3334,20 +3335,19 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS // Re-calculate snippet ranges if snippet session is active if(snippetControlCounter > -1 && !snippetWasJustInserted && !isProcessingMirroredSnippets) { // Remove any fully nested snippets relative to the current snippet which was edited - NSInteger currentSnippetLocation = snippetControlArray[currentSnippetIndex][0]; - NSInteger currentSnippetMaxRange = snippetControlArray[currentSnippetIndex][0] + snippetControlArray[currentSnippetIndex][1]; + SnippetControlInfo *currentSnippetRef = &snippetControlArray[currentSnippetIndex]; + NSInteger currentSnippetLocation = currentSnippetRef->location; + NSInteger currentSnippetMaxRange = currentSnippetRef->location + currentSnippetRef->length; NSInteger i; for(i=0; i<snippetControlMax; i++) { - if(snippetControlArray[i][0] > -1 + if(snippetControlArray[i].location > -1 && i != currentSnippetIndex - && snippetControlArray[i][0] >= currentSnippetLocation - && snippetControlArray[i][0] <= currentSnippetMaxRange - && snippetControlArray[i][0] + snippetControlArray[i][1] >= currentSnippetLocation - && snippetControlArray[i][0] + snippetControlArray[i][1] <= currentSnippetMaxRange + && snippetControlArray[i].location >= currentSnippetLocation + && snippetControlArray[i].location <= currentSnippetMaxRange + && snippetControlArray[i].location + snippetControlArray[i].length >= currentSnippetLocation + && snippetControlArray[i].location + snippetControlArray[i].length <= currentSnippetMaxRange ) { - snippetControlArray[i][0] = -1; - snippetControlArray[i][1] = -1; - snippetControlArray[i][2] = -1; + snippetControlArray[i] = (SnippetControlInfo){-1, -1, -1}; } } @@ -3355,26 +3355,26 @@ static inline NSPoint SPPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NS NSUInteger changeInLength = [textStore changeInLength]; // Adjust length change to current snippet - snippetControlArray[currentSnippetIndex][1] += changeInLength; + currentSnippetRef->length += changeInLength; // If length < 0 break snippet input - if(snippetControlArray[currentSnippetIndex][1] < 0) { + if(currentSnippetRef->length < 0) { [self endSnippetSession]; } else { // Adjust start position of snippets after caret position for(i=0; i<=snippetControlMax; i++) { - if(snippetControlArray[i][0] > -1 && i != currentSnippetIndex) { - if(editStartPosition < snippetControlArray[i][0]) { - snippetControlArray[i][0] += changeInLength; - } else if(editStartPosition >= snippetControlArray[i][0] && editStartPosition <= snippetControlArray[i][0] + snippetControlArray[i][1]) { - snippetControlArray[i][1] += changeInLength; + if(snippetControlArray[i].location > -1 && i != currentSnippetIndex) { + if(editStartPosition < snippetControlArray[i].location) { + snippetControlArray[i].location += changeInLength; + } else if(editStartPosition >= snippetControlArray[i].location && editStartPosition <= snippetControlArray[i].location + snippetControlArray[i].length) { + snippetControlArray[i].length += changeInLength; } } } // Adjust start position of mirrored snippets after caret position if(mirroredCounter > -1) for(i=0; i<=mirroredCounter; i++) { - if(editStartPosition < snippetMirroredControlArray[i][1]) { - snippetMirroredControlArray[i][1] += changeInLength; + if(editStartPosition < snippetMirroredControlArray[i].location) { + snippetMirroredControlArray[i].location += changeInLength; } } } diff --git a/Source/SPUserManager.h b/Source/SPUserManager.h index 3bee8636..6338145f 100644 --- a/Source/SPUserManager.h +++ b/Source/SPUserManager.h @@ -80,6 +80,9 @@ BOOL isSaving; BOOL isInitializing; NSMutableString *errorsString; + + // MySQL 5.7.6 removes the "Password" columns and only uses the "plugin"+"authentication_string" columns + BOOL requiresPost576PasswordHandling; } @property (nonatomic, retain) SPMySQLConnection *connection; diff --git a/Source/SPUserManager.m b/Source/SPUserManager.m index 6f42ac75..a5a83cbe 100644 --- a/Source/SPUserManager.m +++ b/Source/SPUserManager.m @@ -159,6 +159,9 @@ static NSString * const SPTableViewNameColumnID = @"NameColumn"; // Select users from the mysql.user table SPMySQLResult *result = [connection queryString:@"SELECT * FROM mysql.user ORDER BY user"]; [result setReturnDataAsStrings:YES]; + //TODO: improve user feedback + NSAssert(([[result fieldNames] firstObjectCommonWithArray:@[@"Password",@"authentication_string"]] != nil), @"Resultset from mysql.user contains neither 'Password' nor 'authentication_string' column!?"); + requiresPost576PasswordHandling = ![[result fieldNames] containsObject:@"Password"]; [usersResultArray addObjectsFromArray:[result getAllRows]]; [self _initializeTree:usersResultArray]; @@ -244,9 +247,9 @@ static NSString * const SPTableViewNameColumnID = @"NameColumn"; // for each user currently in the database. for (NSUInteger i = 0; i < [items count]; i++) { - NSString *username = [[items objectAtIndex:i] objectForKey:@"User"]; - NSArray *parentResults = [[self _fetchUserWithUserName:username] retain]; NSDictionary *item = [items objectAtIndex:i]; + NSString *username = [item objectForKey:@"User"]; + NSArray *parentResults = [[self _fetchUserWithUserName:username] retain]; SPUserMO *parent; SPUserMO *child; @@ -266,8 +269,16 @@ static NSString * const SPTableViewNameColumnID = @"NameColumn"; // original values for comparison purposes [parent setPrimitiveValue:username forKey:@"user"]; [parent setPrimitiveValue:username forKey:@"originaluser"]; - [parent setPrimitiveValue:[item objectForKey:@"Password"] forKey:@"password"]; - [parent setPrimitiveValue:[item objectForKey:@"Password"] forKey:@"originalpassword"]; + if(requiresPost576PasswordHandling) { + [parent setPrimitiveValue:[item objectForKey:@"plugin"] forKey:@"plugin"]; + NSString *pwHash = [item objectForKey:@"authentication_string"]; + [parent setPrimitiveValue:pwHash forKey:@"authentication_string"]; + if([pwHash length]) [parent setPrimitiveValue:@"sequelpro_dummy_password" forKey:@"password"]; // for the UI dialog + } + else { + [parent setPrimitiveValue:[item objectForKey:@"Password"] forKey:@"password"]; + [parent setPrimitiveValue:[item objectForKey:@"Password"] forKey:@"originalpassword"]; + } } // Setup the NSManagedObject with values from the dictionary @@ -360,7 +371,7 @@ static NSString * const SPTableViewNameColumnID = @"NameColumn"; NSNumber *value = [NSNumber numberWithInteger:[[item objectForKey:key] integerValue]]; [child setValue:value forKey:key]; } - else if (![key isEqualToString:@"User"] && ![key isEqualToString:@"Password"]) + else if (![key isInArray:@[@"User",@"Password",@"plugin",@"authentication_string"]]) { NSString *value = [item objectForKey:key]; [child setValue:value forKey:key]; @@ -807,7 +818,7 @@ static NSString * const SPTableViewNameColumnID = @"NameColumn"; { if (![user parent]) { [user setPrimitiveValue:[user valueForKey:@"user"] forKey:@"originaluser"]; - [user setPrimitiveValue:[user valueForKey:@"password"] forKey:@"originalpassword"]; + if(!requiresPost576PasswordHandling) [user setPrimitiveValue:[user valueForKey:@"password"] forKey:@"originalpassword"]; } } } @@ -961,20 +972,43 @@ static NSString * const SPTableViewNameColumnID = @"NameColumn"; } // If the password has been changed, use the same password on all hosts - if (![[user valueForKey:@"password"] isEqualToString:[user valueForKey:@"originalpassword"]]) { - - for (SPUserMO *child in hosts) - { - NSString *changePasswordStatement = [NSString stringWithFormat: - @"SET PASSWORD FOR %@@%@ = PASSWORD(%@)", - [[user valueForKey:@"user"] tickQuotedString], - [[child host] tickQuotedString], - ([user valueForKey:@"password"]) ? [[user valueForKey:@"password"] tickQuotedString] : @"''"]; - - [connection queryString:changePasswordStatement]; + if(requiresPost576PasswordHandling) { + // the UI password field is bound to the password field, so this is still where the new plaintext value comes from + NSString *newPass = [[user changedValues] objectForKey:@"password"]; + if(newPass) { + // 5.7.6+ can update all users at once + NSMutableString *alterStmt = [NSMutableString stringWithString:@"ALTER USER "]; + BOOL first = YES; + for (SPUserMO *child in hosts) + { + if(!first) [alterStmt appendString:@", "]; + [alterStmt appendFormat:@"%@@%@ IDENTIFIED WITH %@ BY %@", //note: "BY" -> plaintext, "AS" -> hash + [[user valueForKey:@"user"] tickQuotedString], + [[child host] tickQuotedString], + [[user valueForKey:@"plugin"] tickQuotedString], + (![newPass isNSNull] && [newPass length]) ? [newPass tickQuotedString] : @"''"]; + first = NO; + } + [connection queryString:alterStmt]; if(![self _checkAndDisplayMySqlError]) return NO; } } + else { + if (![[user valueForKey:@"password"] isEqualToString:[user valueForKey:@"originalpassword"]]) { + + for (SPUserMO *child in hosts) + { + NSString *changePasswordStatement = [NSString stringWithFormat: + @"SET PASSWORD FOR %@@%@ = PASSWORD(%@)", + [[user valueForKey:@"user"] tickQuotedString], + [[child host] tickQuotedString], + ([user valueForKey:@"password"]) ? [[user valueForKey:@"password"] tickQuotedString] : @"''"]; + + [connection queryString:changePasswordStatement]; + if(![self _checkAndDisplayMySqlError]) return NO; + } + } + } } else { // If the hostname has changed, remane the detail before editing details @@ -1038,14 +1072,25 @@ static NSString * const SPTableViewNameColumnID = @"NameColumn"; // same affect as CREATE USER. That is, a new user with no privleges. NSString *host = [[user valueForKey:@"host"] tickQuotedString]; - if ([user parent] && [[user parent] valueForKey:@"user"] && [[user parent] valueForKey:@"password"]) { + if ([user parent] && [[user parent] valueForKey:@"user"] && ([[user parent] valueForKey:@"password"] || [[user parent] valueForKey:@"authentication_string"])) { NSString *username = [[[user parent] valueForKey:@"user"] tickQuotedString]; - NSString *password = [[[user parent] valueForKey:@"password"] tickQuotedString]; + + NSString *idString; + if(requiresPost576PasswordHandling) { + //copy the hash from the parent. if the parent password changes at the same time, updateUser: will take care of it afterwards + NSString *plugin = [[[user parent] valueForKey:@"plugin"] tickQuotedString]; + NSString *hash = [[[user parent] valueForKey:@"authentication_string"] tickQuotedString]; + idString = [NSString stringWithFormat:@"IDENTIFIED WITH %@ AS %@",plugin,hash]; + } + else { + NSString *password = [[[user parent] valueForKey:@"password"] tickQuotedString]; + idString = [NSString stringWithFormat:@"IDENTIFIED BY %@%@",[[user parent] valueForKey:@"originaluser"]?@"PASSWORD ":@"", password]; + } createStatement = ([serverSupport supportsCreateUser]) ? - [NSString stringWithFormat:@"CREATE USER %@@%@ IDENTIFIED BY %@%@", username, host, [[user parent] valueForKey:@"originaluser"]?@"PASSWORD ":@"", password] : - [NSString stringWithFormat:@"GRANT SELECT ON mysql.* TO %@@%@ IDENTIFIED BY %@%@", username, host, [[user parent] valueForKey:@"originaluser"]?@"PASSWORD ":@"", password]; + [NSString stringWithFormat:@"CREATE USER %@@%@ %@", username, host, idString] : + [NSString stringWithFormat:@"GRANT SELECT ON mysql.* TO %@@%@ %@", username, host, idString]; } else if ([user parent] && [[user parent] valueForKey:@"user"]) { |