From 9801689c0e96b49582b3ee3fc3a9e825181c99ca Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 23 Jan 2018 09:50:02 -0500 Subject: [PATCH] Modify YapDatabase to read converted database. --- SignalMessaging/utils/OWSDatabaseConverter.m | 92 ++++++++++++-------- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/SignalMessaging/utils/OWSDatabaseConverter.m b/SignalMessaging/utils/OWSDatabaseConverter.m index 75f66e566..3e9d1dad5 100644 --- a/SignalMessaging/utils/OWSDatabaseConverter.m +++ b/SignalMessaging/utils/OWSDatabaseConverter.m @@ -164,7 +164,6 @@ const NSUInteger kSqliteHeaderLength = 32; { NSData *keyData = databasePassword; - // Setting the encrypted database page size status = sqlite3_key(db, [keyData bytes], (int)[keyData length]); if (status != SQLITE_OK) { DDLogError(@"Error setting SQLCipher key: %d %s", status, sqlite3_errmsg(db)); @@ -177,10 +176,11 @@ const NSUInteger kSqliteHeaderLength = 32; // // This block was derived from [Yapdatabase configureDatabase]. { - status = sqlite3_exec(db, "PRAGMA journal_mode = WAL;", NULL, NULL, NULL); - if (status != SQLITE_OK) { - DDLogError(@"Error setting PRAGMA journal_mode: %d %s", status, sqlite3_errmsg(db)); - return OWSErrorWithCodeDescription(OWSErrorCodeDatabaseConversionFatalError, @"Failed to set WAL mode"); + NSError *_Nullable error = [self executeSql:@"PRAGMA journal_mode = WAL;" + db:db + label:@"PRAGMA journal_mode = WAL"]; + if (error) { + return error; } // TODO verify we need to do this. @@ -197,11 +197,11 @@ const NSUInteger kSqliteHeaderLength = 32; // (This sqlite db is also used to perform checkpoints. // But a normal value won't affect these operations, // as they will perform sync operations whether the connection is normal or full.) - status = sqlite3_exec(db, "PRAGMA synchronous = NORMAL;", NULL, NULL, NULL); - if (status != SQLITE_OK) { - DDLogError(@"Error setting PRAGMA synchronous: %d %s", status, sqlite3_errmsg(db)); - // This isn't critical, so we can continue. - } + + error = [self executeSql:@"PRAGMA synchronous = NORMAL;" + db:db + label:@"PRAGMA synchronous = NORMAL"]; + // Any error isn't critical, so we can continue. // Set journal_size_imit. // @@ -211,12 +211,10 @@ const NSUInteger kSqliteHeaderLength = 32; NSInteger defaultPragmaJournalSizeLimit = 0; NSString *pragma_journal_size_limit = [NSString stringWithFormat:@"PRAGMA journal_size_limit = %ld;", (long)defaultPragmaJournalSizeLimit]; - - status = sqlite3_exec(db, [pragma_journal_size_limit UTF8String], NULL, NULL, NULL); - if (status != SQLITE_OK) { - DDLogError(@"Error setting PRAGMA journal_size_limit: %d %s", status, sqlite3_errmsg(db)); - // This isn't critical, so we can continue. - } + error = [self executeSql:pragma_journal_size_limit + db:db + label:@"PRAGMA journal_size_limit"]; + // Any error isn't critical, so we can continue. // Disable autocheckpointing. // @@ -257,7 +255,7 @@ const NSUInteger kSqliteHeaderLength = 32; OWSAssert(valueBytes != NULL); NSString *saltString = - [[NSString alloc] initWithBytes:valueBytes length:valueLength encoding:NSUTF8StringEncoding]; + [[NSString alloc] initWithBytes:valueBytes length:(NSUInteger) valueLength encoding:NSUTF8StringEncoding]; sqlite3_finalize(statement); statement = NULL; @@ -273,29 +271,34 @@ const NSUInteger kSqliteHeaderLength = 32; // SQLCipher migration { NSString *setPlainTextHeaderPragma = - [NSString stringWithFormat:@"PRAGMA cipher_plaintext_header_size = %zd;", kSqliteHeaderLength]; + [NSString stringWithFormat:@"PRAGMA cipher_plaintext_header_size = %zd;", kSqliteHeaderLength]; + NSError *_Nullable error = [self executeSql:setPlainTextHeaderPragma + db:db + label:setPlainTextHeaderPragma]; + if (error) { + return error; + } - status = sqlite3_exec(db, [setPlainTextHeaderPragma UTF8String], NULL, NULL, NULL); - if (status != SQLITE_OK) { - DDLogError(@"Error setting PRAGMA cipher_plaintext_header_size = %zd: status: %d, error: %s", - kSqliteHeaderLength, - status, - sqlite3_errmsg(db)); - return OWSErrorWithCodeDescription( - OWSErrorCodeDatabaseConversionFatalError, @"Failed to set PRAGMA cipher_plaintext_header_size"); + NSString *setDefaultPlainTextHeaderPragma = + [NSString stringWithFormat:@"PRAGMA cipher_default_plaintext_header_size = %zd;", kSqliteHeaderLength]; + error = [self executeSql:setDefaultPlainTextHeaderPragma + db:db + label:setDefaultPlainTextHeaderPragma]; + if (error) { + return error; } // Modify the first page, so that SQLCipher will overwrite, respecting our new cipher_plaintext_header_size NSString *tableName = [NSString stringWithFormat:@"signal-migration-%@", [NSUUID new].UUIDString]; NSString *modificationSQL = - [NSString stringWithFormat:@"CREATE TABLE \"%@\"(a integer); INSERT INTO \"%@\"(a) VALUES (1);", - tableName, - tableName]; - DDLogInfo(@"%@ modificationSQL: %@", self.logTag, modificationSQL); - status = sqlite3_exec(db, [modificationSQL UTF8String], NULL, NULL, NULL); - if (status != SQLITE_OK) { - DDLogError(@"%@ Error modifying first page: %d, error: %s", self.logTag, status, sqlite3_errmsg(db)); - return OWSErrorWithCodeDescription(OWSErrorCodeDatabaseConversionFatalError, @"Error modifying first page"); + [NSString stringWithFormat:@"CREATE TABLE \"%@\"(a integer); INSERT INTO \"%@\"(a) VALUES (1);", + tableName, + tableName]; + error = [self executeSql:modificationSQL + db:db + label:modificationSQL]; + if (error) { + return error; } // Force a checkpoint so that the plaintext is written to the actual DB file, not just living in the WAL. @@ -308,6 +311,27 @@ const NSUInteger kSqliteHeaderLength = 32; return nil; } ++ (nullable NSError *)executeSql:(NSString *)sql + db:(sqlite3 *)db + label:(NSString *)label +{ + OWSAssert(db); + OWSAssert(sql.length > 0); + + DDLogVerbose(@"%@ %@", self.logTag, sql); + + int status = sqlite3_exec(db, [sql UTF8String], NULL, NULL, NULL); + if (status != SQLITE_OK) { + DDLogError(@"Error %@: status: %d, error: %s", + label, + status, + sqlite3_errmsg(db)); + return OWSErrorWithCodeDescription( + OWSErrorCodeDatabaseConversionFatalError, [NSString stringWithFormat:@"Failed to set %@", label]); + } + return nil; +} + @end NS_ASSUME_NONNULL_END