From 111247ac56e400d6130f11fd38ea58fe29505999 Mon Sep 17 00:00:00 2001 From: Nicolas Seriot Date: Wed, 8 Sep 2010 00:44:01 +0200 Subject: [PATCH] updated for iOS 4.0, added call history --- Classes/FMDatabase.h | 115 ++++ Classes/FMDatabase.m | 753 +++++++++++++++++++++++++++ Classes/FMDatabaseAdditions.h | 31 ++ Classes/FMDatabaseAdditions.m | 114 ++++ Classes/FMResultSet.h | 89 ++++ Classes/FMResultSet.m | 384 ++++++++++++++ Classes/NSNumber+SP.h | 16 + Classes/NSNumber+SP.m | 36 ++ Classes/SPSourcePhoneTVC.h | 6 + Classes/SPSourcePhoneTVC.m | 82 ++- Classes/SPSourcePhotosTVC.m | 25 +- Classes/SpyPhoneAppDelegate.m | 3 +- SpyPhone.xcodeproj/nst.pbxuser | 500 +++++++++--------- SpyPhone.xcodeproj/nst.perspectivev3 | 108 ++-- SpyPhone.xcodeproj/project.pbxproj | 48 +- 15 files changed, 1974 insertions(+), 336 deletions(-) create mode 100644 Classes/FMDatabase.h create mode 100644 Classes/FMDatabase.m create mode 100644 Classes/FMDatabaseAdditions.h create mode 100644 Classes/FMDatabaseAdditions.m create mode 100644 Classes/FMResultSet.h create mode 100644 Classes/FMResultSet.m create mode 100644 Classes/NSNumber+SP.h create mode 100644 Classes/NSNumber+SP.m diff --git a/Classes/FMDatabase.h b/Classes/FMDatabase.h new file mode 100644 index 0000000..2d9b3cf --- /dev/null +++ b/Classes/FMDatabase.h @@ -0,0 +1,115 @@ +#import +#import "sqlite3.h" +#import "FMResultSet.h" + +@interface FMDatabase : NSObject +{ + sqlite3* db; + NSString* databasePath; + BOOL logsErrors; + BOOL crashOnErrors; + BOOL inUse; + BOOL inTransaction; + BOOL traceExecution; + BOOL checkedOut; + int busyRetryTimeout; + BOOL shouldCacheStatements; + NSMutableDictionary *cachedStatements; +} + + ++ (id)databaseWithPath:(NSString*)inPath; +- (id)initWithPath:(NSString*)inPath; + +- (BOOL)open; +#if SQLITE_VERSION_NUMBER >= 3005000 +- (BOOL)openWithFlags:(int)flags; +#endif +- (BOOL)close; +- (BOOL)goodConnection; +- (void)clearCachedStatements; + +// encryption methods. You need to have purchased the sqlite encryption extensions for these to work. +- (BOOL)setKey:(NSString*)key; +- (BOOL)rekey:(NSString*)key; + + +- (NSString *)databasePath; + +- (NSString*)lastErrorMessage; + +- (int)lastErrorCode; +- (BOOL)hadError; +- (sqlite_int64)lastInsertRowId; + +- (sqlite3*)sqliteHandle; + +- (BOOL)executeUpdate:(NSString*)sql, ...; +- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments; +- (id)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args; // you shouldn't ever need to call this. use the previous two instead. + +- (id)executeQuery:(NSString*)sql, ...; +- (id)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments; +- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args; // you shouldn't ever need to call this. use the previous two instead. + +- (BOOL)rollback; +- (BOOL)commit; +- (BOOL)beginTransaction; +- (BOOL)beginDeferredTransaction; + +- (BOOL)logsErrors; +- (void)setLogsErrors:(BOOL)flag; + +- (BOOL)crashOnErrors; +- (void)setCrashOnErrors:(BOOL)flag; + +- (BOOL)inUse; +- (void)setInUse:(BOOL)value; + +- (BOOL)inTransaction; +- (void)setInTransaction:(BOOL)flag; + +- (BOOL)traceExecution; +- (void)setTraceExecution:(BOOL)flag; + +- (BOOL)checkedOut; +- (void)setCheckedOut:(BOOL)flag; + +- (int)busyRetryTimeout; +- (void)setBusyRetryTimeout:(int)newBusyRetryTimeout; + +- (BOOL)shouldCacheStatements; +- (void)setShouldCacheStatements:(BOOL)value; + +- (NSMutableDictionary *)cachedStatements; +- (void)setCachedStatements:(NSMutableDictionary *)value; + + ++ (NSString*)sqliteLibVersion; + +- (int)changes; + +@end + +@interface FMStatement : NSObject { + sqlite3_stmt *statement; + NSString *query; + long useCount; +} + + +- (void)close; +- (void)reset; + +- (sqlite3_stmt *)statement; +- (void)setStatement:(sqlite3_stmt *)value; + +- (NSString *)query; +- (void)setQuery:(NSString *)value; + +- (long)useCount; +- (void)setUseCount:(long)value; + + +@end + diff --git a/Classes/FMDatabase.m b/Classes/FMDatabase.m new file mode 100644 index 0000000..399a0f6 --- /dev/null +++ b/Classes/FMDatabase.m @@ -0,0 +1,753 @@ +#import "FMDatabase.h" +#import "unistd.h" + +@implementation FMDatabase + ++ (id)databaseWithPath:(NSString*)aPath { + return [[[self alloc] initWithPath:aPath] autorelease]; +} + +- (id)initWithPath:(NSString*)aPath { + self = [super init]; + + if (self) { + databasePath = [aPath copy]; + db = 0x00; + logsErrors = 0x00; + crashOnErrors = 0x00; + busyRetryTimeout = 0x00; + } + + return self; +} + +- (void)dealloc { + [self close]; + + [cachedStatements release]; + [databasePath release]; + + [super dealloc]; +} + ++ (NSString*)sqliteLibVersion { + return [NSString stringWithFormat:@"%s", sqlite3_libversion()]; +} + +- (NSString *)databasePath { + return databasePath; +} + +- (sqlite3*)sqliteHandle { + return db; +} + +- (BOOL)open { + int err = sqlite3_open([databasePath fileSystemRepresentation], &db ); + if(err != SQLITE_OK) { + NSLog(@"error opening!: %d", err); + return NO; + } + + return YES; +} + +#if SQLITE_VERSION_NUMBER >= 3005000 +- (BOOL)openWithFlags:(int)flags { + int err = sqlite3_open_v2([databasePath fileSystemRepresentation], &db, flags, NULL /* Name of VFS module to use */); + if(err != SQLITE_OK) { + NSLog(@"error opening!: %d", err); + return NO; + } + return YES; +} +#endif + + +- (BOOL)close { + + [self clearCachedStatements]; + + if (!db) { + return YES; + } + + int rc; + BOOL retry; + int numberOfRetries = 0; + do { + retry = NO; + rc = sqlite3_close(db); + if (SQLITE_BUSY == rc) { + retry = YES; + usleep(20); + if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) { + NSLog(@"%s:%d", __FUNCTION__, __LINE__); + NSLog(@"Database busy, unable to close"); + return NO; + } + } + else if (SQLITE_OK != rc) { + NSLog(@"error closing!: %d", rc); + } + } + while (retry); + + db = nil; + return YES; +} + +- (void)clearCachedStatements { + + NSEnumerator *e = [cachedStatements objectEnumerator]; + FMStatement *cachedStmt; + + while ((cachedStmt = [e nextObject])) { + [cachedStmt close]; + } + + [cachedStatements removeAllObjects]; +} + +- (FMStatement*)cachedStatementForQuery:(NSString*)query { + return [cachedStatements objectForKey:query]; +} + +- (void)setCachedStatement:(FMStatement*)statement forQuery:(NSString*)query { + //NSLog(@"setting query: %@", query); + query = [query copy]; // in case we got handed in a mutable string... + [statement setQuery:query]; + [cachedStatements setObject:statement forKey:query]; + [query release]; +} + + +- (BOOL)rekey:(NSString*)key { +#ifdef SQLITE_HAS_CODEC + if (!key) { + return NO; + } + + int rc = sqlite3_rekey(db, [key UTF8String], strlen([key UTF8String])); + + if (rc != SQLITE_OK) { + NSLog(@"error on rekey: %d", rc); + NSLog(@"%@", [self lastErrorMessage]); + } + + return (rc == SQLITE_OK); +#else + return NO; +#endif +} + +- (BOOL)setKey:(NSString*)key { +#ifdef SQLITE_HAS_CODEC + if (!key) { + return NO; + } + + int rc = sqlite3_key(db, [key UTF8String], strlen([key UTF8String])); + + return (rc == SQLITE_OK); +#else + return NO; +#endif +} + +- (BOOL)goodConnection { + + if (!db) { + return NO; + } + + FMResultSet *rs = [self executeQuery:@"select name from sqlite_master where type='table'"]; + + if (rs) { + [rs close]; + return YES; + } + + return NO; +} + +- (void)compainAboutInUse { + NSLog(@"The FMDatabase %@ is currently in use.", self); + + if (crashOnErrors) { + NSAssert1(false, @"The FMDatabase %@ is currently in use.", self); + } +} + +- (NSString*)lastErrorMessage { + return [NSString stringWithUTF8String:sqlite3_errmsg(db)]; +} + +- (BOOL)hadError { + int lastErrCode = [self lastErrorCode]; + + return (lastErrCode > SQLITE_OK && lastErrCode < SQLITE_ROW); +} + +- (int)lastErrorCode { + return sqlite3_errcode(db); +} + +- (sqlite_int64)lastInsertRowId { + + if (inUse) { + [self compainAboutInUse]; + return NO; + } + [self setInUse:YES]; + + sqlite_int64 ret = sqlite3_last_insert_rowid(db); + + [self setInUse:NO]; + + return ret; +} + +- (void)bindObject:(id)obj toColumn:(int)idx inStatement:(sqlite3_stmt*)pStmt; { + + if ((!obj) || ((NSNull *)obj == [NSNull null])) { + sqlite3_bind_null(pStmt, idx); + } + + // FIXME - someday check the return codes on these binds. + else if ([obj isKindOfClass:[NSData class]]) { + sqlite3_bind_blob(pStmt, idx, [obj bytes], (int)[obj length], SQLITE_STATIC); + } + else if ([obj isKindOfClass:[NSDate class]]) { + sqlite3_bind_double(pStmt, idx, [obj timeIntervalSince1970]); + } + else if ([obj isKindOfClass:[NSNumber class]]) { + + if (strcmp([obj objCType], @encode(BOOL)) == 0) { + sqlite3_bind_int(pStmt, idx, ([obj boolValue] ? 1 : 0)); + } + else if (strcmp([obj objCType], @encode(int)) == 0) { + sqlite3_bind_int64(pStmt, idx, [obj longValue]); + } + else if (strcmp([obj objCType], @encode(long)) == 0) { + sqlite3_bind_int64(pStmt, idx, [obj longValue]); + } + else if (strcmp([obj objCType], @encode(long long)) == 0) { + sqlite3_bind_int64(pStmt, idx, [obj longLongValue]); + } + else if (strcmp([obj objCType], @encode(float)) == 0) { + sqlite3_bind_double(pStmt, idx, [obj floatValue]); + } + else if (strcmp([obj objCType], @encode(double)) == 0) { + sqlite3_bind_double(pStmt, idx, [obj doubleValue]); + } + else { + sqlite3_bind_text(pStmt, idx, [[obj description] UTF8String], -1, SQLITE_STATIC); + } + } + else { + sqlite3_bind_text(pStmt, idx, [[obj description] UTF8String], -1, SQLITE_STATIC); + } +} + +- (id)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args { + + if (inUse) { + [self compainAboutInUse]; + return nil; + } + + [self setInUse:YES]; + + FMResultSet *rs = nil; + + int rc = 0x00;; + sqlite3_stmt *pStmt = 0x00;; + FMStatement *statement = 0x00; + + if (traceExecution && sql) { + NSLog(@"%@ executeQuery: %@", self, sql); + } + + if (shouldCacheStatements) { + statement = [self cachedStatementForQuery:sql]; + pStmt = statement ? [statement statement] : 0x00; + } + + int numberOfRetries = 0; + BOOL retry = NO; + + if (!pStmt) { + do { + retry = NO; + rc = sqlite3_prepare_v2(db, [sql UTF8String], -1, &pStmt, 0); + + if (SQLITE_BUSY == rc) { + retry = YES; + usleep(20); + + if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) { + NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]); + NSLog(@"Database busy"); + sqlite3_finalize(pStmt); + [self setInUse:NO]; + return nil; + } + } + else if (SQLITE_OK != rc) { + + + if (logsErrors) { + NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); + NSLog(@"DB Query: %@", sql); + if (crashOnErrors) { +//#if defined(__BIG_ENDIAN__) && !TARGET_IPHONE_SIMULATOR +// asm{ trap }; +//#endif + NSAssert2(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); + } + } + + sqlite3_finalize(pStmt); + + [self setInUse:NO]; + return nil; + } + } + while (retry); + } + + id obj; + int idx = 0; + int queryCount = sqlite3_bind_parameter_count(pStmt); // pointed out by Dominic Yu (thanks!) + + while (idx < queryCount) { + + if (arrayArgs) { + obj = [arrayArgs objectAtIndex:idx]; + } + else { + obj = va_arg(args, id); + } + + if (traceExecution) { + NSLog(@"obj: %@", obj); + } + + idx++; + + [self bindObject:obj toColumn:idx inStatement:pStmt]; + } + + if (idx != queryCount) { + NSLog(@"Error: the bind count is not correct for the # of variables (executeQuery)"); + sqlite3_finalize(pStmt); + [self setInUse:NO]; + return nil; + } + + [statement retain]; // to balance the release below + + if (!statement) { + statement = [[FMStatement alloc] init]; + [statement setStatement:pStmt]; + + if (shouldCacheStatements) { + [self setCachedStatement:statement forQuery:sql]; + } + } + + // the statement gets close in rs's dealloc or [rs close]; + rs = [FMResultSet resultSetWithStatement:statement usingParentDatabase:self]; + [rs setQuery:sql]; + + statement.useCount = statement.useCount + 1; + + [statement release]; + + [self setInUse:NO]; + + return rs; +} + +- (id)executeQuery:(NSString*)sql, ... { + va_list args; + va_start(args, sql); + + id result = [self executeQuery:sql withArgumentsInArray:nil orVAList:args]; + + va_end(args); + return result; +} + +- (id)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments { + return [self executeQuery:sql withArgumentsInArray:arguments orVAList:nil]; +} + +- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args { + + if (inUse) { + [self compainAboutInUse]; + return NO; + } + + [self setInUse:YES]; + + int rc = 0x00; + sqlite3_stmt *pStmt = 0x00; + FMStatement *cachedStmt = 0x00; + + if (traceExecution && sql) { + NSLog(@"%@ executeUpdate: %@", self, sql); + } + + if (shouldCacheStatements) { + cachedStmt = [self cachedStatementForQuery:sql]; + pStmt = cachedStmt ? [cachedStmt statement] : 0x00; + } + + int numberOfRetries = 0; + BOOL retry = NO; + + if (!pStmt) { + + do { + retry = NO; + rc = sqlite3_prepare_v2(db, [sql UTF8String], -1, &pStmt, 0); + if (SQLITE_BUSY == rc) { + retry = YES; + usleep(20); + + if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) { + NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]); + NSLog(@"Database busy"); + sqlite3_finalize(pStmt); + [self setInUse:NO]; + return NO; + } + } + else if (SQLITE_OK != rc) { + + + if (logsErrors) { + NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); + NSLog(@"DB Query: %@", sql); + if (crashOnErrors) { +//#if defined(__BIG_ENDIAN__) && !TARGET_IPHONE_SIMULATOR +// asm{ trap }; +//#endif + NSAssert2(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]); + } + } + + sqlite3_finalize(pStmt); + [self setInUse:NO]; + + return NO; + } + } + while (retry); + } + + + id obj; + int idx = 0; + int queryCount = sqlite3_bind_parameter_count(pStmt); + + while (idx < queryCount) { + + if (arrayArgs) { + obj = [arrayArgs objectAtIndex:idx]; + } + else { + obj = va_arg(args, id); + } + + + if (traceExecution) { + NSLog(@"obj: %@", obj); + } + + idx++; + + [self bindObject:obj toColumn:idx inStatement:pStmt]; + } + + if (idx != queryCount) { + NSLog(@"Error: the bind count is not correct for the # of variables (%@) (executeUpdate)", sql); + sqlite3_finalize(pStmt); + [self setInUse:NO]; + return NO; + } + + /* Call sqlite3_step() to run the virtual machine. Since the SQL being + ** executed is not a SELECT statement, we assume no data will be returned. + */ + numberOfRetries = 0; + do { + rc = sqlite3_step(pStmt); + retry = NO; + + if (SQLITE_BUSY == rc) { + // this will happen if the db is locked, like if we are doing an update or insert. + // in that case, retry the step... and maybe wait just 10 milliseconds. + retry = YES; + usleep(20); + + if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) { + NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]); + NSLog(@"Database busy"); + retry = NO; + } + } + else if (SQLITE_DONE == rc || SQLITE_ROW == rc) { + // all is well, let's return. + } + else if (SQLITE_ERROR == rc) { + NSLog(@"Error calling sqlite3_step (%d: %s) SQLITE_ERROR", rc, sqlite3_errmsg(db)); + NSLog(@"DB Query: %@", sql); + } + else if (SQLITE_MISUSE == rc) { + // uh oh. + NSLog(@"Error calling sqlite3_step (%d: %s) SQLITE_MISUSE", rc, sqlite3_errmsg(db)); + NSLog(@"DB Query: %@", sql); + } + else { + // wtf? + NSLog(@"Unknown error calling sqlite3_step (%d: %s) eu", rc, sqlite3_errmsg(db)); + NSLog(@"DB Query: %@", sql); + } + + } while (retry); + + assert( rc!=SQLITE_ROW ); + + + if (shouldCacheStatements && !cachedStmt) { + cachedStmt = [[FMStatement alloc] init]; + + [cachedStmt setStatement:pStmt]; + + [self setCachedStatement:cachedStmt forQuery:sql]; + + [cachedStmt release]; + } + + if (cachedStmt) { + cachedStmt.useCount = cachedStmt.useCount + 1; + rc = sqlite3_reset(pStmt); + } + else { + /* Finalize the virtual machine. This releases all memory and other + ** resources allocated by the sqlite3_prepare() call above. + */ + rc = sqlite3_finalize(pStmt); + } + + [self setInUse:NO]; + + return (rc == SQLITE_OK); +} + + +- (BOOL)executeUpdate:(NSString*)sql, ... { + va_list args; + va_start(args, sql); + + BOOL result = [self executeUpdate:sql withArgumentsInArray:nil orVAList:args]; + + va_end(args); + return result; +} + + + +- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments { + return [self executeUpdate:sql withArgumentsInArray:arguments orVAList:nil]; +} + +/* +- (id) executeUpdate:(NSString *)sql arguments:(va_list)args { + +} +*/ + +- (BOOL)rollback { + BOOL b = [self executeUpdate:@"ROLLBACK TRANSACTION;"]; + if (b) { + inTransaction = NO; + } + return b; +} + +- (BOOL)commit { + BOOL b = [self executeUpdate:@"COMMIT TRANSACTION;"]; + if (b) { + inTransaction = NO; + } + return b; +} + +- (BOOL)beginDeferredTransaction { + BOOL b = [self executeUpdate:@"BEGIN DEFERRED TRANSACTION;"]; + if (b) { + inTransaction = YES; + } + return b; +} + +- (BOOL)beginTransaction { + BOOL b = [self executeUpdate:@"BEGIN EXCLUSIVE TRANSACTION;"]; + if (b) { + inTransaction = YES; + } + return b; +} + +- (BOOL)logsErrors { + return logsErrors; +} +- (void)setLogsErrors:(BOOL)flag { + logsErrors = flag; +} + +- (BOOL)crashOnErrors { + return crashOnErrors; +} +- (void)setCrashOnErrors:(BOOL)flag { + crashOnErrors = flag; +} + +- (BOOL)inUse { + return inUse || inTransaction; +} + +- (void)setInUse:(BOOL)b { + inUse = b; +} + +- (BOOL)inTransaction { + return inTransaction; +} +- (void)setInTransaction:(BOOL)flag { + inTransaction = flag; +} + +- (BOOL)traceExecution { + return traceExecution; +} +- (void)setTraceExecution:(BOOL)flag { + traceExecution = flag; +} + +- (BOOL)checkedOut { + return checkedOut; +} +- (void)setCheckedOut:(BOOL)flag { + checkedOut = flag; +} + + +- (int)busyRetryTimeout { + return busyRetryTimeout; +} +- (void)setBusyRetryTimeout:(int)newBusyRetryTimeout { + busyRetryTimeout = newBusyRetryTimeout; +} + + +- (BOOL)shouldCacheStatements { + return shouldCacheStatements; +} + +- (void)setShouldCacheStatements:(BOOL)value { + + shouldCacheStatements = value; + + if (shouldCacheStatements && !cachedStatements) { + [self setCachedStatements:[NSMutableDictionary dictionary]]; + } + + if (!shouldCacheStatements) { + [self setCachedStatements:nil]; + } +} + +- (NSMutableDictionary *) cachedStatements { + return cachedStatements; +} + +- (void)setCachedStatements:(NSMutableDictionary *)value { + if (cachedStatements != value) { + [cachedStatements release]; + cachedStatements = [value retain]; + } +} + + +- (int)changes { + return(sqlite3_changes(db)); +} + +@end + + + +@implementation FMStatement + +- (void)dealloc { + [self close]; + [query release]; + [super dealloc]; +} + + +- (void)close { + if (statement) { + sqlite3_finalize(statement); + statement = 0x00; + } +} + +- (void)reset { + if (statement) { + sqlite3_reset(statement); + } +} + +- (sqlite3_stmt *)statement { + return statement; +} + +- (void)setStatement:(sqlite3_stmt *)value { + statement = value; +} + +- (NSString *)query { + return query; +} + +- (void)setQuery:(NSString *)value { + if (query != value) { + [query release]; + query = [value retain]; + } +} + +- (long)useCount { + return useCount; +} + +- (void)setUseCount:(long)value { + if (useCount != value) { + useCount = value; + } +} + +- (NSString*)description { + return [NSString stringWithFormat:@"%@ %d hit(s) for query %@", [super description], useCount, query]; +} + + +@end + diff --git a/Classes/FMDatabaseAdditions.h b/Classes/FMDatabaseAdditions.h new file mode 100644 index 0000000..3846268 --- /dev/null +++ b/Classes/FMDatabaseAdditions.h @@ -0,0 +1,31 @@ +// +// FMDatabaseAdditions.h +// fmkit +// +// Created by August Mueller on 10/30/05. +// Copyright 2005 Flying Meat Inc.. All rights reserved. +// + +#import +@interface FMDatabase (FMDatabaseAdditions) + + +- (int)intForQuery:(NSString*)objs, ...; +- (long)longForQuery:(NSString*)objs, ...; +- (BOOL)boolForQuery:(NSString*)objs, ...; +- (double)doubleForQuery:(NSString*)objs, ...; +- (NSString*)stringForQuery:(NSString*)objs, ...; +- (NSData*)dataForQuery:(NSString*)objs, ...; +- (NSDate*)dateForQuery:(NSString*)objs, ...; + +// Notice that there's no dataNoCopyForQuery:. +// That would be a bad idea, because we close out the result set, and then what +// happens to the data that we just didn't copy? Who knows, not I. + + +- (BOOL)tableExists:(NSString*)tableName; +- (FMResultSet*)getSchema; +- (FMResultSet*)getTableSchema:(NSString*)tableName; +- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName; + +@end diff --git a/Classes/FMDatabaseAdditions.m b/Classes/FMDatabaseAdditions.m new file mode 100644 index 0000000..2e1287a --- /dev/null +++ b/Classes/FMDatabaseAdditions.m @@ -0,0 +1,114 @@ +// +// FMDatabaseAdditions.m +// fmkit +// +// Created by August Mueller on 10/30/05. +// Copyright 2005 Flying Meat Inc.. All rights reserved. +// + +#import "FMDatabase.h" +#import "FMDatabaseAdditions.h" + +@implementation FMDatabase (FMDatabaseAdditions) + +#define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \ +va_list args; \ +va_start(args, query); \ +FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orVAList:args]; \ +va_end(args); \ +if (![resultSet next]) { return (type)0; } \ +type ret = [resultSet sel:0]; \ +[resultSet close]; \ +[resultSet setParentDB:nil]; \ +return ret; + + +- (NSString*)stringForQuery:(NSString*)query, ...; { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex); +} + +- (int)intForQuery:(NSString*)query, ...; { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex); +} + +- (long)longForQuery:(NSString*)query, ...; { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex); +} + +- (BOOL)boolForQuery:(NSString*)query, ...; { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex); +} + +- (double)doubleForQuery:(NSString*)query, ...; { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex); +} + +- (NSData*)dataForQuery:(NSString*)query, ...; { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex); +} + +- (NSDate*)dateForQuery:(NSString*)query, ...; { + RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex); +} + + +//check if table exist in database (patch from OZLB) +- (BOOL)tableExists:(NSString*)tableName { + + BOOL returnBool; + //lower case table name + tableName = [tableName lowercaseString]; + //search in sqlite_master table if table exists + FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName]; + //if at least one next exists, table exists + returnBool = [rs next]; + //close and free object + [rs close]; + + return returnBool; +} + +//get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] +//check if table exist in database (patch from OZLB) +- (FMResultSet*)getSchema { + + //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] + FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"]; + + return rs; +} + +//get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] +- (FMResultSet*)getTableSchema:(NSString*)tableName { + + //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] + FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"PRAGMA table_info(%@)", tableName]]; + + return rs; +} + + +//check if column exist in table +- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName { + + BOOL returnBool = NO; + //lower case table name + tableName = [tableName lowercaseString]; + //lower case column name + columnName = [columnName lowercaseString]; + //get table schema + FMResultSet *rs = [self getTableSchema: tableName]; + //check if column is present in table schema + while ([rs next]) { + if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString: columnName]) { + returnBool = YES; + break; + } + } + //close and free object + [rs close]; + + return returnBool; +} + +@end diff --git a/Classes/FMResultSet.h b/Classes/FMResultSet.h new file mode 100644 index 0000000..cff4fc3 --- /dev/null +++ b/Classes/FMResultSet.h @@ -0,0 +1,89 @@ +#import +#import "sqlite3.h" + +#ifndef __has_feature // Optional. +#define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif + +#ifndef NS_RETURNS_NOT_RETAINED +#if __has_feature(attribute_ns_returns_not_retained) +#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) +#else +#define NS_RETURNS_NOT_RETAINED +#endif +#endif + +@class FMDatabase; +@class FMStatement; + +@interface FMResultSet : NSObject { + FMDatabase *parentDB; + FMStatement *statement; + + NSString *query; + NSMutableDictionary *columnNameToIndexMap; + BOOL columnNamesSetup; +} + + ++ (id)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB; + +- (void)close; + +- (NSString *)query; +- (void)setQuery:(NSString *)value; + +- (FMStatement *)statement; +- (void)setStatement:(FMStatement *)value; + +- (void)setParentDB:(FMDatabase *)newDb; + +- (BOOL)next; +- (BOOL)hasAnotherRow; + +- (int)columnIndexForName:(NSString*)columnName; +- (NSString*)columnNameForIndex:(int)columnIdx; + +- (int)intForColumn:(NSString*)columnName; +- (int)intForColumnIndex:(int)columnIdx; + +- (long)longForColumn:(NSString*)columnName; +- (long)longForColumnIndex:(int)columnIdx; + +- (long long int)longLongIntForColumn:(NSString*)columnName; +- (long long int)longLongIntForColumnIndex:(int)columnIdx; + +- (BOOL)boolForColumn:(NSString*)columnName; +- (BOOL)boolForColumnIndex:(int)columnIdx; + +- (double)doubleForColumn:(NSString*)columnName; +- (double)doubleForColumnIndex:(int)columnIdx; + +- (NSString*)stringForColumn:(NSString*)columnName; +- (NSString*)stringForColumnIndex:(int)columnIdx; + +- (NSDate*)dateForColumn:(NSString*)columnName; +- (NSDate*)dateForColumnIndex:(int)columnIdx; + +- (NSData*)dataForColumn:(NSString*)columnName; +- (NSData*)dataForColumnIndex:(int)columnIdx; + +- (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx; +- (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName; + +/* +If you are going to use this data after you iterate over the next row, or after you close the +result set, make sure to make a copy of the data first (or just use dataForColumn:/dataForColumnIndex:) +If you don't, you're going to be in a world of hurt when you try and use the data. +*/ +- (NSData*)dataNoCopyForColumn:(NSString*)columnName NS_RETURNS_NOT_RETAINED; +- (NSData*)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED; + + +- (BOOL)columnIndexIsNull:(int)columnIdx; +- (BOOL)columnIsNull:(NSString*)columnName; + +- (void)kvcMagic:(id)object; +- (NSDictionary *)resultDict; + +@end diff --git a/Classes/FMResultSet.m b/Classes/FMResultSet.m new file mode 100644 index 0000000..3d44ccc --- /dev/null +++ b/Classes/FMResultSet.m @@ -0,0 +1,384 @@ +#import "FMResultSet.h" +#import "FMDatabase.h" +#import "unistd.h" + +@interface FMResultSet (Private) +- (NSMutableDictionary *)columnNameToIndexMap; +- (void)setColumnNameToIndexMap:(NSMutableDictionary *)value; +@end + +@implementation FMResultSet + ++ (id)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB { + + FMResultSet *rs = [[FMResultSet alloc] init]; + + [rs setStatement:statement]; + [rs setParentDB:aDB]; + + return [rs autorelease]; +} + +- (void)dealloc { + [self close]; + + [query release]; + query = nil; + + [columnNameToIndexMap release]; + columnNameToIndexMap = nil; + + [super dealloc]; +} + +- (void)close { + + [statement reset]; + [statement release]; + statement = nil; + + // we don't need this anymore... (i think) + //[parentDB setInUse:NO]; + parentDB = nil; +} + +- (void)setupColumnNames { + + if (!columnNameToIndexMap) { + [self setColumnNameToIndexMap:[NSMutableDictionary dictionary]]; + } + + int columnCount = sqlite3_column_count(statement.statement); + + int columnIdx = 0; + for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { + [columnNameToIndexMap setObject:[NSNumber numberWithInt:columnIdx] + forKey:[[NSString stringWithUTF8String:sqlite3_column_name(statement.statement, columnIdx)] lowercaseString]]; + } + columnNamesSetup = YES; +} + +- (void)kvcMagic:(id)object { + + int columnCount = sqlite3_column_count(statement.statement); + + int columnIdx = 0; + for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { + + const char *c = (const char *)sqlite3_column_text(statement.statement, columnIdx); + + // check for a null row + if (c) { + NSString *s = [NSString stringWithUTF8String:c]; + + [object setValue:s forKey:[NSString stringWithUTF8String:sqlite3_column_name(statement.statement, columnIdx)]]; + } + } +} + +- (NSDictionary *)resultDict { + + NSInteger num_cols = sqlite3_data_count(statement.statement); + + if (num_cols > 0) { + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols]; + + NSInteger i; + for (i = 0; i < num_cols; i++) { + + const char *col_name = sqlite3_column_name(statement.statement, i); + + if (col_name) { + NSString *colName = [NSString stringWithUTF8String:col_name]; + id value = nil; + + // fetch according to type + switch (sqlite3_column_type(statement.statement, i)) { + case SQLITE_INTEGER: { + value = [NSNumber numberWithInt:[self intForColumnIndex:i]]; + break; + } + case SQLITE_FLOAT: { + value = [NSNumber numberWithDouble:[self doubleForColumnIndex:i]]; + break; + } + case SQLITE_TEXT: { + value = [self stringForColumnIndex:i]; + break; + } + case SQLITE_BLOB: { + value = [self dataForColumnIndex:i]; + break; + } + } + + // save to dict + if (value) { + [dict setObject:value forKey:colName]; + } + } + } + + return [[dict copy] autorelease]; + } + else { + NSLog(@"Warning: There seem to be no columns in this set."); + } + + return nil; +} + +- (BOOL)next { + + int rc; + BOOL retry; + int numberOfRetries = 0; + do { + retry = NO; + + rc = sqlite3_step(statement.statement); + + if (SQLITE_BUSY == rc) { + // this will happen if the db is locked, like if we are doing an update or insert. + // in that case, retry the step... and maybe wait just 10 milliseconds. + retry = YES; + usleep(20); + + if ([parentDB busyRetryTimeout] && (numberOfRetries++ > [parentDB busyRetryTimeout])) { + + NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [parentDB databasePath]); + NSLog(@"Database busy"); + break; + } + } + else if (SQLITE_DONE == rc || SQLITE_ROW == rc) { + // all is well, let's return. + } + else if (SQLITE_ERROR == rc) { + NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle])); + break; + } + else if (SQLITE_MISUSE == rc) { + // uh oh. + NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle])); + break; + } + else { + // wtf? + NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle])); + break; + } + + } while (retry); + + + if (rc != SQLITE_ROW) { + [self close]; + } + + return (rc == SQLITE_ROW); +} + +- (BOOL)hasAnotherRow { + return sqlite3_errcode([parentDB sqliteHandle]) == SQLITE_ROW; +} + +- (int)columnIndexForName:(NSString*)columnName { + + if (!columnNamesSetup) { + [self setupColumnNames]; + } + + columnName = [columnName lowercaseString]; + + NSNumber *n = [columnNameToIndexMap objectForKey:columnName]; + + if (n) { + return [n intValue]; + } + + NSLog(@"Warning: I could not find the column named '%@'.", columnName); + + return -1; +} + + + +- (int)intForColumn:(NSString*)columnName { + return [self intForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (int)intForColumnIndex:(int)columnIdx { + return sqlite3_column_int(statement.statement, columnIdx); +} + +- (long)longForColumn:(NSString*)columnName { + return [self longForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (long)longForColumnIndex:(int)columnIdx { + return (long)sqlite3_column_int64(statement.statement, columnIdx); +} + +- (long long int)longLongIntForColumn:(NSString*)columnName { + return [self longLongIntForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (long long int)longLongIntForColumnIndex:(int)columnIdx { + return sqlite3_column_int64(statement.statement, columnIdx); +} + +- (BOOL)boolForColumn:(NSString*)columnName { + return [self boolForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (BOOL)boolForColumnIndex:(int)columnIdx { + return ([self intForColumnIndex:columnIdx] != 0); +} + +- (double)doubleForColumn:(NSString*)columnName { + return [self doubleForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (double)doubleForColumnIndex:(int)columnIdx { + return sqlite3_column_double(statement.statement, columnIdx); +} + +- (NSString*)stringForColumnIndex:(int)columnIdx { + + if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { + return nil; + } + + const char *c = (const char *)sqlite3_column_text(statement.statement, columnIdx); + + if (!c) { + // null row. + return nil; + } + + return [NSString stringWithUTF8String:c]; +} + +- (NSString*)stringForColumn:(NSString*)columnName { + return [self stringForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (NSDate*)dateForColumn:(NSString*)columnName { + return [self dateForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (NSDate*)dateForColumnIndex:(int)columnIdx { + + if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { + return nil; + } + + return [NSDate dateWithTimeIntervalSince1970:[self doubleForColumnIndex:columnIdx]]; +} + + +- (NSData*)dataForColumn:(NSString*)columnName { + return [self dataForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (NSData*)dataForColumnIndex:(int)columnIdx { + + if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { + return nil; + } + + int dataSize = sqlite3_column_bytes(statement.statement, columnIdx); + + NSMutableData *data = [NSMutableData dataWithLength:dataSize]; + + memcpy([data mutableBytes], sqlite3_column_blob(statement.statement, columnIdx), dataSize); + + return data; +} + + +- (NSData*)dataNoCopyForColumn:(NSString*)columnName { + return [self dataNoCopyForColumnIndex:[self columnIndexForName:columnName]]; +} + +- (NSData*)dataNoCopyForColumnIndex:(int)columnIdx { + + if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { + return nil; + } + + int dataSize = sqlite3_column_bytes(statement.statement, columnIdx); + + NSData *data = [NSData dataWithBytesNoCopy:(void *)sqlite3_column_blob(statement.statement, columnIdx) length:dataSize freeWhenDone:NO]; + + return data; +} + + +- (BOOL)columnIndexIsNull:(int)columnIdx { + return sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL; +} + +- (BOOL)columnIsNull:(NSString*)columnName { + return [self columnIndexIsNull:[self columnIndexForName:columnName]]; +} + +- (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx { + + if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { + return nil; + } + + return sqlite3_column_text(statement.statement, columnIdx); +} + +- (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName { + return [self UTF8StringForColumnIndex:[self columnIndexForName:columnName]]; +} + + +// returns autoreleased NSString containing the name of the column in the result set +- (NSString*)columnNameForIndex:(int)columnIdx { + return [NSString stringWithUTF8String: sqlite3_column_name(statement.statement, columnIdx)]; +} + +- (void)setParentDB:(FMDatabase *)newDb { + parentDB = newDb; +} + + +- (NSString *)query { + return query; +} + +- (void)setQuery:(NSString *)value { + [value retain]; + [query release]; + query = value; +} + +- (NSMutableDictionary *)columnNameToIndexMap { + return columnNameToIndexMap; +} + +- (void)setColumnNameToIndexMap:(NSMutableDictionary *)value { + [value retain]; + [columnNameToIndexMap release]; + columnNameToIndexMap = value; +} + +- (FMStatement *)statement { + return statement; +} + +- (void)setStatement:(FMStatement *)value { + if (statement != value) { + [statement release]; + statement = [value retain]; + } +} + + + +@end diff --git a/Classes/NSNumber+SP.h b/Classes/NSNumber+SP.h new file mode 100644 index 0000000..41eb6d3 --- /dev/null +++ b/Classes/NSNumber+SP.h @@ -0,0 +1,16 @@ +// +// NSNumber+SL.h +// SpotLook +// +// Created by Nicolas Seriot on 31.03.08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface NSNumber (SP) + +- (NSString *)prettyBytes; + +@end diff --git a/Classes/NSNumber+SP.m b/Classes/NSNumber+SP.m new file mode 100644 index 0000000..9d6a921 --- /dev/null +++ b/Classes/NSNumber+SP.m @@ -0,0 +1,36 @@ +// +// NSNumber+SL.m +// SpotLook +// +// Created by Nicolas Seriot on 31.03.08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import "NSNumber+SP.h" + + +@implementation NSNumber (SP) + +- (NSString *)prettyBytes { + float bytes = [self longValue]; + NSUInteger unit = 0; + + if(bytes < 1) { return @"-"; } + + while(bytes > 1024) { + bytes = bytes / 1024.0; + unit++; + } + + if(unit > 4) { return @"HUGE"; } + + NSString *unitString = [[NSArray arrayWithObjects:/* @"Bytes", */ @"KB", @"MB", @"GB", @"TB", @"PB", nil] objectAtIndex:unit]; + + if(unit == 0) { + return [NSString stringWithFormat:@"%d %@", (int)bytes, unitString]; + } else { + return [NSString stringWithFormat:@"%.2f %@", (float)bytes, unitString]; + } +} + +@end diff --git a/Classes/SPSourcePhoneTVC.h b/Classes/SPSourcePhoneTVC.h index 76e8e18..3954ce2 100755 --- a/Classes/SPSourcePhoneTVC.h +++ b/Classes/SPSourcePhoneTVC.h @@ -19,6 +19,9 @@ NSString *lastDialed; NSString *lastContact; NSString *lastForwardNumber; + NSMutableArray *callHistories; + NSString *prettyBytesSent; + NSString *prettyBytesReceived; } @property (nonatomic, retain) NSString *ICCID; @@ -29,5 +32,8 @@ @property (nonatomic, retain) NSString *lastDialed; @property (nonatomic, retain) NSString *lastContact; @property (nonatomic, retain) NSString *lastForwardNumber; +@property (nonatomic, retain) NSString *prettyBytesSent; +@property (nonatomic, retain) NSString *prettyBytesReceived; +@property (nonatomic, retain) NSMutableArray *callHistories; @end diff --git a/Classes/SPSourcePhoneTVC.m b/Classes/SPSourcePhoneTVC.m index e94002f..b4fe68e 100755 --- a/Classes/SPSourcePhoneTVC.m +++ b/Classes/SPSourcePhoneTVC.m @@ -10,6 +10,8 @@ #import "SPSourcePhoneTVC.h" #import "SPCell.h" #import +#import "FMDatabase.h" +#import "NSNumber+SP.h" @implementation SPSourcePhoneTVC @@ -21,6 +23,9 @@ @implementation SPSourcePhoneTVC @synthesize lastDialed; @synthesize lastContact; @synthesize lastForwardNumber; +@synthesize callHistories; +@synthesize prettyBytesSent; +@synthesize prettyBytesReceived; - (NSString *)nameOfABPersonWithID:(NSUInteger)recordID { ABAddressBookRef addressBook = ABAddressBookCreate(); @@ -54,13 +59,13 @@ - (NSString *)nameOfABPersonWithID:(NSUInteger)recordID { - (void)loadData { if(contentsDictionaries) return; - NSString *path = @"/var/mobile/Library/Preferences/com.apple.commcenter.plist"; + NSString *path = @"/private/var/wireless/Library/Preferences/com.apple.commcenter.plist"; NSDictionary *d = [NSDictionary dictionaryWithContentsOfFile:path]; - self.ICCID = [NSString stringWithFormat:@"%@", [d valueForKey:@"ICCID"]]; - self.IMSI = [NSString stringWithFormat:@"%@", [d valueForKey:@"IMSI"]]; + self.ICCID = [d valueForKey:@"ICCID"]; + self.IMSI = [d valueForKey:@"IMSI"]; self.phone = [[NSUserDefaults standardUserDefaults] valueForKey:@"SBFormattedPhoneNumber"]; - self.UUID = [[UIDevice currentDevice] uniqueIdentifier]; + self.UUID = [[UIDevice currentDevice] uniqueIdentifier]; /* NSBundle *b = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/Message.framework"]; BOOL success = [b load]; @@ -89,6 +94,55 @@ - (void)loadData { NSString *fullName = [self nameOfABPersonWithID:abId]; self.lastContact = fullName; + /**/ + + self.callHistories = [NSMutableArray array]; + + FMDatabase *db = [FMDatabase databaseWithPath:@"/private/var/wireless/Library/CallHistory/call_history.db"]; + +// NSLocale *usLocale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"] autorelease]; + + if([db open]) { + FMResultSet *rs = [db executeQuery:@"select address, date, flags, duration from call order by date"]; + while ([rs next]) { + int dateInt = [rs intForColumn:@"date"]; + NSDate *date = [NSDate dateWithTimeIntervalSince1970:dateInt]; + NSDateFormatter *df = [[NSDateFormatter alloc] init]; + [df setDateFormat:@"YYYY-MM-dd HH:mm"]; + NSString *dateString = [df stringFromDate:date]; + + int flagsInt = [rs intForColumn:@"flags"]; + NSString *flags = @"?"; + switch (flagsInt) { + case 4: flags = @"<-"; break; + case 5: flags = @"->"; break; + default: break; + } + + int durationInt = [rs intForColumn:@"duration"]; + NSString *duration = [NSString stringWithFormat:@"%d:%02d", durationInt / 60, durationInt % 60]; + + NSString *logLine = [NSString stringWithFormat:@"%@ %@ %@ (%@)", dateString, flags, [rs stringForColumn:@"address"], duration]; + [callHistories addObject:logLine]; + } + [rs close]; + + rs = [db executeQuery:@"select bytes_rcvd, bytes_sent from data where pdp_ip = 0"]; + while ([rs next]) { + double bytes_sent = [rs doubleForColumn:@"bytes_sent"]; + double bytes_rcvd = [rs doubleForColumn:@"bytes_rcvd"]; + + self.prettyBytesSent = [[NSNumber numberWithDouble:bytes_sent] prettyBytes]; + self.prettyBytesReceived = [[NSNumber numberWithDouble:bytes_rcvd] prettyBytes]; + } + + [rs close]; + + [db close]; + } + + /**/ + if(self.lastForwardNumber) { NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:self.lastForwardNumber], @"Call forwarding number", nil]; [self.contentsDictionaries addObject:dict]; @@ -123,6 +177,22 @@ - (void)loadData { NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:self.UUID], @"Device UUID", nil]; [self.contentsDictionaries addObject:dict]; } + + if(prettyBytesSent) { + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:prettyBytesSent], @"Cellular Network - Bytes Sent", nil]; + [self.contentsDictionaries addObject:dict]; + } + + if(prettyBytesReceived) { + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:prettyBytesReceived], @"Cellular Network - Bytes Received", nil]; + [self.contentsDictionaries addObject:dict]; + } + + if(callHistories) { + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:callHistories, @"Call History", nil]; + [self.contentsDictionaries addObject:dict]; + } + } - (void)didReceiveMemoryWarning { @@ -141,6 +211,10 @@ - (void)dealloc { [lastForwardNumber release]; [lastDialed release]; [lastContact release]; + [callHistories release]; + [prettyBytesSent release]; + [prettyBytesReceived release]; + [super dealloc]; } diff --git a/Classes/SPSourcePhotosTVC.m b/Classes/SPSourcePhotosTVC.m index a923395..d468bf2 100644 --- a/Classes/SPSourcePhotosTVC.m +++ b/Classes/SPSourcePhotosTVC.m @@ -29,12 +29,12 @@ - (void)mapButtonClicked:(id)sender { - (NSArray *)jpgPaths { NSMutableArray *a = [NSMutableArray array]; -// NSString *path = @"/var/mobile/Media/DCIM"; - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths count] ? [paths objectAtIndex:0] : nil; - NSString *path = [documentsDirectory stringByAppendingPathComponent:@"../../../Media/DCIM"]; - path = [path stringByStandardizingPath]; - + NSString *path = @"/var/mobile/Media/PhotoData/100APPLE"; +// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); +// NSString *documentsDirectory = [paths count] ? [paths objectAtIndex:0] : nil; +// NSString *path = [documentsDirectory stringByAppendingPathComponent:@"../../../Media/DCIM"]; +// path = [path stringByStandardizingPath]; + NSDirectoryEnumerator *dirEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:path]; BOOL isDir; @@ -46,7 +46,7 @@ - (NSArray *)jpgPaths { while(dirContent = [dirEnumerator nextObject]) { filePath = [path stringByAppendingPathComponent:dirContent]; exists = [[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDir]; - if(exists && !isDir && [[filePath pathExtension] isEqualToString:@"JPG"]) { + if(exists && !isDir && [[filePath pathExtension] isEqualToString:@"THM"]) { [a addObject:filePath]; } } @@ -68,15 +68,15 @@ - (void)readPhotosInNewThread { subpool = [[NSAutoreleasePool alloc] init]; CLLocationCoordinate2D coord = [UIImage coordinatesOfImageAtPath:s]; - if(coord.latitude == 0.0 && coord.longitude == 0.0) continue; - + //if(coord.latitude == 0.0 && coord.longitude == 0.0) continue; NSNumber *lat = [NSNumber numberWithDouble:coord.latitude]; NSNumber *lon = [NSNumber numberWithDouble:coord.longitude]; [coordinates addObject:[NSArray arrayWithObjects:lat, lon, nil]]; - NSString *coordString = [NSString stringWithFormat:@"%@, %@", lat, lon]; - + NSString *coordString = (lat && lon) ? [NSString stringWithFormat:@"%@, %@", lat, lon] : nil; + + NSError *error = nil; NSDictionary *d = [[NSFileManager defaultManager] attributesOfItemAtPath:s error:&error]; if(!d) { @@ -88,7 +88,7 @@ - (void)readPhotosInNewThread { SPImageAnnotation *annotation = [SPImageAnnotation annotationWithCoordinate:coord date:date path:s]; [annotations performSelectorOnMainThread:@selector(addObject:) withObject:annotation waitUntilDone:YES]; - + NSDictionary *cd = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:coordString] forKey:dateString]; [contentsDictionaries performSelectorOnMainThread:@selector(addObject:) withObject:cd waitUntilDone:YES]; @@ -102,6 +102,7 @@ - (void)readPhotosInNewThread { } - (void)loadData { + if(contentsDictionaries) return; UIBarButtonItem *mapButton = [[UIBarButtonItem alloc] initWithTitle:@"Map" style:UIBarButtonItemStylePlain target:self action:@selector(mapButtonClicked:)]; diff --git a/Classes/SpyPhoneAppDelegate.m b/Classes/SpyPhoneAppDelegate.m index 35e708b..39a5025 100644 --- a/Classes/SpyPhoneAppDelegate.m +++ b/Classes/SpyPhoneAppDelegate.m @@ -23,11 +23,12 @@ - (void)applicationDidFinishLaunching:(UIApplication *)application { // Add the tab bar controller's current view as a subview of the window [window addSubview:tabBarController.view]; - + /* BOOL isTVOutEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"TVOutEnabled"]; if(isTVOutEnabled) { [[UIApplication sharedApplication] startTVOut]; } + */ } diff --git a/SpyPhone.xcodeproj/nst.pbxuser b/SpyPhone.xcodeproj/nst.pbxuser index 7f98ed8..b97ba04 100644 --- a/SpyPhone.xcodeproj/nst.pbxuser +++ b/SpyPhone.xcodeproj/nst.pbxuser @@ -1,62 +1,11 @@ // !$*UTF8*$! { - 0315FC701101F1EE00760B3B /* PlistBookmark */ = { - isa = PlistBookmark; - fRef = 0317DEC910FF9CB400C5C2D4 /* Root.plist */; - fallbackIsa = PBXBookmark; - isK = 0; - kPath = ( - ); - name = /Users/nst/Projects/SpyPhone/Settings.bundle/Root.plist; - rLen = 0; - rLoc = 9223372036854775807; - }; - 0315FC711101F1EE00760B3B /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 0328F96010B0CB140074A5A1 /* SPSourceAddressBookTVC.m */; - rLen = 9; - rLoc = 962; - rType = 0; - }; - 0315FC721101F1EE00760B3B /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 0328F96010B0CB140074A5A1 /* SPSourceAddressBookTVC.m */; - name = "SPSourceAddressBookTVC.m: 39"; - rLen = 0; - rLoc = 967; - rType = 0; - vrLen = 1119; - vrLoc = 0; - }; - 0315FC781101F26D00760B3B /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 0328F96010B0CB140074A5A1 /* SPSourceAddressBookTVC.m */; - name = "SPSourceAddressBookTVC.m: 17"; - rLen = 0; - rLoc = 348; - rType = 0; - vrLen = 1119; - vrLoc = 0; - }; - 0315FC791101F26F00760B3B /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 0328F96010B0CB140074A5A1 /* SPSourceAddressBookTVC.m */; - name = "SPSourceAddressBookTVC.m: 17"; - rLen = 0; - rLoc = 348; - rType = 0; - vrLen = 1119; - vrLoc = 0; - }; - 0315FC7A1101F27D00760B3B /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 0328F96010B0CB140074A5A1 /* SPSourceAddressBookTVC.m */; - name = "SPSourceAddressBookTVC.m: 17"; - rLen = 0; - rLoc = 348; - rType = 0; - vrLen = 1119; - vrLoc = 0; + 0310C65410C4BE0800E7ACD2 /* SPImageVC.m */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1078, 598}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 765}"; + }; }; 031748B710B6E35C00B6116E /* SPEmailASAccount.h */ = { uiCtxt = { @@ -144,124 +93,11 @@ }; 0317DE5110FF954800C5C2D4 /* UIApplication_TVOut.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1391, 1755}}"; - sepNavSelRange = "{195, 0}"; - sepNavVisRange = "{0, 403}"; + sepNavIntBoundsRect = "{{0, 0}, {733, 1612}}"; + sepNavSelRange = "{1530, 0}"; + sepNavVisRange = "{1378, 762}"; }; }; - 0317DE5510FF95AE00C5C2D4 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 031748BF10B6E63E00B6116E /* SPEmailAccount.m */; - name = "SPEmailAccount.m: 50"; - rLen = 0; - rLoc = 1259; - rType = 0; - vrLen = 1043; - vrLoc = 258; - }; - 0317DE5610FF95AE00C5C2D4 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 28216C960DB411BC00E5133A /* FirstViewController.m */; - name = "FirstViewController.m: 10"; - rLen = 0; - rLoc = 206; - rType = 0; - vrLen = 604; - vrLoc = 0; - }; - 0317DE5710FF95AE00C5C2D4 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 28216C950DB411BC00E5133A /* FirstViewController.h */; - name = "FirstViewController.h: 13"; - rLen = 0; - rLoc = 214; - rType = 0; - vrLen = 272; - vrLoc = 0; - }; - 0317DE8A10FF995B00C5C2D4 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 29B97316FDCFA39411CA2CEA /* main.m */; - name = "main.m: 19"; - rLen = 0; - rLoc = 390; - rType = 0; - vrLen = 390; - vrLoc = 0; - }; - 0317DE8D10FF995B00C5C2D4 /* Root.plist */ = { - isa = PBXFileReference; - lastKnownFileType = text.plist.xml; - name = Root.plist; - path = /Users/nst/Projects/SpyPhone/Settings.bundle/Root.plist; - sourceTree = ""; - }; - 0317DE8E10FF995B00C5C2D4 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 0317DE8F10FF995B00C5C2D4 /* NSUserDefaults.h */; - name = "NSUserDefaults.h: 19"; - rLen = 42; - rLoc = 439; - rType = 0; - vrLen = 1484; - vrLoc = 115; - }; - 0317DE8F10FF995B00C5C2D4 /* NSUserDefaults.h */ = { - isa = PBXFileReference; - lastKnownFileType = sourcecode.c.h; - name = NSUserDefaults.h; - path = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.2.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSUserDefaults.h; - sourceTree = ""; - }; - 0317DE9B10FF99DB00C5C2D4 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 1D3623250D0F684500981E51 /* SpyPhoneAppDelegate.m */; - name = "SpyPhoneAppDelegate.m: 27"; - rLen = 0; - rLoc = 654; - rType = 0; - vrLen = 1076; - vrLoc = 45; - }; - 0317DE9C10FF99DB00C5C2D4 /* PlistBookmark */ = { - isa = PlistBookmark; - fRef = 0317DE8D10FF995B00C5C2D4 /* Root.plist */; - fallbackIsa = PBXBookmark; - isK = 0; - kPath = ( - ); - name = /Users/nst/Projects/SpyPhone/Settings.bundle/Root.plist; - rLen = 0; - rLoc = 9223372036854775808; - }; - 0317DEC610FF9C4E00C5C2D4 /* PBXTextBookmark */ = { - isa = PBXTextBookmark; - fRef = 0317DE5110FF954800C5C2D4 /* UIApplication_TVOut.m */; - name = "UIApplication_TVOut.m: 11"; - rLen = 0; - rLoc = 195; - rType = 0; - vrLen = 779; - vrLoc = 0; - }; - 0317DEC810FF9CB400C5C2D4 /* PlistBookmark */ = { - isa = PlistBookmark; - fRef = 0317DEC910FF9CB400C5C2D4 /* Root.plist */; - fallbackIsa = PBXBookmark; - isK = 0; - kPath = ( - ); - name = /Users/nst/Projects/SpyPhone/Settings.bundle/Root.plist; - rLen = 0; - rLoc = 9223372036854775808; - }; - 0317DEC910FF9CB400C5C2D4 /* Root.plist */ = { - isa = PBXFileReference; - lastKnownFileType = text.plist.xml; - name = Root.plist; - path = /Users/nst/Projects/SpyPhone/Settings.bundle/Root.plist; - sourceTree = ""; - }; 0328F4AB10B05E890074A5A1 /* SpyPhone */ = { isa = PBXExecutable; activeArgIndices = ( @@ -269,7 +105,7 @@ argumentStrings = ( ); autoAttachOnCrash = 1; - breakpointsEnabled = 0; + breakpointsEnabled = 1; configStateDict = { }; customDataFormattersEnabled = 1; @@ -317,9 +153,9 @@ }; 0328F4CE10B0614A0074A5A1 /* SPAllSourcesTVC.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1391, 1612}}"; - sepNavSelRange = "{2569, 0}"; - sepNavVisRange = "{2213, 731}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 1560}}"; + sepNavSelRange = "{2158, 275}"; + sepNavVisRange = "{1836, 1113}"; }; }; 0328F50810B065530074A5A1 /* SPCell.h */ = { @@ -338,7 +174,7 @@ }; 0328F56810B071110074A5A1 /* SPSourceEmailTVC.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1078, 540}}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 507}}"; sepNavSelRange = "{285, 0}"; sepNavVisRange = "{0, 389}"; }; @@ -361,16 +197,16 @@ hitCount = 0; ignoreCount = 0; location = libobjc.A.dylib; - modificationTime = 283641462.5322911; + modificationTime = 305591634.606102; originalNumberOfMultipleMatches = 1; state = 1; symbolName = objc_exception_throw; }; 0328F61710B07F360074A5A1 /* SPSourceWifiTVC.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1078, 465}}"; - sepNavSelRange = "{234, 0}"; - sepNavVisRange = "{0, 283}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 499}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 278}"; }; }; 0328F61810B07F360074A5A1 /* SPSourceWifiTVC.m */ = { @@ -382,30 +218,30 @@ }; 0328F6BA10B088DD0074A5A1 /* SPSourcePhoneTVC.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1078, 525}}"; - sepNavSelRange = "{410, 0}"; - sepNavVisRange = "{0, 846}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 520}}"; + sepNavSelRange = "{1048, 0}"; + sepNavVisRange = "{42, 1075}"; }; }; 0328F6BB10B088DD0074A5A1 /* SPSourcePhoneTVC.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1097, 1833}}"; - sepNavSelRange = "{2503, 6}"; - sepNavVisRange = "{1637, 1896}"; + sepNavIntBoundsRect = "{{0, 0}, {1391, 2821}}"; + sepNavSelRange = "{4446, 0}"; + sepNavVisRange = "{3845, 792}"; }; }; 0328F75010B09AA60074A5A1 /* SPSourceLocationTVC.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1078, 452}}"; - sepNavSelRange = "{289, 0}"; - sepNavVisRange = "{0, 767}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 716}}"; + sepNavSelRange = "{811, 0}"; + sepNavVisRange = "{0, 811}"; }; }; 0328F75110B09AA60074A5A1 /* SPSourceLocationTVC.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1078, 1235}}"; - sepNavSelRange = "{1008, 6}"; - sepNavVisRange = "{477, 1760}"; + sepNavIntBoundsRect = "{{0, 0}, {1097, 1144}}"; + sepNavSelRange = "{399, 0}"; + sepNavVisRange = "{179, 2032}"; }; }; 0328F80710B0A6FB0074A5A1 /* SPSourceSafariTVC.h */ = { @@ -445,9 +281,9 @@ }; 0328F80E10B0A8B70074A5A1 /* SPSourcePhotosTVC.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1132, 1924}}"; - sepNavSelRange = "{4348, 6}"; - sepNavVisRange = "{3415, 1399}"; + sepNavIntBoundsRect = "{{0, 0}, {1391, 1859}}"; + sepNavSelRange = "{2927, 0}"; + sepNavVisRange = "{2124, 920}"; }; }; 0328F8BE10B0B1AE0074A5A1 /* SPWebViewVC.h */ = { @@ -473,9 +309,9 @@ }; 0328F96010B0CB140074A5A1 /* SPSourceAddressBookTVC.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1391, 871}}"; - sepNavSelRange = "{348, 0}"; - sepNavVisRange = "{0, 485}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 910}}"; + sepNavSelRange = "{349, 0}"; + sepNavVisRange = "{0, 881}"; }; }; 032A7B9110B829DB00E7FB65 /* EXFLogging.h */ = { @@ -592,16 +428,16 @@ }; 032A7BA110B829DB00E7FB65 /* EXFUtils.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1160, 520}}"; - sepNavSelRange = "{1030, 0}"; - sepNavVisRange = "{80, 1324}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 533}}"; + sepNavSelRange = "{1168, 20}"; + sepNavVisRange = "{32, 1414}"; }; }; 032A7BA210B829DB00E7FB65 /* EXFUtils.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1391, 3601}}"; - sepNavSelRange = "{4190, 0}"; - sepNavVisRange = "{3693, 467}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 3497}}"; + sepNavSelRange = "{4048, 20}"; + sepNavVisRange = "{3844, 1236}"; }; }; 032A7E0410B84C1800E7FB65 /* UIImage+GPS.h */ = { @@ -614,8 +450,8 @@ 032A7E0510B84C1800E7FB65 /* UIImage+GPS.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1167, 520}}"; - sepNavSelRange = "{487, 6}"; - sepNavVisRange = "{0, 1547}"; + sepNavSelRange = "{356, 69}"; + sepNavVisRange = "{0, 1639}"; }; }; 032A7EAF10B85E9C00E7FB65 /* SPMapVC.h */ = { @@ -627,9 +463,9 @@ }; 032A7EB010B85E9C00E7FB65 /* SPMapVC.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1391, 1261}}"; - sepNavSelRange = "{1709, 0}"; - sepNavVisRange = "{1441, 571}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 1248}}"; + sepNavSelRange = "{1741, 0}"; + sepNavVisRange = "{164, 1319}"; }; }; 032A7EC910B8617C00E7FB65 /* SPImageAnnotation.h */ = { @@ -660,6 +496,16 @@ sepNavVisRange = "{321, 668}"; }; }; + 032E9C1C12369AB400B08386 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 0364948A10B28BC800C88803 /* SPSourceTVC.h */; + name = "SPSourceTVC.h: 27"; + rLen = 0; + rLoc = 490; + rType = 0; + vrLen = 497; + vrLoc = 0; + }; 0364933F10B16DDD00C88803 /* SPSourceKeyboardTVC.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1078, 452}}"; @@ -669,23 +515,23 @@ }; 0364934010B16DDD00C88803 /* SPSourceKeyboardTVC.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1078, 1586}}"; - sepNavSelRange = "{1548, 0}"; - sepNavVisRange = "{1113, 1200}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 1638}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1049}"; }; }; 0364948A10B28BC800C88803 /* SPSourceTVC.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1078, 619}}"; - sepNavSelRange = "{0, 0}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 507}}"; + sepNavSelRange = "{490, 0}"; sepNavVisRange = "{0, 497}"; }; }; 0364948B10B28BC800C88803 /* SPSourceTVC.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1078, 1105}}"; - sepNavSelRange = "{2278, 0}"; - sepNavVisRange = "{997, 1303}"; + sepNavSelRange = "{359, 0}"; + sepNavVisRange = "{0, 947}"; }; }; 037D3A7F10F3D57B003A85B0 /* SPEmailMobileMeAccount.h */ = { @@ -702,33 +548,153 @@ sepNavVisRange = "{396, 640}"; }; }; - 037D3AA510F3D7C6003A85B0 /* PBXTextBookmark */ = { + 03B6EFC910BB547600CF9139 /* gpl-2.0.txt */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1078, 4420}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1849}"; + }; + }; + 03F2470F1236E1440017F214 /* FMDatabase.m */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1078, 10023}}"; + sepNavSelRange = "{799, 15}"; + sepNavVisRange = "{508, 765}"; + }; + }; + 03F247131236E1440017F214 /* FMResultSet.m */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1078, 5148}}"; + sepNavSelRange = "{6730, 50}"; + sepNavVisRange = "{6229, 1085}"; + }; + }; + 03F247DE1236EABC0017F214 /* PBXTextBookmark */ = { isa = PBXTextBookmark; - fRef = 037D3A7F10F3D57B003A85B0 /* SPEmailMobileMeAccount.h */; - name = "SPEmailMobileMeAccount.h: 1"; - rLen = 0; - rLoc = 0; + fRef = 03F247DF1236EABC0017F214 /* NSDictionary.h */; + name = "NSDictionary.h: 12"; + rLen = 94; + rLoc = 241; rType = 0; - vrLen = 274; - vrLoc = 0; + vrLen = 969; + vrLoc = 1901; + }; + 03F247DF1236EABC0017F214 /* NSDictionary.h */ = { + isa = PBXFileReference; + name = NSDictionary.h; + path = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.2.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSDictionary.h; + sourceTree = ""; + }; + 03F248041236EC710017F214 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 03F248051236EC710017F214 /* NSString.h */; + name = "NSString.h: 88"; + rLen = 71; + rLoc = 4252; + rType = 0; + vrLen = 869; + vrLoc = 3642; }; - 037D3AA610F3D7C6003A85B0 /* PBXTextBookmark */ = { + 03F248051236EC710017F214 /* NSString.h */ = { + isa = PBXFileReference; + name = NSString.h; + path = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.2.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSString.h; + sourceTree = ""; + }; + 03F248161236EE3A0017F214 /* PBXTextBookmark */ = { isa = PBXTextBookmark; - fRef = 037D3A8010F3D57B003A85B0 /* SPEmailMobileMeAccount.m */; - name = "SPEmailMobileMeAccount.m: 28"; + fRef = 0328F96010B0CB140074A5A1 /* SPSourceAddressBookTVC.m */; + name = "SPSourceAddressBookTVC.m: 18"; rLen = 0; - rLoc = 856; + rLoc = 349; rType = 0; - vrLen = 1036; + vrLen = 881; vrLoc = 0; }; - 03B6EFC910BB547600CF9139 /* gpl-2.0.txt */ = { + 03F2481D1236EFAC0017F214 /* NSNumber+SP.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1078, 4420}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRange = "{0, 1849}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 460}}"; + sepNavSelRange = "{202, 0}"; + sepNavVisRange = "{0, 238}"; + }; + }; + 03F2481E1236EFAC0017F214 /* NSNumber+SP.m */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1391, 481}}"; + sepNavSelRange = "{483, 0}"; + sepNavVisRange = "{261, 470}"; }; }; + 03F248261236F02C0017F214 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 03F2470F1236E1440017F214 /* FMDatabase.m */; + name = "FMDatabase.m: 45"; + rLen = 15; + rLoc = 799; + rType = 0; + vrLen = 765; + vrLoc = 508; + }; + 03F248331236F0DD0017F214 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 0328F6BB10B088DD0074A5A1 /* SPSourcePhoneTVC.m */; + name = "SPSourcePhoneTVC.m: 133"; + rLen = 0; + rLoc = 4446; + rType = 0; + vrLen = 1267; + vrLoc = 3392; + }; + 03F248341236F0DD0017F214 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 03F2481D1236EFAC0017F214 /* NSNumber+SP.h */; + name = "NSNumber+SP.h: 12"; + rLen = 0; + rLoc = 202; + rType = 0; + vrLen = 238; + vrLoc = 0; + }; + 03F2483D1236F3300017F214 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 03F2481E1236EFAC0017F214 /* NSNumber+SP.m */; + name = "NSNumber+SP.m: 27"; + rLen = 0; + rLoc = 483; + rType = 0; + vrLen = 728; + vrLoc = 3; + }; + 03F248611236F4CE0017F214 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 032A7E0510B84C1800E7FB65 /* UIImage+GPS.m */; + name = "UIImage+GPS.m: 16"; + rLen = 69; + rLoc = 356; + rType = 0; + vrLen = 1639; + vrLoc = 0; + }; + 03F2486C1236F54A0017F214 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 0328F80E10B0A8B70074A5A1 /* SPSourcePhotosTVC.m */; + name = "SPSourcePhotosTVC.m: 91"; + rLen = 0; + rLoc = 2927; + rType = 0; + vrLen = 920; + vrLoc = 2124; + }; + 03F248701236F5A20017F214 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 0328F80E10B0A8B70074A5A1 /* SPSourcePhotosTVC.m */; + name = "SPSourcePhotosTVC.m: 91"; + rLen = 0; + rLoc = 2927; + rType = 0; + vrLen = 1558; + vrLoc = 1852; + }; 1D3623240D0F684500981E51 /* SpyPhoneAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1160, 446}}"; @@ -738,9 +704,9 @@ }; 1D3623250D0F684500981E51 /* SpyPhoneAppDelegate.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1391, 624}}"; - sepNavSelRange = "{639, 0}"; - sepNavVisRange = "{366, 554}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 728}}"; + sepNavSelRange = "{545, 0}"; + sepNavVisRange = "{272, 655}"; }; }; 1D6058900D05DD3D006BFB54 /* SpyPhone */ = { @@ -751,15 +717,15 @@ }; 28216C950DB411BC00E5133A /* FirstViewController.h */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1078, 535}}"; - sepNavSelRange = "{214, 0}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 507}}"; + sepNavSelRange = "{272, 0}"; sepNavVisRange = "{0, 272}"; }; }; 28216C960DB411BC00E5133A /* FirstViewController.m */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1078, 535}}"; - sepNavSelRange = "{206, 0}"; + sepNavIntBoundsRect = "{{0, 0}, {1078, 507}}"; + sepNavSelRange = "{598, 0}"; sepNavVisRange = "{0, 604}"; }; }; @@ -773,7 +739,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { activeBuildConfigurationName = Debug; activeExecutable = 0328F4AB10B05E890074A5A1 /* SpyPhone */; - activeSDKPreference = iphoneos3.1.2; + activeSDKPreference = iphoneos3.2; activeTarget = 1D6058900D05DD3D006BFB54 /* SpyPhone */; addToTargets = ( 1D6058900D05DD3D006BFB54 /* SpyPhone */, @@ -824,6 +790,20 @@ PBXBookmarksDataSource_CommentsID, ); }; + PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 22, + 300, + 776, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXExecutablesDataSource_ActiveFlagID, + PBXExecutablesDataSource_NameID, + PBXExecutablesDataSource_CommentsID, + ); + }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; @@ -866,7 +846,7 @@ 20, 864, 20, - 48.16259765625, + 48, 43, 43, 20, @@ -887,7 +867,7 @@ PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, - 930, + 848, 60, 20, 48, @@ -904,27 +884,21 @@ PBXFileDataSource_Warnings_ColumnID, ); }; - PBXPerProjectTemplateStateSaveDate = 285340118; - PBXWorkspaceStateSaveDate = 285340118; + PBXPerProjectTemplateStateSaveDate = 305585841; + PBXWorkspaceStateSaveDate = 305585841; }; perUserProjectItems = { - 0315FC701101F1EE00760B3B /* PlistBookmark */ = 0315FC701101F1EE00760B3B /* PlistBookmark */; - 0315FC711101F1EE00760B3B /* PBXTextBookmark */ = 0315FC711101F1EE00760B3B /* PBXTextBookmark */; - 0315FC721101F1EE00760B3B /* PBXTextBookmark */ = 0315FC721101F1EE00760B3B /* PBXTextBookmark */; - 0315FC781101F26D00760B3B /* PBXTextBookmark */ = 0315FC781101F26D00760B3B /* PBXTextBookmark */; - 0315FC791101F26F00760B3B /* PBXTextBookmark */ = 0315FC791101F26F00760B3B /* PBXTextBookmark */; - 0315FC7A1101F27D00760B3B /* PBXTextBookmark */ = 0315FC7A1101F27D00760B3B /* PBXTextBookmark */; - 0317DE5510FF95AE00C5C2D4 = 0317DE5510FF95AE00C5C2D4 /* PBXTextBookmark */; - 0317DE5610FF95AE00C5C2D4 = 0317DE5610FF95AE00C5C2D4 /* PBXTextBookmark */; - 0317DE5710FF95AE00C5C2D4 = 0317DE5710FF95AE00C5C2D4 /* PBXTextBookmark */; - 0317DE8A10FF995B00C5C2D4 = 0317DE8A10FF995B00C5C2D4 /* PBXTextBookmark */; - 0317DE8E10FF995B00C5C2D4 = 0317DE8E10FF995B00C5C2D4 /* PBXTextBookmark */; - 0317DE9B10FF99DB00C5C2D4 = 0317DE9B10FF99DB00C5C2D4 /* PBXTextBookmark */; - 0317DE9C10FF99DB00C5C2D4 = 0317DE9C10FF99DB00C5C2D4 /* PlistBookmark */; - 0317DEC610FF9C4E00C5C2D4 = 0317DEC610FF9C4E00C5C2D4 /* PBXTextBookmark */; - 0317DEC810FF9CB400C5C2D4 = 0317DEC810FF9CB400C5C2D4 /* PlistBookmark */; - 037D3AA510F3D7C6003A85B0 = 037D3AA510F3D7C6003A85B0 /* PBXTextBookmark */; - 037D3AA610F3D7C6003A85B0 = 037D3AA610F3D7C6003A85B0 /* PBXTextBookmark */; + 032E9C1C12369AB400B08386 /* PBXTextBookmark */ = 032E9C1C12369AB400B08386 /* PBXTextBookmark */; + 03F247DE1236EABC0017F214 /* PBXTextBookmark */ = 03F247DE1236EABC0017F214 /* PBXTextBookmark */; + 03F248041236EC710017F214 /* PBXTextBookmark */ = 03F248041236EC710017F214 /* PBXTextBookmark */; + 03F248161236EE3A0017F214 /* PBXTextBookmark */ = 03F248161236EE3A0017F214 /* PBXTextBookmark */; + 03F248261236F02C0017F214 /* PBXTextBookmark */ = 03F248261236F02C0017F214 /* PBXTextBookmark */; + 03F248331236F0DD0017F214 /* PBXTextBookmark */ = 03F248331236F0DD0017F214 /* PBXTextBookmark */; + 03F248341236F0DD0017F214 /* PBXTextBookmark */ = 03F248341236F0DD0017F214 /* PBXTextBookmark */; + 03F2483D1236F3300017F214 /* PBXTextBookmark */ = 03F2483D1236F3300017F214 /* PBXTextBookmark */; + 03F248611236F4CE0017F214 /* PBXTextBookmark */ = 03F248611236F4CE0017F214 /* PBXTextBookmark */; + 03F2486C1236F54A0017F214 /* PBXTextBookmark */ = 03F2486C1236F54A0017F214 /* PBXTextBookmark */; + 03F248701236F5A20017F214 /* PBXTextBookmark */ = 03F248701236F5A20017F214 /* PBXTextBookmark */; }; sourceControlManager = 0328F4B810B05E8E0074A5A1 /* Source Control */; userBuildSettings = { diff --git a/SpyPhone.xcodeproj/nst.perspectivev3 b/SpyPhone.xcodeproj/nst.perspectivev3 index 9843443..cf7dfea 100644 --- a/SpyPhone.xcodeproj/nst.perspectivev3 +++ b/SpyPhone.xcodeproj/nst.perspectivev3 @@ -3,7 +3,7 @@ ActivePerspectiveName - Project + Debug AllowedModules @@ -291,9 +291,9 @@ 29B97314FDCFA39411CA2CEA 080E96DDFE201D6D7F000001 + 031748C210B6E68E00B6116E 29B97315FDCFA39411CA2CEA 29B97317FDCFA39411CA2CEA - 0317DE7B10FF98E900C5C2D4 29B97323FDCFA39411CA2CEA 19C28FACFE9D520D11CA2CBB 1C37FBAC04509CD000000102 @@ -303,12 +303,14 @@ PBXSmartGroupTreeModuleOutlineStateSelectionKey - 65 - 63 + 22 + 6 + 2 + 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 498}, {291, 760}} + {{0, 0}, {291, 713}} PBXTopSmartGroupGIDs @@ -318,7 +320,7 @@ GeometryConfiguration Frame - {{0, 0}, {308, 778}} + {{0, 0}, {308, 731}} GroupTreeTableConfiguration TargetStatusColumn @@ -326,8 +328,6 @@ MainColumn 269 - RubberWindowFrame - 0 59 1440 819 0 0 1440 878 Module PBXSmartGroupTreeModule @@ -343,7 +343,7 @@ PBXProjectModuleGUID 0328F4B210B05E8E0074A5A1 PBXProjectModuleLabel - SPSourceAddressBookTVC.m + SPSourcePhotosTVC.m PBXSplitModuleInNavigatorKey Split0 @@ -351,23 +351,23 @@ PBXProjectModuleGUID 0328F4B310B05E8E0074A5A1 PBXProjectModuleLabel - SPSourceAddressBookTVC.m + SPSourcePhotosTVC.m _historyCapacity 10 bookmark - 0315FC791101F26F00760B3B + 03F248701236F5A20017F214 history - 037D3AA610F3D7C6003A85B0 - 0317DE5510FF95AE00C5C2D4 - 0317DE5610FF95AE00C5C2D4 - 0317DE5710FF95AE00C5C2D4 - 0317DE8A10FF995B00C5C2D4 - 0317DE8E10FF995B00C5C2D4 - 0317DE9B10FF99DB00C5C2D4 - 0317DEC610FF9C4E00C5C2D4 - 0315FC701101F1EE00760B3B - 0315FC781101F26D00760B3B + 03F248261236F02C0017F214 + 032E9C1C12369AB400B08386 + 03F247DE1236EABC0017F214 + 03F248041236EC710017F214 + 03F248331236F0DD0017F214 + 03F248341236F0DD0017F214 + 03F2483D1236F3300017F214 + 03F248161236EE3A0017F214 + 03F248611236F4CE0017F214 + 03F2486C1236F54A0017F214 SplitCount @@ -381,18 +381,16 @@ GeometryConfiguration Frame - {{0, 0}, {1127, 561}} - RubberWindowFrame - 0 59 1440 819 0 0 1440 878 + {{0, 0}, {1127, 517}} Module PBXNavigatorGroup Proportion - 561pt + 517pt Proportion - 212pt + 209pt Tabs @@ -406,7 +404,7 @@ GeometryConfiguration Frame - {{10, 27}, {1127, 185}} + {{10, 27}, {1127, 182}} Module XCDetailModule @@ -422,7 +420,7 @@ GeometryConfiguration Frame - {{10, 27}, {1127, 185}} + {{10, 27}, {1127, 182}} Module PBXProjectFindModule @@ -460,9 +458,7 @@ GeometryConfiguration Frame - {{10, 27}, {1127, 185}} - RubberWindowFrame - 0 59 1440 819 0 0 1440 878 + {{10, 27}, {1127, 182}} Module PBXBuildResultsModule @@ -490,11 +486,11 @@ TableOfContents - 0315FC731101F1EE00760B3B + 03F246D61236DED70017F214 1CA23ED40692098700951B8B - 0315FC741101F1EE00760B3B + 03F246D71236DED70017F214 0328F4B210B05E8E0074A5A1 - 0315FC751101F1EE00760B3B + 03F246D81236DED70017F214 1CA23EDF0692099D00951B8B 1CA23EE00692099D00951B8B 1CA23EE10692099D00951B8B @@ -535,6 +531,8 @@ Layout + BecomeActive + ContentConfiguration PBXProjectModuleGUID @@ -545,12 +543,14 @@ GeometryConfiguration Frame - {{0, 0}, {1440, 203}} + {{0, 0}, {1440, 152}} + RubberWindowFrame + 0 106 1440 772 0 0 1440 878 Module PBXDebugCLIModule Proportion - 203pt + 152pt ContentConfiguration @@ -569,8 +569,8 @@ yes sizes - {{0, 0}, {703, 276}} - {{703, 0}, {737, 276}} + {{0, 0}, {703, 277}} + {{703, 0}, {737, 277}} VerticalSplitView @@ -585,8 +585,8 @@ yes sizes - {{0, 0}, {1440, 276}} - {{0, 276}, {1440, 294}} + {{0, 0}, {1440, 277}} + {{0, 277}, {1440, 297}} @@ -606,7 +606,7 @@ DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame - {{0, 208}, {1440, 570}} + {{0, 157}, {1440, 574}} PBXDebugSessionStackFrameViewKey DebugVariablesTableConfiguration @@ -619,13 +619,17 @@ 507 Frame - {{703, 0}, {737, 276}} + {{703, 0}, {737, 277}} + RubberWindowFrame + 0 106 1440 772 0 0 1440 878 + RubberWindowFrame + 0 106 1440 772 0 0 1440 878 Module PBXDebugSessionModule Proportion - 570pt + 574pt Name @@ -643,13 +647,13 @@ TableOfContents - 0317DE4910FF952400C5C2D4 + 03F246D91236DED70017F214 1CCC7628064C1048000F2A68 1CCC7629064C1048000F2A68 - 0317DE4A10FF952400C5C2D4 - 0317DE4B10FF952400C5C2D4 - 0317DE4C10FF952400C5C2D4 - 0317DE4D10FF952400C5C2D4 + 03F246DA1236DED70017F214 + 03F246DB1236DED70017F214 + 03F246DC1236DED70017F214 + 03F246DD1236DED70017F214 0328F4B210B05E8E0074A5A1 ToolbarConfigUserDefaultsMinorVersion @@ -667,7 +671,7 @@ StatusbarIsVisible TimeStamp - 285340271.94513398 + 305591714.41195601 ToolbarConfigUserDefaultsMinorVersion 2 ToolbarDisplayMode @@ -684,10 +688,12 @@ 5 WindowOrderList + 03F246DE1236DED70017F214 + 03F246E01236DED70017F214 /Users/nst/Projects/SpyPhone/SpyPhone.xcodeproj WindowString - 0 59 1440 819 0 0 1440 878 + 0 106 1440 772 0 0 1440 878 WindowToolsV3 @@ -1060,7 +1066,7 @@ TableOfContents 1C530D5B069F1CE1000CFCEE - 036497BC10B3068400C88803 + 032E9C6E1236DB7000B08386 1C78EAAC065D492600B07095 ToolbarConfiguration diff --git a/SpyPhone.xcodeproj/project.pbxproj b/SpyPhone.xcodeproj/project.pbxproj index 8ccfa23..b4116f5 100644 --- a/SpyPhone.xcodeproj/project.pbxproj +++ b/SpyPhone.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -69,6 +69,11 @@ 03B6EFCA10BB547600CF9139 /* gpl-2.0.txt in Resources */ = {isa = PBXBuildFile; fileRef = 03B6EFC910BB547600CF9139 /* gpl-2.0.txt */; }; 03B6F00410BB588A00CF9139 /* white_hat_mask.png in Resources */ = {isa = PBXBuildFile; fileRef = 03B6F00310BB588A00CF9139 /* white_hat_mask.png */; }; 03B6F03510BB5F4800CF9139 /* email_mask.png in Resources */ = {isa = PBXBuildFile; fileRef = 03B6F03410BB5F4800CF9139 /* email_mask.png */; }; + 03F247141236E1440017F214 /* FMDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 03F2470F1236E1440017F214 /* FMDatabase.m */; }; + 03F247151236E1440017F214 /* FMDatabaseAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 03F247111236E1440017F214 /* FMDatabaseAdditions.m */; }; + 03F247161236E1440017F214 /* FMResultSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 03F247131236E1440017F214 /* FMResultSet.m */; }; + 03F2472F1236E25E0017F214 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 03F2472E1236E25E0017F214 /* libsqlite3.dylib */; }; + 03F2481F1236EFAC0017F214 /* NSNumber+SP.m in Sources */ = {isa = PBXBuildFile; fileRef = 03F2481E1236EFAC0017F214 /* NSNumber+SP.m */; }; 1D3623260D0F684500981E51 /* SpyPhoneAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* SpyPhoneAppDelegate.m */; }; 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; @@ -178,6 +183,15 @@ 03B6EFC910BB547600CF9139 /* gpl-2.0.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "gpl-2.0.txt"; sourceTree = ""; }; 03B6F00310BB588A00CF9139 /* white_hat_mask.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = white_hat_mask.png; sourceTree = ""; }; 03B6F03410BB5F4800CF9139 /* email_mask.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = email_mask.png; sourceTree = ""; }; + 03F2470E1236E1440017F214 /* FMDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabase.h; sourceTree = ""; }; + 03F2470F1236E1440017F214 /* FMDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabase.m; sourceTree = ""; }; + 03F247101236E1440017F214 /* FMDatabaseAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabaseAdditions.h; sourceTree = ""; }; + 03F247111236E1440017F214 /* FMDatabaseAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseAdditions.m; sourceTree = ""; }; + 03F247121236E1440017F214 /* FMResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMResultSet.h; sourceTree = ""; }; + 03F247131236E1440017F214 /* FMResultSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMResultSet.m; sourceTree = ""; }; + 03F2472E1236E25E0017F214 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = /usr/lib/libsqlite3.dylib; sourceTree = ""; }; + 03F2481D1236EFAC0017F214 /* NSNumber+SP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNumber+SP.h"; sourceTree = ""; }; + 03F2481E1236EFAC0017F214 /* NSNumber+SP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNumber+SP.m"; sourceTree = ""; }; 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 1D3623240D0F684500981E51 /* SpyPhoneAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpyPhoneAppDelegate.h; sourceTree = ""; }; 1D3623250D0F684500981E51 /* SpyPhoneAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpyPhoneAppDelegate.m; sourceTree = ""; }; @@ -206,6 +220,7 @@ 032A7D9010B844EF00E7FB65 /* CoreLocation.framework in Frameworks */, 032A81CA10B8EB6100E7FB65 /* MessageUI.framework in Frameworks */, 0317DE6910FF95CC00C5C2D4 /* MediaPlayer.framework in Frameworks */, + 03F2472F1236E25E0017F214 /* libsqlite3.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -303,9 +318,23 @@ name = SPSourcesIcons; sourceTree = ""; }; + 03F2470B1236E1180017F214 /* FMDB */ = { + isa = PBXGroup; + children = ( + 03F2470E1236E1440017F214 /* FMDatabase.h */, + 03F2470F1236E1440017F214 /* FMDatabase.m */, + 03F247101236E1440017F214 /* FMDatabaseAdditions.h */, + 03F247111236E1440017F214 /* FMDatabaseAdditions.m */, + 03F247121236E1440017F214 /* FMResultSet.h */, + 03F247131236E1440017F214 /* FMResultSet.m */, + ); + name = FMDB; + sourceTree = ""; + }; 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( + 03F2470B1236E1180017F214 /* FMDB */, 032A7B9010B829D100E7FB65 /* EXIF */, 031748C110B6E67C00B6116E /* SPEmailAccounts */, 031748C210B6E68E00B6116E /* SPSources */, @@ -327,6 +356,8 @@ 032A7ECA10B8617C00E7FB65 /* SPImageAnnotation.m */, 032A819510B8E7C600E7FB65 /* SPEmailReportVC.h */, 032A819610B8E7C600E7FB65 /* SPEmailReportVC.m */, + 03F2481D1236EFAC0017F214 /* NSNumber+SP.h */, + 03F2481E1236EFAC0017F214 /* NSNumber+SP.m */, ); path = Classes; sourceTree = ""; @@ -390,6 +421,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + 03F2472E1236E25E0017F214 /* libsqlite3.dylib */, 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 1D30AB110D05D00D00671497 /* Foundation.framework */, 288765070DF74369002DB57D /* CoreGraphics.framework */, @@ -428,7 +460,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SpyPhone" */; - compatibilityVersion = "Xcode 3.1"; + compatibilityVersion = "Xcode 3.2"; hasScannedForEncodings = 1; mainGroup = 29B97314FDCFA39411CA2CEA /* MyData */; projectDirPath = ""; @@ -516,6 +548,10 @@ 0310C65510C4BE0800E7ACD2 /* SPImageVC.m in Sources */, 037D3A8110F3D57B003A85B0 /* SPEmailMobileMeAccount.m in Sources */, 0317DE5210FF954800C5C2D4 /* UIApplication_TVOut.m in Sources */, + 03F247141236E1440017F214 /* FMDatabase.m in Sources */, + 03F247151236E1440017F214 /* FMDatabaseAdditions.m in Sources */, + 03F247161236E1440017F214 /* FMResultSet.m in Sources */, + 03F2481F1236EFAC0017F214 /* NSNumber+SP.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -565,7 +601,8 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; - SDKROOT = iphoneos3.0; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + SDKROOT = iphoneos3.2; }; name = Debug; }; @@ -573,12 +610,13 @@ isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Nicolas Seriot (9V2U949PMC)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; - SDKROOT = iphoneos3.0; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = "32101231-1E4B-460A-8AF0-A5BD41F1D898"; + SDKROOT = iphoneos3.2; }; name = Release; };