aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories
diff options
context:
space:
mode:
authorMax <post@wickenrode.com>2017-05-02 01:14:27 +0200
committerMax <post@wickenrode.com>2017-05-02 01:14:27 +0200
commitfac661c5d1dcac7780521facdaebdc6f4c1afa27 (patch)
treead0468669f054f84a00da9dfb4943cd117976b13 /Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories
parent2b081c2ef732599a035dc05ff33b08edffd74b04 (diff)
downloadsequelpro-fac661c5d1dcac7780521facdaebdc6f4c1afa27.tar.gz
sequelpro-fac661c5d1dcac7780521facdaebdc6f4c1afa27.tar.bz2
sequelpro-fac661c5d1dcac7780521facdaebdc6f4c1afa27.zip
Fix some issues with charset handling during connect
* hostname and file paths are places where libmysqlclient ultimately only passes the string to an OS library so we should use whatever charset the OS expects, not mysql * Even though _makeRawMySQLConnectionWithEncoding:isMasterConnection: takes an explicit charset argument most of the conversion logic simply used whatever charset the existing connection currently has, which is not neccesarily the one the new connection should use * Add some remarks about the charset handling with passwords and mysql_error() * Charsets do not apply to sqlstate.
Diffstat (limited to 'Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories')
-rw-r--r--Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Conversion.h14
-rw-r--r--Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Conversion.m14
-rw-r--r--Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m9
3 files changed, 29 insertions, 8 deletions
diff --git a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Conversion.h b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Conversion.h
index 6f7b1a9a..77b70bf9 100644
--- a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Conversion.h
+++ b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Conversion.h
@@ -34,6 +34,7 @@
@interface SPMySQLConnection (Conversion)
+ (const char *)_cStringForString:(NSString *)aString usingEncoding:(NSStringEncoding)anEncoding returningLengthAs:(NSUInteger *)cStringLengthPointer;
++ (NSString *)_stringForCString:(const char *)cString usingEncoding:(NSStringEncoding)encoding;
- (const char *)_cStringForString:(NSString *)aString;
- (NSString *)_stringForCString:(const char *)cString;
@@ -56,3 +57,16 @@ static inline const char* _cStringForStringWithEncoding(NSString* aString, NSStr
return (const char *)(*cachedMethodPointer)(cachedClass, cachedSelector, aString, anEncoding, cStringLengthPointer);
}
+
+/**
+ * Converts a C string (NUL-terminated) to an NSString using the supplied encoding.
+ *
+ * Unlike +[NSString stringWithCString:encoding:] which will crash on a NULL pointer, this method will return nil instead.
+ */
+static inline NSString * _stringForCStringWithEncoding(const char *aString, NSStringEncoding inputEncoding)
+{
+ //This implementation is smaller than the cached selector voodoo above, so let's do it inline
+
+ //NSString will crash on NULL ptr
+ return (aString == NULL)? nil : [NSString stringWithCString:aString encoding:inputEncoding];
+}
diff --git a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Conversion.m b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Conversion.m
index 676684ca..a7d293ea 100644
--- a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Conversion.m
+++ b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Conversion.m
@@ -79,7 +79,7 @@
}
/**
- * Converts a C string to an NSString using the supplied encoding.
+ * Converts a C string to an NSString using the current connection encoding.
* This method *will not* correctly preserve nul characters within c strings; instead
* the first nul character within the string will be treated as the line ending. This
* is unavoidable without supplying a string length, so this method should not be widely
@@ -87,11 +87,15 @@
*/
- (NSString *)_stringForCString:(const char *)cString
{
+ return _stringForCStringWithEncoding(cString, stringEncoding);
+}
- // Don't try and convert null strings
- if (cString == NULL) return nil;
-
- return [NSString stringWithCString:cString encoding:stringEncoding];
+/**
+ * @see _stringForCStringWithEncoding()
+ */
++ (NSString *)_stringForCString:(const char *)cString usingEncoding:(NSStringEncoding)encoding
+{
+ return _stringForCStringWithEncoding(cString, encoding);
}
@end
diff --git a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m
index 594756be..ef98a21c 100644
--- a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m
+++ b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m
@@ -323,7 +323,8 @@
// Store the error state
theErrorMessage = [self _stringForCString:mysql_error(mySQLConnection)];
theErrorID = mysql_errno(mySQLConnection);
- theSqlstate = [self _stringForCString:mysql_sqlstate(mySQLConnection)];
+ // sqlstate is always an ASCII string, regardless of charset (but use latin1 anyway as that is less picky about invalid bytes)
+ theSqlstate = _stringForCStringWithEncoding(mysql_sqlstate(mySQLConnection), NSISOLatin1StringEncoding);
// Prevent retries if the query was cancelled or not a connection error
if (lastQueryWasCancelled || ![SPMySQLConnection isErrorIDConnectionError:theErrorID]) {
@@ -382,7 +383,8 @@
// Update the error message, if appropriate, to reflect result store errors or overall success
theErrorMessage = [self _stringForCString:mysql_error(mySQLConnection)];
theErrorID = mysql_errno(mySQLConnection);
- theSqlstate = [self _stringForCString:mysql_sqlstate(mySQLConnection)];
+ // sqlstate is always an ASCII string, regardless of charset (but use latin1 anyway as that is less picky about invalid bytes)
+ theSqlstate = _stringForCStringWithEncoding(mysql_sqlstate(mySQLConnection), NSISOLatin1StringEncoding);
} else {
theResult = [[SPMySQLEmptyResult alloc] init];
}
@@ -735,7 +737,8 @@
{
// If a SQLSTATE wasn't supplied, select one from the connection
if(!theSqlstate) {
- theSqlstate = [self _stringForCString:mysql_sqlstate(mySQLConnection)];
+ // sqlstate is always an ASCII string, regardless of charset (but use latin1 anyway as that is less picky about invalid bytes)
+ theSqlstate = _stringForCStringWithEncoding(mysql_sqlstate(mySQLConnection), NSISOLatin1StringEncoding);
}
// Clear the last SQLSTATE stored on the instance