├── Email.png ├── Icon.png ├── Phone.png ├── Wifi.png ├── data.png ├── Default.png ├── Photos.png ├── Safari.png ├── YouTube.png ├── report.png ├── Keyboard.png ├── Location.png ├── email_mask.png ├── white_hat.png ├── AddressBook.png ├── white_hat_mask.png ├── Settings.bundle ├── en.lproj │ └── Root.strings └── Root.plist ├── SpyPhone_Prefix.pch ├── SpyPhone.xcodeproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── nst.xcuserdatad │ └── WorkspaceSettings.xcsettings ├── Classes ├── SPCell.m ├── NSNumber+SP.h ├── SPCell.h ├── SPEmailASAccount.h ├── SPEmailPOPAccount.h ├── SPEmailGmailAccount.h ├── SPEmailIMAPAccount.h ├── SPEmailIToolsAccount.h ├── SPEmailMobileMeAccount.h ├── SPSourceKeyboardTVC.h ├── SPSourceAddressBookTVC.h ├── UIImage+GPS.h ├── SPImageVC.h ├── SPSourceEmailTVC.h ├── SPWebViewVC.h ├── SPWifiMapVC.h ├── SpyPhoneAppDelegate.h ├── SPSourceTVC.h ├── SPEmailReportVC.h ├── SPWifiAnnotation.h ├── SPImageMapVC.h ├── SPSourceWifiTVC.h ├── SPSourcePhotosTVC.h ├── SPEmailPOPAccount.m ├── SPImageAnnotation.h ├── SPEmailIMAPAccount.m ├── SPEmailASAccount.m ├── NSNumber+SP.m ├── SPImageVC.m ├── SPWebViewVC.m ├── SPEmailAccount.h ├── TVOutManager.h ├── SPEmailGmailAccount.m ├── SPEmailIToolsAccount.m ├── SPSourceLocationTVC.h ├── SPAllSourcesTVC.h ├── SPEmailMobileMeAccount.m ├── SpyPhoneAppDelegate.m ├── SPImageAnnotation.m ├── SPSourcePhoneTVC.h ├── SPWifiAnnotation.m ├── SPEmailAccount.m ├── UIImage+GPS.m ├── SPSourceAddressBookTVC.m ├── SPSourceEmailTVC.m ├── SPWifiMapVC.m ├── SPSourceTVC.m ├── SPEmailReportVC.m ├── SPSourceWifiTVC.m ├── SPAllSourcesTVC.m ├── SPImageMapVC.m ├── SPSourceKeyboardTVC.m ├── SPSourceLocationTVC.m ├── SPSourcePhotosTVC.m ├── SPSourcePhoneTVC.m ├── TVOutManager_.m └── TVOutManager.m ├── EXIF ├── EXFLogging.h ├── EXFTagDefinitionHolder.h ├── EXF.h ├── EXFJFIF.h ├── EXFUtils.h ├── EXFJpeg.h ├── EXFGPS.h ├── EXFMutableMetaData.h ├── EXFHandlers.h ├── EXFGPS.m ├── EXFMetaData.h ├── EXFJFIF.m ├── EXFUtils.m └── EXFConstants.h ├── main.m ├── OUILookupTool ├── OUILookupTool.h └── OUILookupTool.m ├── README.markdown ├── JSON ├── Readme.markdown ├── LICENSE ├── NSString+SBJSON.m ├── NSObject+SBJSON.m ├── NSString+SBJSON.h ├── NSObject+SBJSON.h ├── SBProxyForJson.h ├── SBJsonBase.m ├── JSON.h ├── SBJsonBase.h ├── SBJsonParser.h ├── SBJsonWriter.m ├── SBJsonWriter.h └── SBJsonStreamWriter.h ├── FMDB ├── FMDatabaseAdditions.h ├── FMResultSet.h ├── FMDatabase.h ├── FMDatabaseAdditions.m └── FMResultSet.m └── SpyPhone-Info.plist /Email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/Email.png -------------------------------------------------------------------------------- /Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/Icon.png -------------------------------------------------------------------------------- /Phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/Phone.png -------------------------------------------------------------------------------- /Wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/Wifi.png -------------------------------------------------------------------------------- /data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/data.png -------------------------------------------------------------------------------- /Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/Default.png -------------------------------------------------------------------------------- /Photos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/Photos.png -------------------------------------------------------------------------------- /Safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/Safari.png -------------------------------------------------------------------------------- /YouTube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/YouTube.png -------------------------------------------------------------------------------- /report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/report.png -------------------------------------------------------------------------------- /Keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/Keyboard.png -------------------------------------------------------------------------------- /Location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/Location.png -------------------------------------------------------------------------------- /email_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/email_mask.png -------------------------------------------------------------------------------- /white_hat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/white_hat.png -------------------------------------------------------------------------------- /AddressBook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/AddressBook.png -------------------------------------------------------------------------------- /white_hat_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/white_hat_mask.png -------------------------------------------------------------------------------- /Settings.bundle/en.lproj/Root.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nst/SpyPhone/master/Settings.bundle/en.lproj/Root.strings -------------------------------------------------------------------------------- /SpyPhone_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SpyPhone' target in the 'SpyPhone' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /SpyPhone.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Classes/SPCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPCell.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPCell.h" 11 | 12 | 13 | @implementation SPCell 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/NSNumber+SP.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSNumber+SL.h 3 | // SpotLook 4 | // 5 | // Created by Nicolas Seriot on 31.03.08. 6 | // Copyright 2008 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface NSNumber (SP) 13 | 14 | - (NSString *)prettyBytes; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/SPCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPCell.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | 12 | 13 | @interface SPCell : UITableViewCell { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/SPEmailASAccount.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailASAccount.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailAccount.h" 11 | 12 | @interface SPEmailASAccount : SPEmailAccount { 13 | 14 | } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/SPEmailPOPAccount.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPEMailPOPAccount.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailAccount.h" 11 | 12 | @interface SPEmailPOPAccount : SPEmailAccount { 13 | 14 | } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/SPEmailGmailAccount.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailGmailAccount.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailAccount.h" 11 | 12 | 13 | @interface SPEmailGmailAccount : SPEmailAccount { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/SPEmailIMAPAccount.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailIMAPAccount.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailAccount.h" 11 | 12 | 13 | @interface SPEmailIMAPAccount : SPEmailAccount { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/SPEmailIToolsAccount.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailIToolsAccount.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailAccount.h" 11 | 12 | @interface SPEmailIToolsAccount : SPEmailAccount { 13 | 14 | } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/SPEmailMobileMeAccount.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailMobileMeAccount.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailAccount.h" 11 | 12 | 13 | @interface SPEmailMobileMeAccount : SPEmailAccount { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/SPSourceKeyboardTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceKeyboardTVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/16/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import "SPSourceTVC.h" 12 | 13 | @interface SPSourceKeyboardTVC : SPSourceTVC { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/SPSourceAddressBookTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceAddressBookTVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/16/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import "SPSourceTVC.h" 12 | 13 | @interface SPSourceAddressBookTVC : SPSourceTVC { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /EXIF/EXFLogging.h: -------------------------------------------------------------------------------- 1 | /* 2 | * logging.h 3 | * 4 | * 5 | * Created by steve woodcock on 28/02/2008. 6 | * Copyright 2008. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | * 9 | */ 10 | 11 | // Logging.h 12 | //extern BOOL gLogging; 13 | #define Debug(FMT,...) /*NSLog(@"DEBUG: " FMT, ##__VA_ARGS__)*/ 14 | #define Warn(FMT,...) /*NSLog(@"WARNING: " FMT, ##__VA_ARGS__)*/ -------------------------------------------------------------------------------- /Classes/UIImage+GPS.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+GPS.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/21/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import 12 | 13 | @interface UIImage (GPS) 14 | 15 | +(CLLocationCoordinate2D)coordinatesOfImageAtPath:(NSString *)path; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/SPImageVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPImageVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/21/09. 6 | // Copyright 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface SPImageVC : UIViewController { 13 | NSString *path; 14 | IBOutlet UIImageView *imageView; 15 | } 16 | 17 | @property (nonatomic, retain) UIImageView *imageView; 18 | @property (nonatomic, retain) NSString *path; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | 12 | int main(int argc, char *argv[]) { 13 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | [pool release]; 16 | return retVal; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /Classes/SPSourceEmailTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceEmailTVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import "SPSourceTVC.h" 12 | 13 | @interface SPSourceEmailTVC : SPSourceTVC { 14 | NSMutableArray *emails; 15 | } 16 | 17 | @property (nonatomic, retain) NSMutableArray *emails; 18 | 19 | - (NSString *)emailForReport; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SpyPhone.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Classes/SPWebViewVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPWebViewVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | 12 | 13 | @interface SPWebViewVC : UIViewController { 14 | NSURLRequest *request; 15 | IBOutlet UIWebView *webView; 16 | } 17 | 18 | @property (nonatomic, retain) NSURLRequest *request; 19 | @property (nonatomic, retain) UIWebView *webView; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Classes/SPWifiMapVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPWifiMapVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 10/31/10. 6 | // Copyright 2010 IICT. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SPWifiMapVC : UIViewController { 13 | NSArray *annotations; 14 | 15 | IBOutlet MKMapView *mapView; 16 | } 17 | 18 | @property (nonatomic, retain) NSArray *annotations; 19 | 20 | - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /EXIF/EXFTagDefinitionHolder.h: -------------------------------------------------------------------------------- 1 | // 2 | // EXFTagDefinition.h 3 | // iphone-test 4 | // 5 | // Created by steve woodcock on 26/03/2008. 6 | // Copyright 2008 __MyCompanyName__. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "EXFConstants.h" 11 | 12 | @interface EXFTagDefinitionHolder :NSObject { 13 | 14 | NSMutableDictionary* definitions; 15 | } 16 | 17 | @property (readwrite, retain) NSDictionary* definitions; 18 | 19 | -(void) addTagDefinition: (EXFTag*) aTagDefinition forKey: (NSNumber*) aTagKey; 20 | 21 | @end 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Classes/SpyPhoneAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SpyPhoneAppDelegate.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright IICT 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | 12 | @interface SpyPhoneAppDelegate : NSObject { 13 | UIWindow *window; 14 | UITabBarController *tabBarController; 15 | } 16 | 17 | @property (nonatomic, retain) IBOutlet UIWindow *window; 18 | @property (nonatomic, retain) IBOutlet UITabBarController *tabBarController; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Settings.bundle/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | StringsTable 6 | Root 7 | PreferenceSpecifiers 8 | 9 | 10 | Type 11 | PSToggleSwitchSpecifier 12 | Title 13 | TV OUT 14 | Key 15 | TVOutEnabled 16 | DefaultValue 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Classes/SPSourceTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceTVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/17/09. 6 | // Copyright 2009. All rights reserved. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import "SPWebViewVC.h" 12 | 13 | /* 14 | [{[va, vb], k1}, 15 | {[vc, vd], k2}, 16 | {[ve, vf], k3}] 17 | */ 18 | 19 | @interface SPSourceTVC : UITableViewController { 20 | NSMutableArray *contentsDictionaries; 21 | } 22 | 23 | @property (retain) NSMutableArray *contentsDictionaries; 24 | 25 | - (UIImage *)image; 26 | 27 | - (void)loadData; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Classes/SPEmailReportVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailReportVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/22/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import 12 | #import "SPAllSourcesTVC.h" 13 | 14 | @interface SPEmailReportVC : UIViewController { 15 | IBOutlet UILabel *message; 16 | IBOutlet SPAllSourcesTVC *allSources; 17 | } 18 | 19 | @property (nonatomic, retain) IBOutlet UILabel *message; 20 | @property (nonatomic, retain) IBOutlet SPAllSourcesTVC *allSources; 21 | 22 | - (IBAction)sendReport:(id)sender; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/SPWifiAnnotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPWifiAnnotation.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 10/31/10. 6 | // Copyright 2010 IICT. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol MKAnnotation; 12 | 13 | @interface SPWifiAnnotation : NSObject { 14 | NSDictionary *accessPoint; 15 | CLLocationCoordinate2D coordinate; 16 | } 17 | 18 | @property (nonatomic, retain) NSDictionary *accessPoint; 19 | @property (nonatomic, readwrite) CLLocationCoordinate2D coordinate; 20 | 21 | + (SPWifiAnnotation *)annotationWithAccessPoint:(NSDictionary *)d; 22 | 23 | - (NSString *)annotationViewIdentifier; 24 | 25 | - (NSString *)title; 26 | - (NSString *)subtitle; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Classes/SPImageMapVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPMapVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/21/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import 12 | 13 | @class SPImageVC; 14 | 15 | @interface SPImageMapVC : UIViewController { 16 | NSArray *annotations; 17 | 18 | IBOutlet MKMapView *mapView; 19 | IBOutlet SPImageVC *imageVC; 20 | } 21 | 22 | @property (nonatomic, retain) NSArray *annotations; 23 | 24 | - (void)addAnnotation:(id )annotation; 25 | 26 | - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Classes/SPSourceWifiTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceWifiTVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import "SPSourceTVC.h" 12 | #import "OUILookupTool.h" 13 | 14 | @class SPWifiMapVC; 15 | 16 | @interface SPSourceWifiTVC : SPSourceTVC { 17 | NSMutableArray *annotations; 18 | NSMutableArray *accessPoints; 19 | IBOutlet SPWifiMapVC *mapVC; 20 | } 21 | 22 | @property (nonatomic, retain) NSMutableArray *annotations; 23 | @property (nonatomic, retain) NSMutableArray *accessPoints; 24 | @property (nonatomic, retain) SPWifiMapVC *mapVC; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /OUILookupTool/OUILookupTool.h: -------------------------------------------------------------------------------- 1 | // 2 | // OUILookupTool.h 3 | // OUILookup 4 | // 5 | // Created by Nicolas Seriot on 10/31/10. 6 | // Copyright 2010 IICT. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class OUILookupTool; 12 | 13 | @protocol OUILookupToolDelegate 14 | - (void)OUILookupTool:(OUILookupTool *)ouiLookupTool didLocateAccessPoint:(NSDictionary *)ap; 15 | @end 16 | 17 | @interface OUILookupTool : NSObject { 18 | NSObject *delegate; 19 | } 20 | 21 | @property (nonatomic, retain) NSObject *delegate; 22 | 23 | // ap should have a "bssid" key 24 | + (OUILookupTool *)locateWifiAccessPoint:(NSDictionary *)ap delegate:(NSObject *)aDelegate; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/SPSourcePhotosTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourcePhotosTVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPSourceTVC.h" 11 | 12 | @class SPImageMapVC; 13 | @class SPImageVC; 14 | 15 | @interface SPSourcePhotosTVC : SPSourceTVC { 16 | NSMutableArray *coordinates; 17 | NSMutableArray *annotations; 18 | 19 | IBOutlet SPImageMapVC *mapVC; 20 | IBOutlet SPImageVC *imageVC; 21 | } 22 | 23 | @property (nonatomic, retain) NSMutableArray *annotations; 24 | @property (nonatomic, retain) NSMutableArray *coordinates; 25 | @property (nonatomic, retain) SPImageMapVC *mapVC; 26 | @property (nonatomic, retain) SPImageVC *imageVC; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | At BlackHat DC 2010, I presented a paper called [iPhone Privacy](http://seriot.ch/resources/talks_papers/iPhonePrivacy.pdf). 2 | 3 | In this paper, I call the following Apple claim into question: 4 | 5 | > Applications on the device are "sandboxed" so they cannot access data stored by other applications. 6 | 7 | > In addition, system files, resources, and the kernel are shielded from the user's application space. 8 | 9 | > Source: [iPhone in Business - Security Overview](http://www.apple.com/iphone/business/docs/iPhone_Security.pdf) 10 | 11 | SpyPhone demoes it is not exactly true. It shows the kind of data a rogue application can collect in a non jailbroken iPhone. 12 | 13 | These data do certainly interest marketers, spammers, thieves, competitors and law enforcement officials. 14 | 15 | -------------------------------------------------------------------------------- /Classes/SPEmailPOPAccount.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPEMailPOPAccount.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailPOPAccount.h" 11 | 12 | 13 | @implementation SPEmailPOPAccount 14 | 15 | + (SPEmailAccount *)accountWithDictionary:(NSDictionary *)d { 16 | SPEmailPOPAccount *account = [[SPEmailPOPAccount alloc] init]; 17 | 18 | account.type = [d valueForKey:@"Short Type String"]; 19 | account.fullname = [d valueForKey:@"FullUserName"]; 20 | account.emails = [d valueForKey:@"EmailAddresses"]; 21 | account.hostname = [d valueForKey:@"Hostname"]; 22 | account.username = [d valueForKey:@"Username"]; 23 | account.displayName = [d valueForKey:@"DisplayName"]; 24 | 25 | return [account autorelease]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Classes/SPImageAnnotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPImageAnnotation.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/21/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | 12 | @protocol MKAnnotation; 13 | 14 | @interface SPImageAnnotation : NSObject { 15 | NSString *title; 16 | NSString *path; 17 | CLLocationCoordinate2D coordinate; 18 | } 19 | 20 | @property (nonatomic, retain) NSString *title; 21 | @property (nonatomic, retain) NSString *path; 22 | @property (nonatomic, readwrite) CLLocationCoordinate2D coordinate; 23 | 24 | + (SPImageAnnotation *) annotationWithCoordinate:(CLLocationCoordinate2D)coord date:(NSDate *)date path:(NSString *)path; 25 | 26 | - (NSString *)annotationViewIdentifier; 27 | - (BOOL)hasValidCoordinates; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Classes/SPEmailIMAPAccount.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailIMAPAccount.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailIMAPAccount.h" 11 | 12 | 13 | @implementation SPEmailIMAPAccount 14 | 15 | + (SPEmailAccount *)accountWithDictionary:(NSDictionary *)d { 16 | SPEmailIMAPAccount *account = [[SPEmailIMAPAccount alloc] init]; 17 | 18 | account.type = [d valueForKey:@"Short Type String"]; 19 | account.fullname = [d valueForKey:@"FullUserName"]; 20 | account.emails = [d valueForKey:@"EmailAddresses"]; 21 | account.hostname = [d valueForKey:@"Hostname"]; 22 | account.username = [d valueForKey:@"Username"]; 23 | account.displayName = [d valueForKey:@"DisplayName"]; 24 | 25 | return [account autorelease]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Classes/SPEmailASAccount.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailASAccount.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailASAccount.h" 11 | 12 | 13 | @implementation SPEmailASAccount 14 | 15 | + (SPEmailAccount *)accountWithDictionary:(NSDictionary *)d { 16 | SPEmailASAccount *account = [[SPEmailASAccount alloc] init]; 17 | 18 | account.type = [d valueForKey:@"Short Type String"]; 19 | //account.fullname = nil; 20 | account.emails = [NSArray arrayWithObject:[d valueForKey:@"ASAccountEmailAddress"]]; 21 | account.hostname = [d valueForKey:@"ASAccountHost"]; 22 | account.username = [d valueForKey:@"ASAccountUsername"]; 23 | account.displayName = [d valueForKey:@"DisplayName"]; 24 | 25 | return [account autorelease]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Classes/NSNumber+SP.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSNumber+SL.m 3 | // SpotLook 4 | // 5 | // Created by Nicolas Seriot on 31.03.08. 6 | // Copyright 2008 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "NSNumber+SP.h" 10 | 11 | 12 | @implementation NSNumber (SP) 13 | 14 | - (NSString *)prettyBytes { 15 | float bytes = [self longValue]; 16 | NSUInteger unit = 0; 17 | 18 | if(bytes < 1) { return @"-"; } 19 | 20 | while(bytes > 1024) { 21 | bytes = bytes / 1024.0; 22 | unit++; 23 | } 24 | 25 | if(unit > 4) { return @"HUGE"; } 26 | 27 | NSString *unitString = [[NSArray arrayWithObjects:/* @"Bytes", */ @"KB", @"MB", @"GB", @"TB", @"PB", nil] objectAtIndex:unit]; 28 | 29 | if(unit == 0) { 30 | return [NSString stringWithFormat:@"%d %@", (int)bytes, unitString]; 31 | } else { 32 | return [NSString stringWithFormat:@"%.2f %@", (float)bytes, unitString]; 33 | } 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /JSON/Readme.markdown: -------------------------------------------------------------------------------- 1 | JSON Framework 2 | ============== 3 | 4 | JSON is a light-weight data interchange format that's easy to read and 5 | write for humans and computers alike. This framework implements a strict 6 | JSON parser and generator in Objective-C. 7 | 8 | Features 9 | -------- 10 | 11 | * BSD license. 12 | * Easy-to-use API. 13 | * Strict parsing & generation. 14 | * Stack of error available in case of failure so you can easily figure out what is wrong. 15 | * Optional pretty-printing of JSON output. 16 | * Optionally sorted dictionary keys in JSON output. 17 | * Configurable recursion depth for parsing, for added security. 18 | 19 | Links 20 | ----- 21 | 22 | * The GitHub [project page][src]. 23 | * The online [API documentation][api]. 24 | * The new [website][web]. 25 | 26 | [api]: http://stig.github.com/json-framework/api 27 | [web]: http://stig.github.com/json-framework 28 | [src]: http://github.com/stig/json-framework 29 | -------------------------------------------------------------------------------- /Classes/SPImageVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPImageVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/21/09. 6 | // Copyright 2009. All rights reserved. 7 | // 8 | 9 | #import "SPImageVC.h" 10 | 11 | 12 | @implementation SPImageVC 13 | 14 | @synthesize imageView; 15 | @synthesize path; 16 | 17 | - (void)viewDidAppear:(BOOL)animated { 18 | imageView.image = [UIImage imageWithContentsOfFile:path]; 19 | } 20 | 21 | - (void)viewDidDisappear:(BOOL)animated { 22 | imageView.image = nil; 23 | } 24 | 25 | - (void)didReceiveMemoryWarning { 26 | // Releases the view if it doesn't have a superview. 27 | [super didReceiveMemoryWarning]; 28 | 29 | // Release any cached data, images, etc that aren't in use. 30 | } 31 | 32 | - (void)viewDidUnload { 33 | // Release any retained subviews of the main view. 34 | // e.g. self.myOutlet = nil; 35 | } 36 | 37 | 38 | - (void)dealloc { 39 | [path release]; 40 | [imageView release]; 41 | [super dealloc]; 42 | } 43 | 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Classes/SPWebViewVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPWebViewVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPWebViewVC.h" 11 | 12 | 13 | @implementation SPWebViewVC 14 | 15 | @synthesize webView; 16 | @synthesize request; 17 | 18 | - (void)didReceiveMemoryWarning { 19 | // Releases the view if it doesn't have a superview. 20 | [super didReceiveMemoryWarning]; 21 | 22 | // Release any cached data, images, etc that aren't in use. 23 | } 24 | 25 | - (void)viewDidUnload { 26 | // Release any retained subviews of the main view. 27 | // e.g. self.myOutlet = nil; 28 | } 29 | 30 | - (void)viewDidAppear:(BOOL)animated { 31 | [webView loadRequest:request]; 32 | } 33 | 34 | - (void)viewDidDisappear:(BOOL)animated { 35 | [webView loadRequest:nil]; 36 | } 37 | 38 | - (void)dealloc { 39 | [request release]; 40 | [webView release]; 41 | [super dealloc]; 42 | } 43 | 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Classes/SPEmailAccount.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailAccount.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | 12 | // TODO: subclass for AOL accounts 13 | 14 | @interface SPEmailAccount : NSObject { 15 | NSString *fullname; 16 | NSArray *emails; 17 | NSString *type; 18 | NSString *hostname; 19 | NSString *username; 20 | NSString *displayName; 21 | NSMutableArray *calendars; 22 | } 23 | 24 | @property (nonatomic, retain) NSString *fullname; 25 | @property (nonatomic, retain) NSArray *emails; 26 | @property (nonatomic, retain) NSString *type; 27 | @property (nonatomic, retain) NSString *hostname; 28 | @property (nonatomic, retain) NSString *username; 29 | @property (nonatomic, retain) NSString *displayName; 30 | @property (nonatomic, retain) NSArray *calendars; 31 | 32 | + (SPEmailAccount *)accountWithDictionary:(NSDictionary *)d; 33 | - (NSArray *)infoArray; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Classes/TVOutManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // TVOutManager.h 3 | // TVOutOS4Test 4 | // 5 | // Created by Rob Terrell (rob@touchcentric.com) on 8/16/10. 6 | // Copyright 2010 TouchCentric LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface TVOutManager : NSObject { 13 | 14 | UIWindow* deviceWindow; 15 | UIWindow* tvoutWindow; 16 | NSTimer *updateTimer; 17 | UIImage *image; 18 | UIImageView *mirrorView; 19 | BOOL done; 20 | BOOL tvSafeMode; 21 | CGAffineTransform startingTransform; 22 | } 23 | 24 | @property(assign) BOOL tvSafeMode; 25 | 26 | 27 | + (TVOutManager *)sharedInstance; 28 | 29 | - (void) startTVOut; 30 | - (void) stopTVOut; 31 | - (void) updateTVOut; 32 | - (void) updateLoop; 33 | - (void) screenDidConnectNotification: (NSNotification*) notification; 34 | - (void) screenDidDisconnectNotification: (NSNotification*) notification; 35 | - (void) screenModeDidChangeNotification: (NSNotification*) notification; 36 | - (void) deviceOrientationDidChange: (NSNotification*) notification; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Classes/SPEmailGmailAccount.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailGmailAccount.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailGmailAccount.h" 11 | 12 | 13 | @implementation SPEmailGmailAccount 14 | 15 | + (SPEmailAccount *)accountWithDictionary:(NSDictionary *)d { 16 | SPEmailGmailAccount *account = [[SPEmailGmailAccount alloc] init]; 17 | 18 | account.type = [d valueForKey:@"Short Type String"]; 19 | account.fullname = [d valueForKey:@"FullUserName"]; 20 | account.hostname = [d valueForKey:@"Hostname"]; 21 | account.username = [d valueForKey:@"Username"]; 22 | account.displayName = [d valueForKey:@"DisplayName"]; 23 | 24 | NSString *theEmail = [d valueForKey:@"Username"]; 25 | if(![[theEmail lowercaseString] hasSuffix:@"@gmail.com"]) { 26 | theEmail = [theEmail stringByAppendingString:@"@gmail.com"]; 27 | } 28 | account.emails = [NSArray arrayWithObject:theEmail]; 29 | 30 | return [account autorelease]; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /FMDB/FMDatabaseAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.h 3 | // fmkit 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import 10 | @interface FMDatabase (FMDatabaseAdditions) 11 | 12 | 13 | - (int)intForQuery:(NSString*)objs, ...; 14 | - (long)longForQuery:(NSString*)objs, ...; 15 | - (BOOL)boolForQuery:(NSString*)objs, ...; 16 | - (double)doubleForQuery:(NSString*)objs, ...; 17 | - (NSString*)stringForQuery:(NSString*)objs, ...; 18 | - (NSData*)dataForQuery:(NSString*)objs, ...; 19 | - (NSDate*)dateForQuery:(NSString*)objs, ...; 20 | 21 | // Notice that there's no dataNoCopyForQuery:. 22 | // That would be a bad idea, because we close out the result set, and then what 23 | // happens to the data that we just didn't copy? Who knows, not I. 24 | 25 | 26 | - (BOOL)tableExists:(NSString*)tableName; 27 | - (FMResultSet*)getSchema; 28 | - (FMResultSet*)getTableSchema:(NSString*)tableName; 29 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Classes/SPEmailIToolsAccount.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailIToolsAccount.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailIToolsAccount.h" 11 | 12 | 13 | @implementation SPEmailIToolsAccount 14 | 15 | + (SPEmailAccount *)accountWithDictionary:(NSDictionary *)d { 16 | SPEmailIToolsAccount *account = [[SPEmailIToolsAccount alloc] init]; 17 | 18 | account.type = [d valueForKey:@"Short Type String"]; 19 | account.fullname = [d valueForKey:@"FullUserName"]; 20 | NSArray *theEmailAddresses = [d valueForKey:@"EmailAddresses"]; 21 | NSMutableArray *theEmails = [NSMutableArray array]; 22 | for (id emailAddress in theEmailAddresses) { 23 | [theEmails addObject:[NSString stringWithFormat:@"%@@me.com", emailAddress]]; 24 | } 25 | account.emails = theEmails; 26 | //account.hostname = nil; 27 | account.username = [d valueForKey:@"Username"]; 28 | account.displayName = [d valueForKey:@"DisplayName"]; 29 | 30 | return [account autorelease]; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Classes/SPSourceLocationTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceLocationTVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import 12 | #import "SPSourceTVC.h" 13 | 14 | @class CLLocation; 15 | 16 | @interface SPSourceLocationTVC : SPSourceTVC /* */ { 17 | NSArray *items; 18 | // MKReverseGeocoder *geo; 19 | NSString *geoString; 20 | 21 | NSString *locString; 22 | NSString *locDateString; 23 | NSString *timezone; 24 | NSArray *cities; 25 | 26 | CLLocation *cachedLocationFromMaps; 27 | } 28 | 29 | //@property (nonatomic, retain) MKReverseGeocoder *geo; 30 | @property (nonatomic, retain) NSString *geoString; 31 | @property (nonatomic, retain) CLLocation *cachedLocationFromMaps; 32 | @property (nonatomic, retain) NSArray *cities; 33 | @property (nonatomic, retain) NSString *locString; 34 | @property (nonatomic, retain) NSString *locDateString; 35 | @property (nonatomic, retain) NSString *timezone; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Classes/SPAllSourcesTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SourcesTVController.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | 12 | @class SPSourceEmailTVC; 13 | @class SPSourceWifiTVC; 14 | @class SPSourcePhoneTVC; 15 | @class SPSourceLocationTVC; 16 | @class SPSourcePhotosTVC; 17 | @class SPSourceAddressBookTVC; 18 | @class SPSourceKeyboardTVC; 19 | 20 | @interface SPAllSourcesTVC : UITableViewController { 21 | NSArray *sources; 22 | 23 | IBOutlet SPSourceEmailTVC *sourceEmailTVC; 24 | IBOutlet SPSourceWifiTVC *sourceWifiTVC; 25 | IBOutlet SPSourcePhoneTVC *sourcePhoneTVC; 26 | IBOutlet SPSourceLocationTVC *sourceLocationTVC; 27 | IBOutlet SPSourcePhotosTVC *sourcePhotosTVC; 28 | IBOutlet SPSourceAddressBookTVC *sourceAddressBookTVC; 29 | IBOutlet SPSourceKeyboardTVC *sourceKeyboardTVC; 30 | } 31 | 32 | @property (nonatomic, retain) NSArray *sources; 33 | 34 | - (NSString *)emailForReport; 35 | - (NSString *)report; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /SpyPhone-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | ch.seriot.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSMainNibFile 28 | MainWindow 29 | CFBundleShortVersionString 30 | 31 | UIPrerenderedIcon 32 | YES 33 | 34 | 35 | -------------------------------------------------------------------------------- /Classes/SPEmailMobileMeAccount.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailMobileMeAccount.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailMobileMeAccount.h" 11 | 12 | 13 | @implementation SPEmailMobileMeAccount 14 | 15 | + (SPEmailAccount *)accountWithDictionary:(NSDictionary *)d { 16 | SPEmailMobileMeAccount *account = [[SPEmailMobileMeAccount alloc] init]; 17 | 18 | account.type = [d valueForKey:@"Short Type String"]; 19 | account.fullname = [d valueForKey:@"FullUserName"]; 20 | account.emails = [d valueForKey:@"EmailAddresses"]; 21 | account.username = [d valueForKey:@"Username"]; 22 | account.displayName = [d valueForKey:@"DisplayName"]; 23 | 24 | NSMutableArray *theCalendars = [NSMutableArray array]; 25 | NSDictionary *calendars = [d valueForKey:@"Subscribed Calendars"]; 26 | if (calendars) { 27 | for(id calendarItem in [calendars allValues]) { 28 | [theCalendars addObject:[calendarItem valueForKey:@"com.apple.ical.urlsubscribe.url"]]; 29 | } 30 | 31 | account.calendars = theCalendars; 32 | } 33 | return [account autorelease]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Classes/SpyPhoneAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SpyPhoneAppDelegate.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright IICT 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SpyPhoneAppDelegate.h" 11 | #import "TVOutManager.h" 12 | 13 | @implementation SpyPhoneAppDelegate 14 | 15 | @synthesize window; 16 | @synthesize tabBarController; 17 | 18 | - (void)dealloc { 19 | [tabBarController release]; 20 | [window release]; 21 | [super dealloc]; 22 | } 23 | 24 | - (void)applicationDidFinishLaunching:(UIApplication *)application { 25 | 26 | // Add the tab bar controller's current view as a subview of the window 27 | [window addSubview:tabBarController.view]; 28 | 29 | /* 30 | // FIXME: TVOut does not work so well 31 | 32 | 1. start SP, suspend 33 | 2. plug 34 | 3. start SP, suspend 35 | 4. start SP, SP quits 36 | 5. start SP 37 | */ 38 | 39 | BOOL isTVOutEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"TVOutEnabled"]; 40 | if(isTVOutEnabled) { 41 | [TVOutManager sharedInstance].tvSafeMode = NO; 42 | [[TVOutManager sharedInstance] startTVOut]; 43 | } 44 | } 45 | 46 | @end 47 | 48 | -------------------------------------------------------------------------------- /Classes/SPImageAnnotation.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPImageAnnotation.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/21/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPImageAnnotation.h" 11 | 12 | 13 | @implementation SPImageAnnotation 14 | 15 | @synthesize title; 16 | @synthesize path; 17 | @synthesize coordinate; 18 | 19 | - (BOOL)hasValidCoordinates { 20 | return coordinate.longitude != 0.0 && coordinate.latitude != 0.0; 21 | } 22 | 23 | + (SPImageAnnotation *)annotationWithCoordinate:(CLLocationCoordinate2D)coord date:(NSDate *)date path:(NSString *)path { 24 | 25 | SPImageAnnotation *annotation = [[SPImageAnnotation alloc] init]; 26 | annotation.coordinate = coord; 27 | annotation.path = path; 28 | 29 | NSDateFormatter *df = [[NSDateFormatter alloc] init]; 30 | [df setDateFormat:@"yyyy-MM-dd HH:mm"]; 31 | annotation.title = [df stringFromDate:date]; 32 | [df release]; 33 | 34 | return [annotation autorelease]; 35 | } 36 | 37 | - (void)dealloc { 38 | [path release]; 39 | [title release]; 40 | [super dealloc]; 41 | } 42 | 43 | - (NSString *)annotationViewIdentifier { 44 | return title; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /EXIF/EXF.h: -------------------------------------------------------------------------------- 1 | /* 2 | * EXF.h 3 | * 4 | * 5 | * Created by steve woodcock on 23/03/2008. 6 | * Copyright 2008. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | * 9 | */ 10 | 11 | /*! 12 | @header EXF.h 13 | @abstract The group of the entire EXIF API headers 14 | @discussion These are: 15 | 1) EXFConstants.h 16 | 2) EXFMetaData.h 17 | 3) EXFJFIF.h 18 | 4) EXFJpeg.h 19 | 5) EXFGPS.h 20 | 6) EXFHandlers.h 21 | 22 | To use the framework just use the follwoign import statement 23 | #import "EXF.h" 24 | */ 25 | 26 | /* 27 | Details the Constants for the tag Ids, enums etc 28 | */ 29 | #import "EXFConstants.h" 30 | 31 | 32 | /* 33 | Details the EXFObject which represents the meta information of the JPEG image. 34 | */ 35 | #import "EXFMetaData.h" 36 | 37 | /* 38 | The JFIF is an alternative meta format used to encode information. 39 | */ 40 | #import "EXFJFIF.h" 41 | 42 | /* 43 | The entry point which is used to scan an existing file and reconstruct a new image 44 | */ 45 | #import "EXFJpeg.h" 46 | 47 | /* 48 | A GPS Location object 49 | */ 50 | #import "EXFGPS.h" 51 | 52 | /* 53 | The tag specific handlers which represent special processing required for some tags. 54 | */ 55 | #import "EXFHandlers.h" 56 | 57 | -------------------------------------------------------------------------------- /EXIF/EXFJFIF.h: -------------------------------------------------------------------------------- 1 | // 2 | // EXFJFIF.h 3 | // iphone-test 4 | // 5 | // Created by steve woodcock on 24/03/2008. 6 | // Copyright 2008 __MyCompanyName__. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | 11 | #define EXIF_JPEGCoding 0x10 12 | #define EXIF_1ByteCoding 0x11 13 | #define EXIF_3ByteCoding 0x13 14 | 15 | enum JFIFUnits { 16 | JFIF_NONE =0, 17 | JFIF_DPI = 1, 18 | JFIF_DPC = 2 19 | }; 20 | typedef enum JFIFUnits JFIFUnits; 21 | 22 | @interface EXFJFIF : NSObject { 23 | 24 | NSString* identifier; 25 | int length; 26 | int resolutionX; 27 | int resolutionY; 28 | int thumbnailX; 29 | int thumbnailY; 30 | NSData* thumbnail; 31 | NSString* version; 32 | JFIFUnits units; 33 | } 34 | 35 | @property (readonly, retain) NSString* identifier; 36 | @property (readonly, retain) NSString* version; 37 | 38 | @property (readonly) int length; 39 | @property (readonly) int resolutionX; 40 | @property (readonly) int resolutionY; 41 | 42 | @property (readonly) int thumbnailX; 43 | @property (readonly) int thumbnailY; 44 | @property (readonly,retain) NSData* thumbnail; 45 | @property (readonly) JFIFUnits units; 46 | 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Classes/SPSourcePhoneTVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourcePhoneTVC.h 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import "SPSourceTVC.h" 12 | 13 | @interface SPSourcePhoneTVC : SPSourceTVC { 14 | NSString *ICCID; 15 | // NSString *IMEI; 16 | NSString *IMSI; 17 | NSString *phone; 18 | NSString *UUID; 19 | NSString *lastDialed; 20 | NSString *lastContact; 21 | NSString *lastForwardNumber; 22 | NSMutableArray *callHistories; 23 | NSString *prettyBytesSent; 24 | NSString *prettyBytesReceived; 25 | } 26 | 27 | @property (nonatomic, retain) NSString *ICCID; 28 | //@property (nonatomic, retain) NSString *IMEI; 29 | @property (nonatomic, retain) NSString *IMSI; 30 | @property (nonatomic, retain) NSString *phone; 31 | @property (nonatomic, retain) NSString *UUID; 32 | @property (nonatomic, retain) NSString *lastDialed; 33 | @property (nonatomic, retain) NSString *lastContact; 34 | @property (nonatomic, retain) NSString *lastForwardNumber; 35 | @property (nonatomic, retain) NSString *prettyBytesSent; 36 | @property (nonatomic, retain) NSString *prettyBytesReceived; 37 | @property (nonatomic, retain) NSMutableArray *callHistories; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Classes/SPWifiAnnotation.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPWifiAnnotation.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 10/31/10. 6 | // Copyright 2010 IICT. All rights reserved. 7 | // 8 | 9 | #import "SPWifiAnnotation.h" 10 | 11 | 12 | @implementation SPWifiAnnotation 13 | 14 | @synthesize coordinate; 15 | @synthesize accessPoint; 16 | 17 | - (NSString *)title { 18 | return [accessPoint valueForKey:@"SSID_STR"]; 19 | } 20 | 21 | - (NSString *)subtitle { 22 | NSDate *joined = [accessPoint valueForKey:@"lastJoined"]; 23 | NSDate *autoJoined = [accessPoint valueForKey:@"lastAutoJoined"]; 24 | 25 | NSDate *date = autoJoined ? autoJoined : joined; 26 | 27 | return [date description]; 28 | } 29 | 30 | + (SPWifiAnnotation *)annotationWithAccessPoint:(NSDictionary *)ap { 31 | NSString *latitude = [ap valueForKeyPath:@"location.latitude"]; 32 | NSString *longitude = [ap valueForKeyPath:@"location.longitude"]; 33 | 34 | if(latitude == nil || longitude == nil) return nil; 35 | 36 | SPWifiAnnotation *annotation = [[SPWifiAnnotation alloc] init]; 37 | annotation.accessPoint = ap; 38 | annotation.coordinate = CLLocationCoordinate2DMake([latitude doubleValue], [longitude doubleValue]);; 39 | return [annotation autorelease]; 40 | } 41 | 42 | - (void)dealloc { 43 | [accessPoint release]; 44 | [super dealloc]; 45 | } 46 | 47 | - (NSString *)annotationViewIdentifier { 48 | return [accessPoint valueForKey:@"BSSID"]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Classes/SPEmailAccount.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailAccount.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/20/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailAccount.h" 11 | 12 | 13 | @implementation SPEmailAccount 14 | 15 | @synthesize fullname; 16 | @synthesize emails; 17 | @synthesize type; 18 | @synthesize hostname; 19 | @synthesize username; 20 | @synthesize displayName; 21 | @synthesize calendars; 22 | 23 | - (void)dealloc { 24 | [fullname release]; 25 | [emails release]; 26 | [type release]; 27 | [hostname release]; 28 | [username release]; 29 | [displayName release]; 30 | [super dealloc]; 31 | } 32 | 33 | + (SPEmailAccount *)accountWithDictionary:(NSDictionary *)d { 34 | return nil; // for subclasses 35 | } 36 | 37 | - (NSArray *)infoArray { 38 | NSMutableArray *a = [NSMutableArray array]; 39 | 40 | if(fullname) [a addObject:[NSString stringWithFormat:@"Name: %@", fullname]]; 41 | if(type) [a addObject:[NSString stringWithFormat:@"Type: %@", type]]; 42 | if(hostname) [a addObject:[NSString stringWithFormat:@"Host: %@", hostname]]; 43 | if(username) [a addObject:[NSString stringWithFormat:@"User: %@", username]]; 44 | if(emails) { 45 | for (id emailAddress in emails) 46 | [a addObject:[NSString stringWithFormat:@"Email: %@", emailAddress]]; 47 | } 48 | if (calendars) { 49 | for (id calendar in calendars) 50 | [a addObject:[NSString stringWithFormat:@"Calendar URL: %@", calendar]]; 51 | } 52 | 53 | return a; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /JSON/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2007-2010 Stig Brautaset. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright notice, 9 | this list of conditions and the following disclaimer in the documentation 10 | and/or other materials provided with the distribution. 11 | * Neither the name of the author nor the names of its contributors may be used 12 | to endorse or promote products derived from this software without specific 13 | prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /EXIF/EXFUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * EXFUtils.h 3 | * iphoneGeo 4 | * 5 | * Created by steve woodcock on 23/03/2008. 6 | * Copyright 2008. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | * 9 | * Static helper methods to deal with byte array read/write and big endian/little endian ordering 10 | */ 11 | 12 | #import "EXFConstants.h" 13 | 14 | 15 | @interface EXFUtils : NSObject { 16 | 17 | } 18 | 19 | +(UInt32) read4Bytes:(UInt8**) bytePtr: (BOOL) bigEndianOrder; 20 | +(SInt32) read4SignedBytes:(UInt8**) bytePtr: (BOOL) bigEndianOrder; 21 | +(UInt16) read2Bytes:(UInt8**) bytePtr: (BOOL) bigEndianOrder; 22 | +(SInt16) read2SignedBytes:(UInt8**) bytePtr: (BOOL) bigEndianOrder; 23 | 24 | +(void) write1Byte:(UInt8**) bytePtr: (id) value:(BOOL) bigEndianOrder; 25 | +(void) write1SignedByte:(UInt8**) bytePtr: (id) value:(BOOL) bigEndianOrder; 26 | +(void) write4Bytes:(UInt8**) bytePtr: (id) value: (BOOL) bigEndianOrder; 27 | +(void) write4SignedBytes:(UInt8**) bytePtr: (id) value: (BOOL) bigEndianOrder; 28 | +(void) write2Bytes:(UInt8**) bytePtr: (id) value:(BOOL) bigEndianOrder; 29 | +(void) write2SignedBytes:(UInt8**) bytePtr: (id) value: (BOOL) bigEndianOrder; 30 | 31 | +(NSString*)newStringFromBuffer:(UInt8**) ptr: (UInt32) byteCount: (NSStringEncoding) encoding; 32 | 33 | 34 | +(void) appendRationalToData:( NSMutableData*) target: (NSNumber*) rational: (BOOL) bigEndianOrder; 35 | +(void) appendFractionToData:( NSMutableData*) target: (EXFraction*) fraction: (BOOL) bigEndianOrder; 36 | 37 | +(void) convertRationalToFraction: (long**) numDenumArray: (NSNumber*) rational; 38 | 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Classes/UIImage+GPS.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+GPS.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/21/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "UIImage+GPS.h" 11 | #import "EXF.h" 12 | 13 | @implementation UIImage (GPS) 14 | 15 | // adapted from http://davidjhinson.wordpress.com/2009/06/05/you-can-have-it-in-any-color-as-long-as-its-black/ 16 | +(CLLocationCoordinate2D)coordinatesOfImageAtPath:(NSString *)path { 17 | CLLocationCoordinate2D coord = {0.0, 0.0}; 18 | 19 | NSData *data =[NSData dataWithContentsOfFile:path]; 20 | if(!data) return coord; 21 | 22 | EXFJpeg* jpegScanner = [[EXFJpeg alloc] init]; 23 | [jpegScanner scanImageData:data]; 24 | EXFGPSLoc *lat = [jpegScanner.exifMetaData tagValue:[NSNumber numberWithInt:EXIF_GPSLatitude]]; 25 | NSString *latRef = [jpegScanner.exifMetaData tagValue:[NSNumber numberWithInt:EXIF_GPSLatitudeRef]]; 26 | EXFGPSLoc *lon = [jpegScanner.exifMetaData tagValue:[NSNumber numberWithInt:EXIF_GPSLongitude]]; 27 | NSString *lonRef = [jpegScanner.exifMetaData tagValue:[NSNumber numberWithInt:EXIF_GPSLongitudeRef]]; 28 | [jpegScanner release]; 29 | 30 | if([latRef length] == 0 || [lonRef length] == 0) return coord; 31 | 32 | coord.latitude = [[NSString stringWithFormat:@"%f", lat.degrees.numerator + ((float)lat.minutes.numerator / (float)lat.minutes.denominator) / 60.0] floatValue]; 33 | coord.longitude = [[NSString stringWithFormat:@"%f", lon.degrees.numerator + ((float)lon.minutes.numerator / (float)lon.minutes.denominator) / 60.0] floatValue]; 34 | 35 | if([[latRef substringToIndex:1] isEqualToString:@"S"]) coord.latitude = -coord.latitude; 36 | if([[lonRef substringToIndex:1] isEqualToString:@"W"]) coord.longitude = -coord.longitude; 37 | 38 | return coord; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /EXIF/EXFJpeg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * EXFJpeg.h 3 | * iphoneGeo 4 | * 5 | * Created by steve woodcock on 30/03/2008. 6 | * Copyright 2008. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | * 9 | * The EXFJpeg object is used to scan the original image in order to extract the JFIF/EXIF data and 10 | * following any changes to the EXIF object will return the bytes representing the new image. 11 | */ 12 | 13 | #import "EXFMetaData.h" 14 | #import "EXFJFIF.h" 15 | #import "EXFJpeg.h" 16 | #import "EXFConstants.h" 17 | 18 | 19 | @interface EXFJpeg : NSObject { 20 | 21 | // stores length of the image in bytes 22 | CFIndex imageLength; 23 | 24 | // pointer to the start of the image byte array 25 | ByteArray* imageStartPtr; 26 | 27 | // pointer to the current parsing point in the byte array 28 | ByteArray* imageBytePtr; 29 | 30 | // A dictionary of the EXIF blocks in the file that have been parsed 31 | NSMutableDictionary* keyedHeaders; 32 | 33 | // The EXF MetaData image attributes 34 | EXFMetaData* exifMetaData; 35 | 36 | // Image attributes outside EXIF in the Components section of the file 37 | int numComponents; 38 | 39 | // The JFIF MetaData image attributes 40 | EXFJFIF* jfif; 41 | 42 | NSData* remainingData; 43 | } 44 | 45 | /* 46 | Returns the EXIF MetaData object. 47 | */ 48 | @property (readonly, retain) EXFMetaData* exifMetaData; 49 | 50 | /* 51 | Returns the JFIF Meta Data of a scanned Image 52 | */ 53 | @property (readonly, retain) EXFJFIF* jfif; 54 | 55 | 56 | /* 57 | Scans the Image Data 58 | */ 59 | -(void) scanImageData:(NSData*) imageData; 60 | 61 | /* 62 | Returns the image byte array for the new image with amended data 63 | */ 64 | -(void) populateImageData: (NSMutableData*) newImageData; 65 | 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /EXIF/EXFGPS.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @header EXFGPS Structures 3 | Created by steve woodcock on 30/03/2008. 4 | @copyright 2008. 5 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 6 | 7 | @discussion A set of fractions that represent the 3 rational numbers that make up the 8 | GPS Location. these are: 9 | Degrees 10 | Minutes 11 | Seconds 12 | 13 | The EXF Specification suggests the location should be displayed as 3 rationals. Although we use fractions 14 | to actually represent any stored number without getting precision errors. 15 | */ 16 | 17 | #import "EXFConstants.h" 18 | 19 | /*! 20 | @class EXFGPSLoc 21 | @abstract A GPS Location 22 | @discussion EXFGPSLoc represents a GPS Location. In order to remian aligned to the EXIF format for GPS data, the actual object is 23 | structured as 3 EXFraction objects, one each for degrees, minutes and seconds. 24 | 25 | 26 | */ 27 | 28 | @interface EXFGPSLoc : NSObject { 29 | EXFraction* degrees; 30 | EXFraction* minutes; 31 | EXFraction* seconds; 32 | } 33 | 34 | 35 | @property (retain) EXFraction* degrees; 36 | @property (retain) EXFraction* minutes; 37 | @property (retain) EXFraction* seconds; 38 | 39 | -(double) descriptionAsDecimal; 40 | 41 | @end 42 | 43 | /*! 44 | @class EXFGPSTimeStamp 45 | @abstract A GPS Timestamp 46 | @discussion EXFGPSTimeStamp represents a GPS Timestamp. In order to remian aligned to the EXIF format for GPS data, the actual object is 47 | structured as 3 EXFraction objects, one each for hours, minutes and seconds. 48 | 49 | 50 | */ 51 | 52 | @interface EXFGPSTimeStamp : NSObject { 53 | EXFraction* hours; 54 | EXFraction* minutes; 55 | EXFraction* seconds; 56 | } 57 | 58 | 59 | @property (retain) EXFraction* hours; 60 | @property (retain) EXFraction* minutes; 61 | @property (retain) EXFraction* seconds; 62 | 63 | @end -------------------------------------------------------------------------------- /EXIF/EXFMutableMetaData.h: -------------------------------------------------------------------------------- 1 | /* 2 | * EXFMutableMetaData.h 3 | * iphoneGeo 4 | * 5 | * Created by steve woodcock on 23/03/2008. 6 | * Copyright 2008 __MyCompanyName__. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | * 9 | */ 10 | #import "EXFMetaData.h" 11 | #import "EXFJFIF.h" 12 | 13 | 14 | /* Mutable interface Category for EXFJFIF */ 15 | 16 | @interface EXFJFIF () 17 | 18 | 19 | - (void) parseJfif:(CFDataRef*) theJfifData; 20 | 21 | @property (readwrite, retain) NSString* identifier; 22 | @property (readwrite, retain) NSString* version; 23 | 24 | @property (readwrite, retain) NSData* thumbnail; 25 | 26 | // primitive attributes 27 | @property (readwrite) JFIFUnits units; 28 | @property (readwrite) int length; 29 | @property (readwrite) int resolutionX; 30 | @property (readwrite) int resolutionY; 31 | 32 | @property (readwrite) int thumbnailX; 33 | @property (readwrite) int thumbnailY; 34 | 35 | @end 36 | 37 | /* Mutable interface Category for EXFObject */ 38 | @interface EXFMetaData () 39 | 40 | 41 | 42 | - (void) parseExif:(CFDataRef*) theExifData; 43 | - (void) getData: (NSMutableData*) imageData; 44 | 45 | -(void) setupHandlers; 46 | 47 | 48 | @property (readwrite,retain) NSMutableDictionary* userKeyedHandlers; 49 | 50 | @property (readwrite,retain) NSMutableDictionary* keyedHandlers; 51 | @property (readwrite,retain) EXFTagDefinitionHolder* tagDefinitions; 52 | @property (readwrite, retain) NSMutableDictionary* keyedTagValues; 53 | 54 | @property (readwrite,retain) NSMutableDictionary* keyedThumbnailTagValues; 55 | 56 | @property (readwrite,retain) NSData* thumbnailBytes; 57 | 58 | @property (readwrite) int compression; 59 | @property (readwrite) int bitsPerPixel; 60 | @property (readwrite) int height; 61 | @property (readwrite) int width; 62 | @property (readwrite) CFIndex byteLength; 63 | 64 | @property (readwrite) BOOL bigEndianOrder; 65 | @property (readwrite) ByteArray* exif_ptr; 66 | 67 | 68 | @end -------------------------------------------------------------------------------- /EXIF/EXFHandlers.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @header EXFTagHandler 3 | @copyright 2008. Created by steve woodcock on 30/03/2008. 4 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 5 | @discussion The EXFHandlers are to enable either overriding of default tag handling, or to be able to handle tags that 6 | are not recognised by the parser. 7 | 8 | In order to use this the implementation must support the protocol that at the very least provides: 9 | 1) Decoding the tag data from a byte format 10 | 2) The size in bytes that the value will occupy 11 | 3) Whether it will support the object type provided 12 | 4) Encoding of the value into a byte form 13 | 5) (Optionally) the tagFomat (see EXFConstants for the tagFormat enumeration) 14 | 15 | 16 | */ 17 | 18 | /*! 19 | @protocol EXFTagHandler 20 | @abstract Prtocol defintion for User defined Tag Handlers 21 | */ 22 | @protocol EXFTagHandler 23 | 24 | /*! 25 | Decoding of the tag from a byte buffer and insertion into the provided dictionary under the key provided 26 | */ 27 | -(void)decodeTag:(NSMutableDictionary*) keyedValues: (NSNumber*) tagId: (CFDataRef*) tagData: (BOOL) bigEndianOrder; 28 | 29 | -(int) getSizeOfValue:(id)value; 30 | 31 | -(BOOL)supportsValueType:(id) value; 32 | 33 | -(void)encodeTag: (NSMutableData*) targetBuffer: (id) tagData:(BOOL) bigEndianOrder; 34 | 35 | @optional 36 | 37 | -(int) tagFormat; 38 | -(int) parentTagId; 39 | -(BOOL) isEditable; 40 | 41 | @end 42 | 43 | /* 44 | These are the internal Handlers used to provide specialised handling for 45 | certain tags. 46 | */ 47 | 48 | @interface EXFGPSLocationHandler: NSObject 49 | 50 | @end 51 | 52 | @interface EXFGPSTimeHandler: NSObject 53 | 54 | @end 55 | 56 | @interface EXFTextHandler: NSObject 57 | 58 | @end 59 | 60 | @interface EXFASCIIHandler: NSObject 61 | 62 | @end 63 | 64 | @interface EXFByteHandler: NSObject 65 | @end 66 | 67 | @interface EXFByteArrayHandler: NSObject 68 | @end 69 | -------------------------------------------------------------------------------- /JSON/NSString+SBJSON.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2007-2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import "NSString+SBJSON.h" 31 | #import "SBJsonParser.h" 32 | 33 | @implementation NSString (NSString_SBJSON) 34 | 35 | - (id)JSONValue 36 | { 37 | SBJsonParser *jsonParser = [SBJsonParser new]; 38 | id repr = [jsonParser objectWithString:self]; 39 | if (!repr) 40 | NSLog(@"-JSONValue failed. Error trace is: %@", [jsonParser errorTrace]); 41 | [jsonParser release]; 42 | return repr; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Classes/SPSourceAddressBookTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceAddressBookTVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/16/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPSourceAddressBookTVC.h" 11 | #import 12 | 13 | 14 | @implementation SPSourceAddressBookTVC 15 | 16 | - (void)loadData { 17 | if(contentsDictionaries) return; 18 | 19 | ABAddressBookRef addressBook = ABAddressBookCreate(); 20 | 21 | NSArray *people = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 22 | 23 | NSMutableArray *allEmails = [NSMutableArray array]; 24 | 25 | for(id record in people) { 26 | ABMultiValueRef emailsContainer = ABRecordCopyValue(record, kABPersonEmailProperty); 27 | CFArrayRef emails = ABMultiValueCopyArrayOfAllValues(emailsContainer); 28 | CFRelease(emailsContainer); 29 | if(emails) { 30 | [allEmails addObjectsFromArray:(NSArray *)emails]; 31 | CFRelease(emails); 32 | } 33 | } 34 | 35 | [people release]; 36 | 37 | CFRelease(addressBook); 38 | 39 | NSString *keyName = [NSString stringWithFormat:@"%d Email Addresses", [allEmails count]]; 40 | self.contentsDictionaries = [NSArray arrayWithObject:[NSDictionary dictionaryWithObject:allEmails forKey:keyName]]; 41 | } 42 | 43 | /* 44 | // Override to allow orientations other than the default portrait orientation. 45 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 46 | // Return YES for supported orientations 47 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 48 | } 49 | */ 50 | 51 | - (void)didReceiveMemoryWarning { 52 | // Releases the view if it doesn't have a superview. 53 | [super didReceiveMemoryWarning]; 54 | 55 | // Release any cached data, images, etc that aren't in use. 56 | } 57 | 58 | - (void)viewDidUnload { 59 | // Release any retained subviews of the main view. 60 | // e.g. self.myOutlet = nil; 61 | } 62 | 63 | 64 | - (void)dealloc { 65 | [super dealloc]; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /JSON/NSObject+SBJSON.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import "NSObject+SBJSON.h" 31 | #import "SBJsonWriter.h" 32 | 33 | @implementation NSObject (NSObject_SBJSON) 34 | 35 | - (NSString *)JSONRepresentation { 36 | SBJsonWriter *jsonWriter = [SBJsonWriter new]; 37 | NSString *json = [jsonWriter stringWithObject:self]; 38 | if (!json) 39 | NSLog(@"-JSONRepresentation failed. Error trace is: %@", [jsonWriter errorTrace]); 40 | [jsonWriter release]; 41 | return json; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /JSON/NSString+SBJSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import 31 | 32 | /** 33 | @brief Adds JSON parsing methods to NSString 34 | 35 | This is a category on NSString that adds methods for parsing the target string. 36 | */ 37 | @interface NSString (NSString_SBJSON) 38 | 39 | /** 40 | @brief Returns the NSDictionary or NSArray represented by the current string's JSON representation. 41 | 42 | Returns the dictionary or array represented in the receiver, or nil on error. 43 | 44 | Returns the NSDictionary or NSArray represented by the current string's JSON representation. 45 | */ 46 | - (id)JSONValue; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /JSON/NSObject+SBJSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import 31 | 32 | 33 | /** 34 | @brief Adds JSON generation to Foundation classes 35 | 36 | This is a category on NSObject that adds methods for returning JSON representations 37 | of standard objects to the objects themselves. This means you can call the 38 | -JSONRepresentation method on an NSArray object and it'll do what you want. 39 | */ 40 | @interface NSObject (NSObject_SBJSON) 41 | 42 | /** 43 | @brief Returns a string containing the receiver encoded in JSON. 44 | 45 | This method is added as a category on NSObject but is only actually 46 | supported for the following objects: 47 | @li NSDictionary 48 | @li NSArray 49 | */ 50 | - (NSString *)JSONRepresentation; 51 | 52 | @end 53 | 54 | -------------------------------------------------------------------------------- /EXIF/EXFGPS.m: -------------------------------------------------------------------------------- 1 | /* 2 | * EXFGPSLoc.m 3 | * 4 | * 5 | * Created by steve woodcock on 30/03/2008. 6 | * Copyright 2008. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | * 9 | * A set of fractions that represent the 3 rational numbers that make up the 10 | * GPS Location. these are: 11 | * Degrees 12 | * Minutes 13 | * Seconds 14 | * 15 | * The EXF Specification suggests the location should be displayed as 3 rationals. ALthough we use fractions 16 | * to actually represent any stored number without getting precision errors. 17 | */ 18 | 19 | #import "EXFGPS.h" 20 | 21 | 22 | 23 | @implementation EXFGPSLoc 24 | 25 | @synthesize degrees; 26 | @synthesize minutes; 27 | @synthesize seconds; 28 | 29 | -(NSString*) description{ 30 | 31 | return [NSString stringWithFormat:@"%@\xC2\xB0 %@' %@\"",degrees, minutes,seconds]; 32 | } 33 | 34 | 35 | -(double) descriptionAsDecimal{ 36 | return ((double)degrees.numerator/degrees.denominator) +(((double)minutes.numerator/ minutes.denominator)/60) + (((double)seconds.numerator /seconds.denominator)/3600) ; 37 | } 38 | 39 | -(void) dealloc{ 40 | self.degrees =nil; 41 | self.minutes=nil; 42 | self.seconds =nil; 43 | 44 | [super dealloc]; 45 | } 46 | @end 47 | 48 | @implementation EXFGPSTimeStamp 49 | 50 | @synthesize hours; 51 | @synthesize minutes; 52 | @synthesize seconds; 53 | 54 | -(NSString*) description{ 55 | 56 | NSString* hoursStr = [NSString stringWithFormat:@"%i", (int)hours.numerator/hours.denominator]; 57 | NSString* minutesStr = [NSString stringWithFormat:@"%i", (int)minutes.numerator/minutes.denominator]; 58 | NSString* secondsStr = [NSString stringWithFormat:@"%i", (int)seconds.numerator/seconds.denominator]; 59 | 60 | if ([hoursStr length] ==1){ 61 | hoursStr = [NSString stringWithFormat:@"0%@", hoursStr]; 62 | } 63 | if ([minutesStr length] ==1){ 64 | minutesStr = [NSString stringWithFormat:@"0%@", minutesStr]; 65 | } 66 | if ([secondsStr length] ==1){ 67 | secondsStr = [NSString stringWithFormat:@"0%@", secondsStr]; 68 | } 69 | 70 | 71 | return [NSString stringWithFormat:@"%@:%@:%@",hoursStr,minutesStr,secondsStr]; 72 | } 73 | 74 | -(void) dealloc{ 75 | self.hours =nil; 76 | self.minutes=nil; 77 | self.seconds =nil; 78 | 79 | [super dealloc]; 80 | } 81 | @end 82 | -------------------------------------------------------------------------------- /JSON/SBProxyForJson.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | /** 36 | @brief Allows generation of JSON for otherwise unsupported classes. 37 | 38 | If you have a custom class that you want to create a JSON representation for you can implement 39 | this method in your class. It should return a representation of your object defined 40 | in terms of objects that can be translated into JSON. For example, a Person 41 | object might implement it like this: 42 | 43 | @code 44 | - (id)proxyForJson { 45 | return [NSDictionary dictionaryWithObjectsAndKeys: 46 | name, @"name", 47 | phone, @"phone", 48 | email, @"email", 49 | nil]; 50 | } 51 | @endcode 52 | 53 | */ 54 | @interface NSObject (SBProxyForJson) 55 | 56 | - (id)proxyForJson; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Classes/SPSourceEmailTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceEmailTVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPSourceEmailTVC.h" 11 | #import "SPCell.h" 12 | #import "SPEmailASAccount.h" 13 | #import "SPEmailPOPAccount.h" 14 | #import "SPEmailIToolsAccount.h" 15 | #import "SPEmailGmailAccount.h" 16 | #import "SPEmailIMAPAccount.h" 17 | #import "SPEmailMobileMeAccount.h" 18 | 19 | @implementation SPSourceEmailTVC 20 | 21 | @synthesize emails; 22 | 23 | - (void)dealloc { 24 | [emails release]; 25 | [super dealloc]; 26 | } 27 | 28 | - (NSString *)emailForReport { 29 | [self loadData]; 30 | 31 | if([emails count] < 1) return nil; 32 | return [emails objectAtIndex:0]; 33 | } 34 | 35 | - (void)loadData { 36 | if(contentsDictionaries) return; 37 | 38 | self.emails = [NSMutableArray array]; 39 | self.contentsDictionaries = [NSMutableArray array]; 40 | 41 | NSMutableArray *accountsFound = [NSMutableArray array]; 42 | 43 | NSString *path = @"/var/mobile/Library/Preferences/com.apple.accountsettings.plist"; 44 | NSDictionary *d = [NSDictionary dictionaryWithContentsOfFile:path]; 45 | NSArray *accounts = [d valueForKey:@"Accounts"]; 46 | for(NSDictionary *account in accounts) { 47 | NSString *classValue = [account valueForKey:@"Class"]; 48 | if([classValue isEqualToString:@"ASAccount"]) [accountsFound addObject:[SPEmailASAccount accountWithDictionary:account]]; 49 | if([classValue isEqualToString:@"POPAccount"]) [accountsFound addObject:[SPEmailPOPAccount accountWithDictionary:account]]; 50 | if([classValue isEqualToString:@"iToolsAccount"]) [accountsFound addObject:[SPEmailIToolsAccount accountWithDictionary:account]]; 51 | if([classValue isEqualToString:@"GmailAccount"]) [accountsFound addObject:[SPEmailGmailAccount accountWithDictionary:account]]; 52 | if([classValue isEqualToString:@"IMAPAccount"]) [accountsFound addObject:[SPEmailIMAPAccount accountWithDictionary:account]]; 53 | if([classValue isEqualToString:@"MobileMeAccount"]) [accountsFound addObject:[SPEmailMobileMeAccount accountWithDictionary:account]]; 54 | } 55 | 56 | for(SPEmailAccount *account in accountsFound) { 57 | if(!account.emails) continue; 58 | [emails addObjectsFromArray:account.emails]; 59 | [contentsDictionaries addObject:[NSDictionary dictionaryWithObject:[account infoArray] forKey:account.displayName]]; 60 | } 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Classes/SPWifiMapVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPWifiMapVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 10/31/10. 6 | // Copyright 2010 IICT. All rights reserved. 7 | // 8 | 9 | #import "SPWifiMapVC.h" 10 | 11 | 12 | @implementation SPWifiMapVC 13 | 14 | @synthesize annotations; 15 | 16 | //- (void)setAnnotations:(NSArray *)someAnnotations { 17 | // [mapView removeAnnotations:mapView.annotations]; 18 | // 19 | // [annotations autorelease]; 20 | // annotations = [someAnnotations retain]; 21 | // 22 | // [mapView addAnnotations:annotations]; 23 | //} 24 | 25 | - (void)loadView { 26 | [super loadView]; 27 | 28 | self.title = @"Wifi Map"; 29 | } 30 | 31 | - (void)viewWillAppear:(BOOL)animated { 32 | [super viewWillAppear:animated]; 33 | 34 | [mapView removeAnnotations:mapView.annotations]; 35 | [mapView addAnnotations:annotations]; 36 | 37 | id annotation = [annotations lastObject]; 38 | MKCoordinateSpan span = MKCoordinateSpanMake(0.03, 0.03); 39 | MKCoordinateRegion region = [mapView regionThatFits:MKCoordinateRegionMake(annotation.coordinate, span)]; 40 | 41 | @try { 42 | [mapView setRegion:region animated:NO]; 43 | } @catch (NSException *exception) { 44 | NSLog(@"-- %@", exception); 45 | } @finally { 46 | } 47 | } 48 | 49 | - (void)viewDidAppear:(BOOL)animated { 50 | [super viewDidAppear:animated]; 51 | 52 | 53 | if([annotations count] == 1) [mapView selectAnnotation:[annotations lastObject] animated:YES]; 54 | } 55 | 56 | - (MKAnnotationView *)mapView:(MKMapView *)aMapView viewForAnnotation:(id )annotation { 57 | 58 | if([annotation isKindOfClass:[MKUserLocation class]]) return nil; 59 | 60 | NSString *annID = @"SPWifiAnnotation"; 61 | MKAnnotationView *av = [aMapView dequeueReusableAnnotationViewWithIdentifier:annID]; 62 | 63 | if(av == nil) { 64 | av = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annID] autorelease]; 65 | av.canShowCallout = YES; 66 | } 67 | return av; 68 | } 69 | 70 | /* 71 | // Override to allow orientations other than the default portrait orientation. 72 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 73 | // Return YES for supported orientations 74 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 75 | } 76 | */ 77 | 78 | - (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views { 79 | [aMapView selectAnnotation:[aMapView.annotations lastObject] animated:YES]; 80 | } 81 | 82 | - (void)dealloc { 83 | [annotations release]; 84 | [super dealloc]; 85 | } 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /Classes/SPSourceTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceTVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/17/09. 6 | // Copyright 2009. All rights reserved. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPSourceTVC.h" 11 | #import "SPCell.h" 12 | 13 | @implementation SPSourceTVC 14 | 15 | @synthesize contentsDictionaries; 16 | 17 | - (UIImage *)image { 18 | NSString *className = NSStringFromClass([self class]); 19 | NSString *name = nil; 20 | 21 | if([className hasPrefix:@"SPSource"] && [className hasSuffix:@"TVC"]) { 22 | NSRange range = NSMakeRange(8, [className length] - 3 - 8); 23 | name = [className substringWithRange:range]; 24 | } 25 | 26 | NSString *imageName = [name stringByAppendingPathExtension:@"png"]; 27 | return [UIImage imageNamed:imageName]; 28 | } 29 | 30 | - (void)didReceiveMemoryWarning { 31 | // Releases the view if it doesn't have a superview. 32 | [super didReceiveMemoryWarning]; 33 | 34 | // Release any cached data, images, etc that aren't in use. 35 | } 36 | 37 | - (void)loadData { 38 | // to be overriden by subclasses 39 | } 40 | 41 | - (void)viewDidLoad { 42 | [super viewDidLoad]; 43 | 44 | if(!contentsDictionaries) [self loadData]; 45 | } 46 | 47 | - (void)dealloc { 48 | [super dealloc]; 49 | } 50 | 51 | #pragma mark UITableViewDataSource 52 | 53 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 54 | return [contentsDictionaries count]; 55 | } 56 | 57 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 58 | NSDictionary *d = [contentsDictionaries objectAtIndex:section]; 59 | return [[d allKeys] lastObject]; 60 | } 61 | 62 | - (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section { 63 | NSDictionary *d = [contentsDictionaries objectAtIndex:section]; 64 | NSArray *a = [[d allValues] lastObject]; 65 | return [a count]; 66 | } 67 | 68 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 69 | 70 | static NSString *SourceCellIdentifier = @"SPCell"; 71 | 72 | SPCell *cell = (SPCell *)[tableView dequeueReusableCellWithIdentifier:SourceCellIdentifier]; 73 | if (cell == nil) { 74 | cell = (SPCell *)[[[NSBundle mainBundle] loadNibNamed:@"SPCell" owner:self options:nil] lastObject]; 75 | } 76 | 77 | NSArray *a = [[[contentsDictionaries objectAtIndex:indexPath.section] allValues] lastObject]; 78 | cell.accessoryType = UITableViewCellAccessoryNone; 79 | cell.textLabel.adjustsFontSizeToFitWidth = YES; 80 | cell.textLabel.text = [a objectAtIndex:indexPath.row]; 81 | return cell; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /Classes/SPEmailReportVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPEmailReportVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/22/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPEmailReportVC.h" 11 | 12 | @implementation SPEmailReportVC 13 | 14 | @synthesize message; 15 | @synthesize allSources; 16 | 17 | 18 | - (IBAction)sendReport:(id)sender { 19 | if([MFMailComposeViewController canSendMail] == NO) { 20 | message.text = @"Error: this device can't send emails."; 21 | return; 22 | } 23 | 24 | MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init]; 25 | picker.mailComposeDelegate = self; 26 | 27 | [picker setSubject:@"SpyPhone Report"]; 28 | 29 | // Set up recipients 30 | NSString *email = [allSources emailForReport]; 31 | if(email) [picker setToRecipients:[NSArray arrayWithObject:email]]; 32 | 33 | // Fill out the email body text 34 | NSString *emailBody = [allSources report]; 35 | [picker setMessageBody:emailBody isHTML:NO]; 36 | 37 | [self presentModalViewController:picker animated:YES]; 38 | [picker release]; 39 | } 40 | 41 | // Dismisses the email composition interface when users tap Cancel or Send. Proceeds to update the message field with the result of the operation. 42 | - (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error { 43 | // message.hidden = NO; 44 | // Notifies users about errors associated with the interface 45 | switch (result) { 46 | case MFMailComposeResultCancelled: 47 | message.text = @"Result: canceled"; 48 | break; 49 | case MFMailComposeResultSaved: 50 | message.text = @"Result: saved"; 51 | break; 52 | case MFMailComposeResultSent: 53 | message.text = @"Result: sent"; 54 | break; 55 | case MFMailComposeResultFailed: 56 | message.text = @"Result: failed"; 57 | break; 58 | default: 59 | message.text = @"Result: not sent"; 60 | break; 61 | } 62 | 63 | [self dismissModalViewControllerAnimated:YES]; 64 | } 65 | 66 | - (void)didReceiveMemoryWarning { 67 | // Releases the view if it doesn't have a superview. 68 | [super didReceiveMemoryWarning]; 69 | 70 | // Release any cached data, images, etc that aren't in use. 71 | } 72 | 73 | - (void)viewDidUnload { 74 | // Release any retained subviews of the main view. 75 | // e.g. self.myOutlet = nil; 76 | } 77 | 78 | - (void)dealloc { 79 | [allSources release]; 80 | [message release]; 81 | [super dealloc]; 82 | } 83 | 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /FMDB/FMResultSet.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "sqlite3.h" 3 | 4 | #ifndef __has_feature // Optional. 5 | #define __has_feature(x) 0 // Compatibility with non-clang compilers. 6 | #endif 7 | 8 | #ifndef NS_RETURNS_NOT_RETAINED 9 | #if __has_feature(attribute_ns_returns_not_retained) 10 | #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) 11 | #else 12 | #define NS_RETURNS_NOT_RETAINED 13 | #endif 14 | #endif 15 | 16 | @class FMDatabase; 17 | @class FMStatement; 18 | 19 | @interface FMResultSet : NSObject { 20 | FMDatabase *parentDB; 21 | FMStatement *statement; 22 | 23 | NSString *query; 24 | NSMutableDictionary *columnNameToIndexMap; 25 | BOOL columnNamesSetup; 26 | } 27 | 28 | 29 | + (id)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB; 30 | 31 | - (void)close; 32 | 33 | - (NSString *)query; 34 | - (void)setQuery:(NSString *)value; 35 | 36 | - (FMStatement *)statement; 37 | - (void)setStatement:(FMStatement *)value; 38 | 39 | - (void)setParentDB:(FMDatabase *)newDb; 40 | 41 | - (BOOL)next; 42 | - (BOOL)hasAnotherRow; 43 | 44 | - (int)columnIndexForName:(NSString*)columnName; 45 | - (NSString*)columnNameForIndex:(int)columnIdx; 46 | 47 | - (int)intForColumn:(NSString*)columnName; 48 | - (int)intForColumnIndex:(int)columnIdx; 49 | 50 | - (long)longForColumn:(NSString*)columnName; 51 | - (long)longForColumnIndex:(int)columnIdx; 52 | 53 | - (long long int)longLongIntForColumn:(NSString*)columnName; 54 | - (long long int)longLongIntForColumnIndex:(int)columnIdx; 55 | 56 | - (BOOL)boolForColumn:(NSString*)columnName; 57 | - (BOOL)boolForColumnIndex:(int)columnIdx; 58 | 59 | - (double)doubleForColumn:(NSString*)columnName; 60 | - (double)doubleForColumnIndex:(int)columnIdx; 61 | 62 | - (NSString*)stringForColumn:(NSString*)columnName; 63 | - (NSString*)stringForColumnIndex:(int)columnIdx; 64 | 65 | - (NSDate*)dateForColumn:(NSString*)columnName; 66 | - (NSDate*)dateForColumnIndex:(int)columnIdx; 67 | 68 | - (NSData*)dataForColumn:(NSString*)columnName; 69 | - (NSData*)dataForColumnIndex:(int)columnIdx; 70 | 71 | - (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx; 72 | - (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName; 73 | 74 | /* 75 | If you are going to use this data after you iterate over the next row, or after you close the 76 | result set, make sure to make a copy of the data first (or just use dataForColumn:/dataForColumnIndex:) 77 | If you don't, you're going to be in a world of hurt when you try and use the data. 78 | */ 79 | - (NSData*)dataNoCopyForColumn:(NSString*)columnName NS_RETURNS_NOT_RETAINED; 80 | - (NSData*)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED; 81 | 82 | 83 | - (BOOL)columnIndexIsNull:(int)columnIdx; 84 | - (BOOL)columnIsNull:(NSString*)columnName; 85 | 86 | - (void)kvcMagic:(id)object; 87 | - (NSDictionary *)resultDict; 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /JSON/SBJsonBase.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import "SBJsonBase.h" 31 | NSString * SBJSONErrorDomain = @"org.brautaset.JSON.ErrorDomain"; 32 | 33 | 34 | @implementation SBJsonBase 35 | 36 | @synthesize errorTrace; 37 | @synthesize maxDepth; 38 | 39 | - (id)init { 40 | self = [super init]; 41 | if (self) 42 | self.maxDepth = 512; 43 | return self; 44 | } 45 | 46 | - (void)dealloc { 47 | [errorTrace release]; 48 | [super dealloc]; 49 | } 50 | 51 | - (void)addErrorWithCode:(NSUInteger)code description:(NSString*)str { 52 | NSDictionary *userInfo; 53 | if (!errorTrace) { 54 | errorTrace = [NSMutableArray new]; 55 | userInfo = [NSDictionary dictionaryWithObject:str forKey:NSLocalizedDescriptionKey]; 56 | 57 | } else { 58 | userInfo = [NSDictionary dictionaryWithObjectsAndKeys: 59 | str, NSLocalizedDescriptionKey, 60 | [errorTrace lastObject], NSUnderlyingErrorKey, 61 | nil]; 62 | } 63 | 64 | NSError *error = [NSError errorWithDomain:SBJSONErrorDomain code:code userInfo:userInfo]; 65 | 66 | [self willChangeValueForKey:@"errorTrace"]; 67 | [errorTrace addObject:error]; 68 | [self didChangeValueForKey:@"errorTrace"]; 69 | } 70 | 71 | - (void)clearErrorTrace { 72 | [self willChangeValueForKey:@"errorTrace"]; 73 | [errorTrace release]; 74 | errorTrace = nil; 75 | [self didChangeValueForKey:@"errorTrace"]; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /JSON/JSON.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009-2010 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | /** 31 | @mainpage A strict JSON parser and generator for Objective-C 32 | 33 | JSON (JavaScript Object Notation) is a lightweight data-interchange 34 | format. This framework provides two apis for parsing and generating 35 | JSON. One standard object-based and a higher level api consisting of 36 | categories added to existing Objective-C classes. 37 | 38 | This framework does its best to be as strict as possible, both in what it accepts and what it generates. For example, it does not support trailing commas in arrays or objects. Nor does it support embedded comments, or anything else not in the JSON specification. This is considered a feature. 39 | 40 | @section Links 41 | 42 | @li Project home page. 43 | @li Online version of the API documentation. 44 | 45 | */ 46 | 47 | 48 | // This setting of 1 is best if you copy the source into your project. 49 | // The build transforms the 1 to a 0 when building the framework and static lib. 50 | 51 | #if 1 52 | 53 | #import "SBJsonParser.h" 54 | #import "SBJsonWriter.h" 55 | #import "SBJsonStreamWriter.h" 56 | #import "NSObject+SBJSON.h" 57 | #import "NSString+SBJSON.h" 58 | 59 | #else 60 | 61 | #import 62 | #import 63 | #import 64 | #import 65 | #import 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /Classes/SPSourceWifiTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceWifiTVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPSourceWifiTVC.h" 11 | #import "OUILookupTool.h" 12 | #import "SPWifiMapVC.h" 13 | #import "SPWifiAnnotation.h" 14 | #import "SPCell.h" 15 | 16 | @implementation SPSourceWifiTVC 17 | 18 | @synthesize annotations; 19 | @synthesize accessPoints; 20 | @synthesize mapVC; 21 | 22 | - (void)loadData { 23 | 24 | if(contentsDictionaries) return; 25 | 26 | UIBarButtonItem *mapButton = [[UIBarButtonItem alloc] initWithTitle:@"Map" style:UIBarButtonItemStylePlain target:self action:@selector(mapButtonClicked:)]; 27 | super.navigationItem.rightBarButtonItem = mapButton; 28 | 29 | self.contentsDictionaries = [NSMutableArray array]; 30 | 31 | self.annotations = [NSMutableArray array]; 32 | 33 | self.accessPoints = [NSMutableArray array]; 34 | 35 | NSString *path = @"/Library/Preferences/SystemConfiguration/com.apple.wifi.plist"; 36 | NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; 37 | if(!dict) return; 38 | 39 | NSArray *a = [dict valueForKey:@"List of known networks"]; 40 | if(!a) return; 41 | 42 | for(NSDictionary *d in a) { 43 | NSMutableDictionary *md = [NSMutableDictionary dictionaryWithDictionary:d]; 44 | 45 | [OUILookupTool locateWifiAccessPoint:md delegate:self]; 46 | 47 | NSString *name = [d valueForKey:@"SSID_STR"]; 48 | 49 | NSDate *joined = [md valueForKey:@"lastJoined"]; 50 | NSDate *autoJoined = [md valueForKey:@"lastAutoJoined"]; 51 | 52 | NSString *date = [NSString stringWithFormat:@"%@", autoJoined ? autoJoined : joined]; 53 | 54 | [contentsDictionaries addObject:[NSDictionary dictionaryWithObject:[NSArray arrayWithObject:name] forKey:date]]; 55 | [accessPoints addObject:md]; 56 | } 57 | } 58 | 59 | - (void)mapButtonClicked:(id)sender { 60 | mapVC.annotations = annotations; 61 | [self.navigationController pushViewController:mapVC animated:YES]; 62 | } 63 | 64 | - (void)dealloc { 65 | [accessPoints release]; 66 | [annotations release]; 67 | [mapVC release]; 68 | [super dealloc]; 69 | } 70 | 71 | #pragma mark OUILookupTool 72 | 73 | - (void)OUILookupTool:(OUILookupTool *)ouiLookupTool didLocateAccessPoint:(NSDictionary *)ap { 74 | //NSLog(@"-- %@", ap); 75 | 76 | [accessPoints addObject:ap]; 77 | 78 | SPWifiAnnotation *annotation = [SPWifiAnnotation annotationWithAccessPoint:ap]; 79 | 80 | if(annotation) [annotations addObject:annotation]; 81 | } 82 | 83 | #pragma mark UITableViewDelegate 84 | 85 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 86 | 87 | NSDictionary *ap = [accessPoints objectAtIndex:indexPath.section]; 88 | 89 | SPWifiAnnotation *annotation = [SPWifiAnnotation annotationWithAccessPoint:ap]; 90 | 91 | if(annotation == nil) return; 92 | 93 | mapVC.annotations = [NSArray arrayWithObject:annotation]; 94 | 95 | [self.navigationController pushViewController:mapVC animated:YES]; 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /Classes/SPAllSourcesTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SourcesTVController.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPAllSourcesTVC.h" 11 | #import "SPSourceTVC.h" 12 | #import "SPCell.h" 13 | 14 | @implementation SPAllSourcesTVC 15 | 16 | @synthesize sources; 17 | 18 | - (void)loadSources { 19 | if(sources) return; 20 | 21 | if(!self.isViewLoaded) [self loadView]; 22 | 23 | self.sources = [NSArray arrayWithObjects: 24 | sourceEmailTVC, 25 | sourceWifiTVC, 26 | sourcePhoneTVC, 27 | sourceLocationTVC, 28 | sourcePhotosTVC, 29 | sourceAddressBookTVC, 30 | sourceKeyboardTVC, 31 | nil]; 32 | } 33 | 34 | - (NSString *)emailForReport { 35 | if(!self.isViewLoaded) [self loadView]; 36 | 37 | return [sourceEmailTVC emailForReport]; 38 | } 39 | 40 | // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 41 | - (void)viewDidLoad { 42 | [super viewDidLoad]; 43 | 44 | if(!sources) [self loadSources]; 45 | } 46 | 47 | - (NSString *)report { 48 | [self loadSources]; 49 | 50 | NSMutableString *s = [NSMutableString string]; 51 | 52 | for(SPSourceTVC *source in sources) { 53 | [s appendString:[NSString stringWithFormat:@"----- %@ -----\n\n", [source.title uppercaseString]]]; 54 | 55 | [source loadData]; 56 | NSArray *a = source.contentsDictionaries; 57 | for(NSDictionary *d in a) { 58 | [s appendString:[NSString stringWithFormat:@"[[ %@ ]]\n", [[d allKeys] lastObject]]]; 59 | [s appendString:[[[d allValues] lastObject] componentsJoinedByString:@"\n"]]; 60 | [s appendString:@"\n\n"]; 61 | } 62 | //[s appendString:@"\n"]; 63 | } 64 | 65 | return s; 66 | } 67 | 68 | - (void)dealloc { 69 | [sources release]; 70 | [super dealloc]; 71 | } 72 | 73 | #pragma mark UITableViewDataSource 74 | 75 | - (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section { 76 | return [sources count]; 77 | } 78 | 79 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 80 | 81 | static NSString *SourceCellIdentifier = @"SPCell"; 82 | 83 | SPCell *cell = (SPCell *)[tableView dequeueReusableCellWithIdentifier:SourceCellIdentifier]; 84 | if (cell == nil) { 85 | cell = (SPCell *)[[[NSBundle mainBundle] loadNibNamed:@"SPCell" owner:self options:nil] lastObject]; 86 | } 87 | 88 | SPSourceTVC *sourceTVC = [sources objectAtIndex:indexPath.row]; 89 | 90 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 91 | cell.textLabel.text = [sourceTVC title]; 92 | cell.imageView.image = [sourceTVC image]; 93 | return cell; 94 | } 95 | 96 | #pragma mark UITableViewDelegate 97 | 98 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 99 | UIViewController *sourceVC = [sources objectAtIndex:indexPath.row]; 100 | [self.navigationController pushViewController:sourceVC animated:YES]; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /JSON/SBJsonBase.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import 31 | 32 | extern NSString * SBJSONErrorDomain; 33 | 34 | 35 | enum { 36 | EUNSUPPORTED = 1, 37 | EPARSENUM, 38 | EPARSE, 39 | EFRAGMENT, 40 | ECTRL, 41 | EUNICODE, 42 | EDEPTH, 43 | EESCAPE, 44 | ETRAILCOMMA, 45 | ETRAILGARBAGE, 46 | EEOF, 47 | EINPUT 48 | }; 49 | 50 | /** 51 | @brief Common base class for parsing & writing. 52 | 53 | This class contains the common error-handling code and option between the parser/writer. 54 | */ 55 | @interface SBJsonBase : NSObject { 56 | NSMutableArray *errorTrace; 57 | 58 | @protected 59 | NSUInteger depth, maxDepth; 60 | } 61 | 62 | /** 63 | @brief The maximum recursing depth. 64 | 65 | Defaults to 512. If the input is nested deeper than this the input will be deemed to be 66 | malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can 67 | turn off this security feature by setting the maxDepth value to 0. 68 | */ 69 | @property NSUInteger maxDepth; 70 | 71 | /** 72 | @brief Return an error trace, or nil if there was no errors. 73 | 74 | Note that this method returns the trace of the last method that failed. 75 | You need to check the return value of the call you're making to figure out 76 | if the call actually failed, before you know call this method. 77 | */ 78 | @property(copy,readonly) NSArray* errorTrace; 79 | 80 | /// @internal for use in subclasses to add errors to the stack trace 81 | - (void)addErrorWithCode:(NSUInteger)code description:(NSString*)str; 82 | 83 | /// @internal for use in subclasess to clear the error before a new parsing attempt 84 | - (void)clearErrorTrace; 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /FMDB/FMDatabase.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "sqlite3.h" 3 | #import "FMResultSet.h" 4 | 5 | @interface FMDatabase : NSObject 6 | { 7 | sqlite3* db; 8 | NSString* databasePath; 9 | BOOL logsErrors; 10 | BOOL crashOnErrors; 11 | BOOL inUse; 12 | BOOL inTransaction; 13 | BOOL traceExecution; 14 | BOOL checkedOut; 15 | int busyRetryTimeout; 16 | BOOL shouldCacheStatements; 17 | NSMutableDictionary *cachedStatements; 18 | } 19 | 20 | 21 | + (id)databaseWithPath:(NSString*)inPath; 22 | - (id)initWithPath:(NSString*)inPath; 23 | 24 | - (BOOL)open; 25 | #if SQLITE_VERSION_NUMBER >= 3005000 26 | - (BOOL)openWithFlags:(int)flags; 27 | #endif 28 | - (BOOL)close; 29 | - (BOOL)goodConnection; 30 | - (void)clearCachedStatements; 31 | 32 | // encryption methods. You need to have purchased the sqlite encryption extensions for these to work. 33 | - (BOOL)setKey:(NSString*)key; 34 | - (BOOL)rekey:(NSString*)key; 35 | 36 | 37 | - (NSString *)databasePath; 38 | 39 | - (NSString*)lastErrorMessage; 40 | 41 | - (int)lastErrorCode; 42 | - (BOOL)hadError; 43 | - (sqlite_int64)lastInsertRowId; 44 | 45 | - (sqlite3*)sqliteHandle; 46 | 47 | - (BOOL)executeUpdate:(NSString*)sql, ...; 48 | - (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments; 49 | - (id)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args; // you shouldn't ever need to call this. use the previous two instead. 50 | 51 | - (id)executeQuery:(NSString*)sql, ...; 52 | - (id)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments; 53 | - (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args; // you shouldn't ever need to call this. use the previous two instead. 54 | 55 | - (BOOL)rollback; 56 | - (BOOL)commit; 57 | - (BOOL)beginTransaction; 58 | - (BOOL)beginDeferredTransaction; 59 | 60 | - (BOOL)logsErrors; 61 | - (void)setLogsErrors:(BOOL)flag; 62 | 63 | - (BOOL)crashOnErrors; 64 | - (void)setCrashOnErrors:(BOOL)flag; 65 | 66 | - (BOOL)inUse; 67 | - (void)setInUse:(BOOL)value; 68 | 69 | - (BOOL)inTransaction; 70 | - (void)setInTransaction:(BOOL)flag; 71 | 72 | - (BOOL)traceExecution; 73 | - (void)setTraceExecution:(BOOL)flag; 74 | 75 | - (BOOL)checkedOut; 76 | - (void)setCheckedOut:(BOOL)flag; 77 | 78 | - (int)busyRetryTimeout; 79 | - (void)setBusyRetryTimeout:(int)newBusyRetryTimeout; 80 | 81 | - (BOOL)shouldCacheStatements; 82 | - (void)setShouldCacheStatements:(BOOL)value; 83 | 84 | - (NSMutableDictionary *)cachedStatements; 85 | - (void)setCachedStatements:(NSMutableDictionary *)value; 86 | 87 | 88 | + (NSString*)sqliteLibVersion; 89 | 90 | - (int)changes; 91 | 92 | @end 93 | 94 | @interface FMStatement : NSObject { 95 | sqlite3_stmt *statement; 96 | NSString *query; 97 | long useCount; 98 | } 99 | 100 | 101 | - (void)close; 102 | - (void)reset; 103 | 104 | - (sqlite3_stmt *)statement; 105 | - (void)setStatement:(sqlite3_stmt *)value; 106 | 107 | - (NSString *)query; 108 | - (void)setQuery:(NSString *)value; 109 | 110 | - (long)useCount; 111 | - (void)setUseCount:(long)value; 112 | 113 | 114 | @end 115 | 116 | -------------------------------------------------------------------------------- /Classes/SPImageMapVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPMapVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/21/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPImageMapVC.h" 11 | #import "SPImageVC.h" 12 | 13 | @implementation SPImageMapVC 14 | 15 | @synthesize annotations; 16 | 17 | - (void)addAnnotation:(id )annotation { 18 | [mapView addAnnotation:annotation]; 19 | } 20 | 21 | - (MKAnnotationView *)mapView:(MKMapView *)aMapView viewForAnnotation:(id )annotation { 22 | 23 | if([annotation isKindOfClass:[MKUserLocation class]]) return nil; 24 | 25 | NSString *annID = @"SPImageAnnotation"; 26 | MKAnnotationView *av = [aMapView dequeueReusableAnnotationViewWithIdentifier:annID]; 27 | 28 | if(av == nil) { 29 | av = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annID] autorelease]; 30 | [av setRightCalloutAccessoryView:[UIButton buttonWithType:UIButtonTypeDetailDisclosure]]; 31 | av.canShowCallout = YES; 32 | } 33 | return av; 34 | } 35 | 36 | - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control { 37 | 38 | NSString *path = [(id)view.annotation path]; 39 | 40 | NSError *error = nil; 41 | NSDictionary *d = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&error]; 42 | if(!d) { 43 | NSLog(@"Error: can't read file attributes at path %@, %@ %@", path, [error description], [error userInfo]); 44 | } 45 | 46 | NSDate *date = [d fileModificationDate]; 47 | NSDateFormatter *df = [[NSDateFormatter alloc] init]; 48 | [df setDateFormat:@"yyyy-MM-dd HH:mm"]; 49 | imageVC.title = error ? @"Photo" : [df stringFromDate:date]; 50 | [df release]; 51 | 52 | imageVC.path = path; 53 | [self.navigationController pushViewController:imageVC animated:YES]; 54 | } 55 | 56 | - (void)viewDidLoad { 57 | [super viewDidLoad]; 58 | 59 | //mapView.showsUserLocation = YES; 60 | 61 | if([annotations count] == 0) return; 62 | 63 | MKCoordinateRegion region; 64 | MKCoordinateSpan span = MKCoordinateSpanMake(0.03, 0.03); 65 | 66 | for(id annotation in annotations) { 67 | region = [mapView regionThatFits:MKCoordinateRegionMake(annotation.coordinate, span)]; 68 | } 69 | 70 | [mapView setRegion:region]; 71 | [mapView addAnnotations:annotations]; 72 | } 73 | 74 | /* 75 | // Override to allow orientations other than the default portrait orientation. 76 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 77 | // Return YES for supported orientations 78 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 79 | } 80 | */ 81 | 82 | - (void)didReceiveMemoryWarning { 83 | // Releases the view if it doesn't have a superview. 84 | [super didReceiveMemoryWarning]; 85 | 86 | // Release any cached data, images, etc that aren't in use. 87 | } 88 | 89 | - (void)viewDidUnload { 90 | // Release any retained subviews of the main view. 91 | // e.g. self.myOutlet = nil; 92 | self.annotations = nil; 93 | } 94 | 95 | - (void)dealloc { 96 | [annotations release]; 97 | [super dealloc]; 98 | } 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /JSON/SBJsonParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import 31 | #import "SBJsonBase.h" 32 | 33 | /** 34 | @brief The JSON parser class. 35 | 36 | JSON is mapped to Objective-C types in the following way: 37 | 38 | @li Null -> NSNull 39 | @li String -> NSMutableString 40 | @li Array -> NSMutableArray 41 | @li Object -> NSMutableDictionary 42 | @li Boolean -> NSNumber (initialised with -initWithBool:) 43 | @li Number -> (NSNumber | NSDecimalNumber) 44 | 45 | Since Objective-C doesn't have a dedicated class for boolean values, these turns into NSNumber 46 | instances. These are initialised with the -initWithBool: method, and 47 | round-trip back to JSON properly. (They won't silently suddenly become 0 or 1; they'll be 48 | represented as 'true' and 'false' again.) 49 | 50 | As an optimisation short JSON integers turn into NSNumber instances, while complex ones turn into NSDecimalNumber instances. 51 | We can thus avoid any loss of precision as JSON allows ridiculously large numbers. 52 | 53 | */ 54 | @interface SBJsonParser : SBJsonBase { 55 | 56 | @private 57 | const char *c; 58 | } 59 | 60 | /** 61 | @brief Return the object represented by the given string 62 | 63 | Returns the object represented by the passed-in string or nil on error. The returned object can be 64 | a string, number, boolean, null, array or dictionary. 65 | 66 | @param repr the json string to parse 67 | */ 68 | - (id)objectWithString:(NSString *)repr; 69 | 70 | /** 71 | @brief Return the object represented by the given string 72 | 73 | Returns the object represented by the passed-in string or nil on error. The returned object can be 74 | a string, number, boolean, null, array or dictionary. 75 | 76 | @param jsonText the json string to parse 77 | @param error pointer to an NSError object to populate on error 78 | */ 79 | 80 | - (id)objectWithString:(NSString*)jsonText 81 | error:(NSError**)error; 82 | 83 | 84 | @end 85 | 86 | 87 | -------------------------------------------------------------------------------- /JSON/SBJsonWriter.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import "SBJsonWriter.h" 31 | #import "SBJsonStreamWriter.h" 32 | #import "SBProxyForJson.h" 33 | 34 | @interface SBJsonWriter () 35 | 36 | - (NSData*)dataWithObject:(id)value; 37 | 38 | @end 39 | 40 | @implementation SBJsonWriter 41 | 42 | @synthesize sortKeys; 43 | @synthesize humanReadable; 44 | 45 | 46 | - (NSString*)stringWithObject:(id)value { 47 | [self clearErrorTrace]; 48 | 49 | NSData *data = [self dataWithObject:value]; 50 | if (data) 51 | return [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; 52 | return nil; 53 | } 54 | 55 | - (NSString*)stringWithObject:(id)value error:(NSError**)error { 56 | NSString *tmp = [self stringWithObject:value]; 57 | if (tmp) 58 | return tmp; 59 | 60 | if (error) 61 | *error = [self.errorTrace lastObject]; 62 | return nil; 63 | } 64 | 65 | - (NSData*)dataWithObject:(id)object { 66 | NSOutputStream *stream = [[[NSOutputStream alloc] initToMemory] autorelease]; 67 | 68 | SBJsonStreamWriter *streamWriter = [[[SBJsonStreamWriter alloc] initWithStream:stream] autorelease]; 69 | streamWriter.sortKeys = self.sortKeys; 70 | streamWriter.maxDepth = self.maxDepth; 71 | streamWriter.humanReadable = self.humanReadable; 72 | 73 | BOOL ok = NO; 74 | if ([object isKindOfClass:[NSDictionary class]]) 75 | ok = [streamWriter writeObject:object]; 76 | 77 | else if ([object isKindOfClass:[NSArray class]]) 78 | ok = [streamWriter writeArray:object]; 79 | 80 | else if ([object respondsToSelector:@selector(proxyForJson)]) 81 | return [self dataWithObject:[object proxyForJson]]; 82 | else { 83 | [self addErrorWithCode:EUNSUPPORTED description:@"Not valid type for JSON"]; 84 | return nil; 85 | } 86 | 87 | if (ok) 88 | return [stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; 89 | 90 | [self addErrorWithCode:EUNSUPPORTED description:streamWriter.error]; 91 | return nil; 92 | } 93 | 94 | 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /OUILookupTool/OUILookupTool.m: -------------------------------------------------------------------------------- 1 | // 2 | // OUILookupTool.m 3 | // OUILookup 4 | // 5 | // Created by Nicolas Seriot on 10/31/10. 6 | // Copyright 2010 IICT. All rights reserved. 7 | // 8 | 9 | #import "OUILookupTool.h" 10 | #import "JSON.h" 11 | 12 | @implementation OUILookupTool 13 | 14 | @synthesize delegate; 15 | 16 | - (void)fetchLocationForAccessPointInNewThread:(NSMutableDictionary *)ap { 17 | 18 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 19 | 20 | NSString *aBSSID = [ap valueForKey:@"BSSID"]; 21 | 22 | NSDictionary *d = [NSDictionary dictionaryWithObject:aBSSID forKey:@"mac_address"]; 23 | NSArray *wifiTowers = [NSArray arrayWithObject:d]; 24 | 25 | NSDictionary *postDictionary = [[NSMutableDictionary alloc] initWithCapacity:3]; 26 | [postDictionary setValue:@"1.1.0" forKey:@"version"]; 27 | [postDictionary setValue:@"ouilookup" forKey:@"host"]; 28 | [postDictionary setValue:wifiTowers forKey:@"wifi_towers"]; 29 | 30 | NSString *postJSON = [postDictionary JSONRepresentation]; 31 | [postDictionary release]; 32 | 33 | NSData *data = [postJSON dataUsingEncoding:NSUTF8StringEncoding]; 34 | 35 | NSURL *url = [NSURL URLWithString:@"http://66.249.92.104/loc/json"]; 36 | 37 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 38 | [request setHTTPBody:data]; 39 | [request setCachePolicy:NSURLRequestUseProtocolCachePolicy]; 40 | [request setHTTPMethod:@"POST"]; 41 | [request setValue:@"application/json" forHTTPHeaderField:@"Content-type"]; 42 | NSString *contentLength = [NSString stringWithFormat:@"%d", [data length]]; 43 | [request setValue:contentLength forHTTPHeaderField:@"Content-Length"]; 44 | [request setValue:@"www.google.com" forHTTPHeaderField:@"Host"]; 45 | 46 | NSError *error = nil; 47 | NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error]; 48 | NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; 49 | 50 | NSDictionary *responseDict = [responseString JSONValue]; 51 | 52 | NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:ap, @"originalDict", responseDict, @"responseDict", nil]; 53 | 54 | [self performSelectorOnMainThread:@selector(didFinishLookup:) withObject:params waitUntilDone:YES]; 55 | 56 | [pool release]; 57 | } 58 | 59 | - (void)didFinishLookup:(NSDictionary *)params { 60 | // NSLog(@"-- %@", ap); 61 | 62 | NSMutableDictionary *ap = [params objectForKey:@"originalDict"]; 63 | NSDictionary *responseDict = [params objectForKey:@"responseDict"]; 64 | 65 | [ap addEntriesFromDictionary:responseDict]; 66 | 67 | [delegate OUILookupTool:self didLocateAccessPoint:ap]; 68 | } 69 | 70 | - (void)dealloc { 71 | [delegate release]; 72 | [super dealloc]; 73 | } 74 | 75 | + (NSString *)formattedBSSID:(NSString *)aBSSID { 76 | NSArray *comps = [aBSSID componentsSeparatedByString:@":"]; 77 | 78 | if([comps count] != 6) return nil; 79 | 80 | NSMutableArray *a = [NSMutableArray array]; 81 | 82 | for(NSString *comp in comps) { 83 | NSUInteger length = [comp length]; 84 | if(length == 0 || length > 2) return nil; 85 | 86 | NSString *s = length == 2 ? comp : [@"0" stringByAppendingString:comp]; 87 | [a addObject:s]; 88 | } 89 | 90 | return [a componentsJoinedByString:@":"]; 91 | } 92 | 93 | + (OUILookupTool *)locateWifiAccessPoint:(NSMutableDictionary *)ap delegate:(NSObject *)aDelegate { 94 | NSString *aBSSID = [ap valueForKey:@"BSSID"]; 95 | NSString *formattedBSSID = [self formattedBSSID:aBSSID]; 96 | if(formattedBSSID == nil) return nil; 97 | 98 | [ap setValue:formattedBSSID forKey:@"BSSID"]; 99 | 100 | OUILookupTool *olt = [[OUILookupTool alloc] init]; 101 | olt.delegate = aDelegate; 102 | 103 | [NSThread detachNewThreadSelector:@selector(fetchLocationForAccessPointInNewThread:) toTarget:olt withObject:ap]; 104 | return [olt autorelease]; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /Classes/SPSourceKeyboardTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceKeyboardTVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/16/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPSourceKeyboardTVC.h" 11 | 12 | 13 | @implementation SPSourceKeyboardTVC 14 | 15 | - (BOOL)caseInsensitiveString:(NSString *)s startsWithUnichar:(unichar)c { 16 | if(![s length]) return NO; 17 | 18 | unichar c1 = [[s lowercaseString] characterAtIndex:0]; 19 | unichar c2 = [[[NSString stringWithFormat:@"%c", c] lowercaseString] characterAtIndex:0]; 20 | return c1 == c2; 21 | } 22 | 23 | - (NSString *)sanitizeString:(NSString *)s { 24 | NSString *s2 = [s stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 25 | s2 = [s2 stringByTrimmingCharactersInSet:[NSCharacterSet controlCharacterSet]]; 26 | return [s2 stringByTrimmingCharactersInSet:[NSCharacterSet illegalCharacterSet]]; 27 | } 28 | 29 | - (NSArray *)wordsInDictionaryCacheFileAtPath:(NSString *)path { 30 | 31 | NSData *data = [NSData dataWithContentsOfFile:path]; 32 | if(!data) return nil; 33 | 34 | static const int BUFSIZE = 256; 35 | 36 | int length = [data length]; 37 | int len = 0; 38 | int pos = 0; 39 | NSRange range; 40 | char buf[BUFSIZE]; 41 | NSString *w = nil; 42 | 43 | NSMutableArray *words = [NSMutableArray array]; 44 | 45 | while(pos < length) { 46 | range = NSMakeRange(pos, MIN(BUFSIZE, length-pos)); 47 | [data getBytes:buf range:range]; 48 | len = strlen(buf); 49 | w = [[NSString alloc] initWithBytes:buf length:len encoding:NSUTF8StringEncoding]; 50 | if([w length]) { 51 | [words addObject:[self sanitizeString:w]]; 52 | } 53 | [w release]; 54 | pos += (len + 1); 55 | } 56 | 57 | return words; 58 | } 59 | 60 | - (void)loadData { 61 | if(contentsDictionaries) return; 62 | 63 | NSMutableSet *set = [NSMutableSet set]; 64 | 65 | NSString *dir = @"/var/mobile/Library/Keyboard/"; 66 | NSError *error = nil; 67 | NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dir error:&error]; 68 | 69 | if(dirContents == nil) { 70 | NSLog(@"-- error: %@", error); 71 | return; 72 | } 73 | 74 | for(NSString *filePath in dirContents) { 75 | if(![filePath hasSuffix:@".dat"]) continue; 76 | NSArray *a = [self wordsInDictionaryCacheFileAtPath:[dir stringByAppendingPathComponent:filePath]]; 77 | if(!a) continue; 78 | [set addObjectsFromArray:a]; 79 | } 80 | 81 | NSArray *words = [[set allObjects] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; 82 | 83 | NSMutableArray *letters = [NSMutableArray array]; 84 | NSMutableArray *letterWords = [[NSMutableArray alloc] init]; 85 | 86 | NSString *current = nil; 87 | 88 | for(NSString *w in words) { 89 | if([w length] == 0) continue; 90 | 91 | NSString *s = [[w substringToIndex:1] lowercaseString]; 92 | 93 | if([s isEqualToString:current]) { 94 | // w starts with current letter 95 | [letterWords addObject:w]; 96 | } else { 97 | // w start with new letter 98 | 99 | // add previous letterWords to letters 100 | if(current) { 101 | [letters addObject:[NSDictionary dictionaryWithObjectsAndKeys:letterWords, current, nil]]; 102 | } 103 | 104 | // update current 105 | current = s; 106 | 107 | // create new letterWords 108 | [letterWords release]; 109 | letterWords = [[NSMutableArray alloc] init]; 110 | [letterWords addObject:w]; 111 | } 112 | } 113 | 114 | if(!current) current = @""; 115 | 116 | [letters addObject:[NSDictionary dictionaryWithObjectsAndKeys:letterWords, current, nil]]; 117 | 118 | [letterWords release]; 119 | 120 | self.contentsDictionaries = letters; 121 | } 122 | 123 | #pragma mark UITableViewDataSource 124 | 125 | - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { 126 | NSMutableArray *a = [NSMutableArray array]; 127 | for(NSDictionary *d in contentsDictionaries) { 128 | [a addObject:[[d allKeys] lastObject]]; 129 | } 130 | return a; 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /EXIF/EXFMetaData.h: -------------------------------------------------------------------------------- 1 | /* 2 | * EXFMetaData.h 3 | * iphoneGeo 4 | * 5 | * Created by steve woodcock on 30/03/2008. 6 | * Copyright 2008. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | * 9 | * The EXFMetaData stores the EXIF Meta Data itself, as well as the meta data and bytes of the thumbnail image if there is one. 10 | * 11 | * 12 | */ 13 | 14 | #import "EXFTagDefinitionHolder.h" 15 | #import "EXFConstants.h" 16 | #import "EXFHandlers.h" 17 | 18 | 19 | @interface EXFMetaData : NSObject { 20 | 21 | // endian ordering for image 22 | BOOL bigEndianOrder; 23 | 24 | // Dictionary of special tag handlers 25 | NSMutableDictionary* keyedHandlers; 26 | 27 | // Dictionary of user supplied handlers 28 | NSMutableDictionary* userKeyedHandlers; 29 | 30 | // dictionary of parsed EXIF Data 31 | NSMutableDictionary* keyedTagValues; 32 | 33 | // Dictionary of parsed Thumbnail EXIF Data 34 | NSMutableDictionary* keyedThumbnailTagValues; 35 | 36 | // pointer to byte array of EXIF Block 37 | ByteArray* exif_ptr; 38 | 39 | // The NSByte array for the thumbnail data 40 | NSData* thumbnailBytes; 41 | 42 | // tag definitions 43 | EXFTagDefinitionHolder* tagDefinitions; 44 | 45 | // Image attributes outside EXIF 46 | int compression; 47 | int bitsPerPixel; 48 | int height; 49 | int width; 50 | int numComponents; 51 | 52 | // length of image 53 | CFIndex byteLength; 54 | } 55 | 56 | /* 57 | Add a user specified handler prior to parsing the data. Allows over-ride of existing behaviour or 58 | handling of tags that are not in the EXIF spec. 59 | 60 | The handler will throw an NSException if: 61 | 1) the Key is not a valid Number 62 | 2) The tag handler is nil 63 | 3) The tag handler does not conform to the EXFHandler protocol 64 | 4) The handler attempts to override one for the container tags that contains other tags 65 | 5) The handler does not conform to the optional part of the protocol if is being used to handle a tag that is not already defined. 66 | 6) The handler returns an invalid parent Id or tagformat if it supports the optional part of the protocol 67 | */ 68 | -(void) addHandler:(id) aTagHandler forKey:(NSNumber*) aKey; 69 | 70 | /* 71 | Remove a handler. Note this only removes user handlers and cannot be used to remove a built in handler 72 | */ 73 | -(void) removeHandler: (NSNumber*) aKey; 74 | 75 | /* 76 | Removes all user handlers. 77 | */ 78 | -(void) removeAllHandlers; 79 | 80 | 81 | // Returns a tag definition for a particular tag 82 | - (EXFTag*) tagDefinition: (NSNumber*)aTagId ; 83 | 84 | //returns all keys for parent id 85 | -(NSMutableArray*) tagDefinitionsForParent:(NSNumber*) parent withoutImmutable:(BOOL) includeImmutable ; 86 | 87 | // Gets the tag value from a parsed file (if any) 88 | - (id) tagValue: (NSNumber*)aTagId; 89 | 90 | 91 | // Gets the thumbnail tag value from a parsed file (if any) 92 | - (id) thumbnailTagValue: (NSNumber*)aTagId; 93 | 94 | 95 | -(void) addTagValue:(id)value forKey:(NSNumber*) atagKey; 96 | 97 | -(void) removeTagValue:(NSNumber*) atagKey; 98 | 99 | // returns the tag definitions for the EXIF Data 100 | @property (readonly,retain) NSDictionary* keyedTagDefinitions; 101 | 102 | // The parsed Exif tag values. 103 | @property (readonly,retain) NSMutableDictionary* keyedTagValues; 104 | 105 | // The parsed Exif thumbnail values 106 | @property (readonly,retain) NSMutableDictionary* keyedThumbnailTagValues; 107 | 108 | // The thumbnail bytes if any 109 | @property (readonly,retain) NSData* thumbnailBytes; 110 | 111 | // Compression value 112 | @property (readonly) int compression; 113 | 114 | // bits per pixel 115 | @property (readonly) int bitsPerPixel; 116 | 117 | // image height 118 | @property (readonly) int height; 119 | 120 | // image width 121 | @property (readonly) int width; 122 | 123 | // byte length 124 | @property (readonly) CFIndex byteLength; 125 | 126 | // byte order 127 | @property (readonly) BOOL bigEndianOrder; 128 | @end 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /EXIF/EXFJFIF.m: -------------------------------------------------------------------------------- 1 | // 2 | // EXFJFIF.m 3 | // iphone-test 4 | // 5 | // Created by steve woodcock on 24/03/2008. 6 | // Copyright 2008 __MyCompanyName__. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "EXFMutableMetaData.h" 11 | #import "EXFLogging.h" 12 | 13 | @implementation EXFJFIF 14 | 15 | @synthesize identifier; 16 | @synthesize version; 17 | @synthesize length; 18 | @synthesize resolutionX; 19 | @synthesize resolutionY; 20 | 21 | @synthesize thumbnailX; 22 | @synthesize thumbnailY; 23 | 24 | @synthesize thumbnail; 25 | @synthesize units; 26 | 27 | const NSString* JFIF_IDENTIFIER = @"JFIF\0"; 28 | const int JFIF_MIN_LENGTH =14; 29 | 30 | -(id) init{ 31 | if (self = [super init]) { 32 | self.identifier =nil; 33 | self.version =nil; 34 | self.thumbnail =nil; 35 | 36 | self.length =0; 37 | } 38 | return self; 39 | } 40 | 41 | -(void) dealloc{ 42 | self.identifier = nil; 43 | self.version =nil; 44 | self.thumbnail=nil; 45 | 46 | [super dealloc]; 47 | } 48 | 49 | - (void) parseJfif:(CFDataRef*) theJfifData{ 50 | 51 | CFIndex dataLen = CFDataGetLength(*theJfifData); 52 | 53 | // make sure the data len is big enough for the parsing 54 | 55 | if (dataLen < JFIF_MIN_LENGTH ) 56 | { 57 | Debug(@"Length for JFIF is too short at %i", dataLen); 58 | return; 59 | }else{ 60 | int strLen =[JFIF_IDENTIFIER length]; 61 | // get a pointer in the array 62 | UInt8* bytePtr = (UInt8 *) CFDataGetBytePtr(*theJfifData); 63 | 64 | 65 | // get the text identifier 66 | NSData* commentData = [NSData dataWithBytes:bytePtr length:strLen]; 67 | 68 | NSString* comments = [[NSString alloc] initWithBytes:[commentData bytes] length:strLen encoding:NSASCIIStringEncoding]; 69 | 70 | // if identifier is nil or not JFIF then it is some app specific thing that we can skip 71 | if (comments != nil && ([JFIF_IDENTIFIER compare: comments] == NSOrderedSame)){ 72 | 73 | self.length = dataLen; 74 | 75 | self.identifier =comments; 76 | 77 | // get the version 78 | UInt8 majorVersion = bytePtr[strLen]; 79 | UInt8 minorVersion = bytePtr[strLen+1]; 80 | NSString* ver = [[NSString alloc] initWithFormat:@"%x.%x",majorVersion, minorVersion]; 81 | self.version = ver; 82 | [ver release]; 83 | 84 | 85 | // get the units 86 | self.units = bytePtr[strLen+2]; 87 | 88 | //JFIF is always big endian 89 | 90 | 91 | 92 | self.resolutionX = ((bytePtr[strLen+3] << 8) | bytePtr[strLen+4]); 93 | 94 | self.resolutionY =((bytePtr[strLen+5] << 8) | bytePtr[strLen+6]); 95 | 96 | 97 | // get the thumbnail data 98 | 99 | self.thumbnailX = bytePtr[strLen+7]; 100 | self.thumbnailY = bytePtr[strLen+8]; 101 | 102 | if (self.thumbnailX !=0 && self.thumbnailY != 0){ 103 | // thumbnail is 3n where n = thumbnailX x thumnailY 104 | long thumbnailBytes = 3 * (self.thumbnailX * self.thumbnailY); 105 | 106 | // see if the data len is enough for the image 107 | if (thumbnailBytes == (dataLen -JFIF_MIN_LENGTH)){ 108 | NSData* thumbnailData = [NSData dataWithBytes: &bytePtr[JFIF_MIN_LENGTH] length:thumbnailBytes]; 109 | self.thumbnail = thumbnailData; 110 | }else{ 111 | Debug(@"Thumbnail bytes %i is not equal to data length remaining %i", thumbnailBytes,dataLen -JFIF_MIN_LENGTH); 112 | } 113 | } 114 | 115 | } 116 | // release our comments string 117 | [comments release]; 118 | } 119 | 120 | 121 | 122 | } 123 | 124 | 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /Classes/SPSourceLocationTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourceLocationTVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPSourceLocationTVC.h" 11 | #import 12 | #import "SPImageMapVC.h" 13 | #import "SPImageAnnotation.h" 14 | 15 | @implementation SPSourceLocationTVC 16 | 17 | @synthesize cities; 18 | //@synthesize geo; 19 | @synthesize geoString; 20 | @synthesize locString; 21 | @synthesize locDateString; 22 | @synthesize timezone; 23 | @synthesize cachedLocationFromMaps; 24 | 25 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 26 | if(indexPath.section == 0 && indexPath.row == 0 && cachedLocationFromMaps) { 27 | SPImageMapVC *mapVC = [[SPImageMapVC alloc] initWithNibName:@"SPImageMapVC" bundle:[NSBundle mainBundle]]; 28 | [self.navigationController pushViewController:mapVC animated:YES]; 29 | SPImageAnnotation *annotation = [SPImageAnnotation annotationWithCoordinate:cachedLocationFromMaps.coordinate date:nil path:nil]; 30 | if(annotation) 31 | [mapVC addAnnotation:annotation]; 32 | } 33 | } 34 | 35 | - (void)loadData { 36 | if(contentsDictionaries) return; 37 | 38 | NSString *path = @"/var/mobile/Library/Preferences/com.apple.Maps.plist"; 39 | NSDictionary *d = [NSDictionary dictionaryWithContentsOfFile:path]; 40 | NSData *data = [d valueForKey:@"UserLocation"]; 41 | CLLocation *loc = data ? [NSKeyedUnarchiver unarchiveObjectWithData:data] : nil; 42 | self.cachedLocationFromMaps = loc; 43 | self.locString = @""; 44 | self.locDateString = @""; 45 | if(loc) { 46 | self.locString = [NSString stringWithFormat:@"%f, %f", loc.coordinate.latitude, loc.coordinate.longitude]; 47 | self.locDateString = [NSString stringWithFormat:@"%@", loc.timestamp]; 48 | } 49 | 50 | path = @"/var/mobile/Library/Preferences/com.apple.preferences.datetime.plist"; 51 | d = [NSDictionary dictionaryWithContentsOfFile:path]; 52 | self.timezone = [NSString stringWithFormat:@"%@", [d valueForKey:@"timezone"]]; 53 | 54 | path = @"/var/mobile/Library/Preferences/com.apple.weather.plist"; 55 | d = [NSDictionary dictionaryWithContentsOfFile:path]; 56 | NSMutableArray *citiesNames = [NSMutableArray array]; 57 | for(NSDictionary *dict in [d valueForKey:@"Cities"]) { 58 | [citiesNames addObject:[dict objectForKey:@"Name"]]; 59 | } 60 | self.cities = citiesNames; 61 | 62 | self.contentsDictionaries = [NSArray arrayWithObjects: 63 | [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:locString], @"Location", nil], 64 | [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:locDateString], @"Location Date", nil], 65 | [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:timezone], @"Timezone", nil], 66 | [NSDictionary dictionaryWithObjectsAndKeys:cities, @"Weather Cities", nil], 67 | nil]; 68 | /* 69 | self.geo = [[[MKReverseGeocoder alloc] initWithCoordinate:loc.coordinate] autorelease]; 70 | geo.delegate = self; 71 | [geo start]; 72 | */ 73 | } 74 | 75 | - (void)dealloc { 76 | [items release]; 77 | // [geo release]; 78 | [geoString release]; 79 | [cachedLocationFromMaps release]; 80 | [super dealloc]; 81 | } 82 | /* 83 | #pragma mark MKReverseGeocoderDelegate 84 | 85 | - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark { 86 | self.geoString = [NSString stringWithFormat:@"%@ %@", placemark.locality, placemark.country]; 87 | 88 | self.contentsDictionaries = [NSArray arrayWithObjects: 89 | [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:[NSString stringWithFormat:@"%@ %@", locString, geoString]], @"Location", nil], 90 | [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:locDateString], @"Location Date", nil], 91 | [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:timezone], @"Timezone", nil], 92 | [NSDictionary dictionaryWithObjectsAndKeys:cities, @"Weather Cities", nil], 93 | nil]; 94 | 95 | [self.tableView reloadData]; 96 | } 97 | 98 | - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error { 99 | NSLog(@"-- Error: %@", [error description]); 100 | } 101 | */ 102 | @end 103 | -------------------------------------------------------------------------------- /FMDB/FMDatabaseAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.m 3 | // fmkit 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import "FMDatabase.h" 10 | #import "FMDatabaseAdditions.h" 11 | 12 | @implementation FMDatabase (FMDatabaseAdditions) 13 | 14 | #define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \ 15 | va_list args; \ 16 | va_start(args, query); \ 17 | FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orVAList:args]; \ 18 | va_end(args); \ 19 | if (![resultSet next]) { return (type)0; } \ 20 | type ret = [resultSet sel:0]; \ 21 | [resultSet close]; \ 22 | [resultSet setParentDB:nil]; \ 23 | return ret; 24 | 25 | 26 | - (NSString*)stringForQuery:(NSString*)query, ...; { 27 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex); 28 | } 29 | 30 | - (int)intForQuery:(NSString*)query, ...; { 31 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex); 32 | } 33 | 34 | - (long)longForQuery:(NSString*)query, ...; { 35 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex); 36 | } 37 | 38 | - (BOOL)boolForQuery:(NSString*)query, ...; { 39 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex); 40 | } 41 | 42 | - (double)doubleForQuery:(NSString*)query, ...; { 43 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex); 44 | } 45 | 46 | - (NSData*)dataForQuery:(NSString*)query, ...; { 47 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex); 48 | } 49 | 50 | - (NSDate*)dateForQuery:(NSString*)query, ...; { 51 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex); 52 | } 53 | 54 | 55 | //check if table exist in database (patch from OZLB) 56 | - (BOOL)tableExists:(NSString*)tableName { 57 | 58 | BOOL returnBool; 59 | //lower case table name 60 | tableName = [tableName lowercaseString]; 61 | //search in sqlite_master table if table exists 62 | FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName]; 63 | //if at least one next exists, table exists 64 | returnBool = [rs next]; 65 | //close and free object 66 | [rs close]; 67 | 68 | return returnBool; 69 | } 70 | 71 | //get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] 72 | //check if table exist in database (patch from OZLB) 73 | - (FMResultSet*)getSchema { 74 | 75 | //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] 76 | 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"]; 77 | 78 | return rs; 79 | } 80 | 81 | //get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] 82 | - (FMResultSet*)getTableSchema:(NSString*)tableName { 83 | 84 | //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] 85 | FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"PRAGMA table_info(%@)", tableName]]; 86 | 87 | return rs; 88 | } 89 | 90 | 91 | //check if column exist in table 92 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName { 93 | 94 | BOOL returnBool = NO; 95 | //lower case table name 96 | tableName = [tableName lowercaseString]; 97 | //lower case column name 98 | columnName = [columnName lowercaseString]; 99 | //get table schema 100 | FMResultSet *rs = [self getTableSchema: tableName]; 101 | //check if column is present in table schema 102 | while ([rs next]) { 103 | if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString: columnName]) { 104 | returnBool = YES; 105 | break; 106 | } 107 | } 108 | //close and free object 109 | [rs close]; 110 | 111 | return returnBool; 112 | } 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /JSON/SBJsonWriter.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Stig Brautaset. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without specific 16 | prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #import 31 | #import "SBJsonBase.h" 32 | 33 | /** 34 | @brief The JSON writer class. 35 | 36 | Objective-C types are mapped to JSON types in the following way: 37 | 38 | @li NSNull -> Null 39 | @li NSString -> String 40 | @li NSArray -> Array 41 | @li NSDictionary -> Object 42 | @li NSNumber (-initWithBool:) -> Boolean 43 | @li NSNumber -> Number 44 | 45 | In JSON the keys of an object must be strings. NSDictionary keys need 46 | not be, but attempting to convert an NSDictionary with non-string keys 47 | into JSON will throw an exception. 48 | 49 | NSNumber instances created with the +initWithBool: method are 50 | converted into the JSON boolean "true" and "false" values, and vice 51 | versa. Any other NSNumber instances are converted to a JSON number the 52 | way you would expect. 53 | 54 | */ 55 | @interface SBJsonWriter : SBJsonBase { 56 | 57 | @private 58 | BOOL sortKeys, humanReadable; 59 | } 60 | 61 | /** 62 | @brief Whether we are generating human-readable (multiline) JSON. 63 | 64 | Set whether or not to generate human-readable JSON. The default is NO, which produces 65 | JSON without any whitespace. (Except inside strings.) If set to YES, generates human-readable 66 | JSON with linebreaks after each array value and dictionary key/value pair, indented two 67 | spaces per nesting level. 68 | */ 69 | @property BOOL humanReadable; 70 | 71 | /** 72 | @brief Whether or not to sort the dictionary keys in the output. 73 | 74 | If this is set to YES, the dictionary keys in the JSON output will be in sorted order. 75 | (This is useful if you need to compare two structures, for example.) The default is NO. 76 | */ 77 | @property BOOL sortKeys; 78 | 79 | /** 80 | @brief Return JSON representation for the given object. 81 | 82 | Returns a string containing JSON representation of the passed in value, or nil on error. 83 | If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. 84 | 85 | @param value any instance that can be represented as JSON text. 86 | */ 87 | - (NSString*)stringWithObject:(id)value; 88 | 89 | /** 90 | @brief Return JSON representation for the given object. 91 | 92 | Returns an NSData object containing JSON represented as UTF8 text, or nil on error. 93 | 94 | @param value any instance that can be represented as JSON text. 95 | */ 96 | - (NSData*)dataWithObject:(id)value; 97 | 98 | /** 99 | @brief Return JSON representation (or fragment) for the given object. 100 | 101 | Returns a string containing JSON representation of the passed in value, or nil on error. 102 | If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. 103 | 104 | @param value any instance that can be represented as a JSON fragment 105 | @param error pointer to object to be populated with NSError on failure 106 | 107 | */- (NSString*)stringWithObject:(id)value 108 | error:(NSError**)error; 109 | 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /JSON/SBJsonStreamWriter.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, Stig Brautaset. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | Neither the name of the the author nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #import 34 | 35 | @class SBJsonStreamWriterStateMachine; 36 | 37 | /** 38 | @brief The Stream Writer class. 39 | 40 | SBJsonStreamWriter accepts various messages and writes JSON text to an 41 | NSOutputStream designated at iniatilisation time. 42 | 43 | A range of high-, mid- and low-level methods. You can mix and match calls 44 | to these. For example, you may want to call -writeArrayOpen to start an 45 | array and then repeatedly call -writeObject: with an object. 46 | 47 | In JSON the keys of an object must be strings. NSDictionary keys need 48 | not be, but attempting to convert an NSDictionary with non-string keys 49 | into JSON will result in an error. 50 | 51 | NSNumber instances created with the +initWithBool: method are 52 | converted into the JSON boolean "true" and "false" values, and vice 53 | versa. Any other NSNumber instances are converted to a JSON number the 54 | way you would expect. 55 | 56 | */ 57 | 58 | @interface SBJsonStreamWriter : NSObject { 59 | @private 60 | NSString *error; 61 | SBJsonStreamWriterStateMachine **states; 62 | NSOutputStream *stream; 63 | NSUInteger depth, maxDepth; 64 | BOOL sortKeys, humanReadable; 65 | } 66 | 67 | /** 68 | @brief The maximum recursing depth. 69 | 70 | Defaults to 512. If the input is nested deeper than this the input will be deemed to be 71 | malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can 72 | turn off this security feature by setting the maxDepth value to 0. 73 | */ 74 | @property NSUInteger maxDepth; 75 | 76 | /** 77 | @brief Whether we are generating human-readable (multiline) JSON. 78 | 79 | Set whether or not to generate human-readable JSON. The default is NO, which produces 80 | JSON without any whitespace between tokens. If set to YES, generates human-readable 81 | JSON with linebreaks after each array value and dictionary key/value pair, indented two 82 | spaces per nesting level. 83 | */ 84 | @property BOOL humanReadable; 85 | 86 | /** 87 | @brief Whether or not to sort the dictionary keys in the output. 88 | 89 | If this is set to YES, the dictionary keys in the JSON output will be in sorted order. 90 | (This is useful if you need to compare two structures, for example.) The default is NO. 91 | */ 92 | @property BOOL sortKeys; 93 | 94 | /** 95 | @brief Contains the error description after an error has occured. 96 | */ 97 | @property (copy, readonly) NSString *error; 98 | 99 | /** 100 | @brief Initialise a stream writer. 101 | 102 | You have to create an output stream first. You should not open/close the stream 103 | manually; this class takes care of that. 104 | */ 105 | - (id)initWithStream:(NSOutputStream*)stream; 106 | 107 | /** 108 | @brief Write an NSDictionary to the JSON stream. 109 | */ 110 | - (BOOL)writeObject:(NSDictionary*)dict; 111 | 112 | /** 113 | @brief Write an NSArray to the JSON stream. 114 | */ 115 | - (BOOL)writeArray:(NSArray *)array; 116 | 117 | /// Start writing an Object to the stream 118 | - (BOOL)writeObjectOpen; 119 | 120 | /// Close the current object being written 121 | - (BOOL)writeObjectClose; 122 | 123 | /// Start writing an Array to the stream 124 | - (BOOL)writeArrayOpen; 125 | 126 | /// Close the current Array being written 127 | - (BOOL)writeArrayClose; 128 | 129 | /// Write a null to the stream 130 | - (BOOL)writeNull; 131 | 132 | /// Write a boolean to the stream 133 | - (BOOL)writeBool:(BOOL)x; 134 | 135 | //- (BOOL)writeInteger:(long)l; 136 | //- (BOOL)writeDouble:(double)d; 137 | 138 | /// Write a Number to the stream 139 | - (BOOL)writeNumber:(NSNumber*)n; 140 | 141 | /// Write a String to the stream 142 | - (BOOL)writeString:(NSString*)s; 143 | 144 | @end 145 | -------------------------------------------------------------------------------- /Classes/SPSourcePhotosTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourcePhotosTVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import 11 | #import "SPSourcePhotosTVC.h" 12 | #import "UIImage+GPS.h" 13 | #import "SPImageMapVC.h" 14 | #import "SPImageVC.h" 15 | #import "SPImageAnnotation.h" 16 | 17 | @implementation SPSourcePhotosTVC 18 | 19 | @synthesize annotations; 20 | @synthesize coordinates; 21 | @synthesize mapVC; 22 | @synthesize imageVC; 23 | 24 | - (void)mapButtonClicked:(id)sender { 25 | NSArray *annotationsWithValidCoordinates = [annotations filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { 26 | SPImageAnnotation *annotation = (SPImageAnnotation *)evaluatedObject; 27 | return [annotation hasValidCoordinates]; 28 | }] ]; 29 | 30 | mapVC.annotations = annotationsWithValidCoordinates; 31 | 32 | [self.navigationController pushViewController:mapVC animated:YES]; 33 | } 34 | 35 | - (NSArray *)jpgPngPaths { 36 | NSMutableArray *a = [NSMutableArray array]; 37 | 38 | NSString *dirPath = @"/private/var/mobile/Media/PhotoStreamsData/"; 39 | NSFileManager *fm = [[NSFileManager alloc] init]; 40 | NSDirectoryEnumerator *dirEnum = [fm enumeratorAtPath:dirPath]; 41 | 42 | NSString *path = nil; 43 | while (path = [dirEnum nextObject]) { 44 | 45 | if([[path pathComponents] containsObject:@".MISC"]) continue; 46 | 47 | NSString *fullPath = [dirPath stringByAppendingPathComponent:path]; 48 | 49 | if([fm isReadableFileAtPath:fullPath] == NO) continue; 50 | 51 | NSString *ext = [fullPath pathExtension]; 52 | if([ext isEqualToString:@"JPG"] || [ext isEqualToString:@"PNG"]) { 53 | [a addObject:fullPath]; 54 | } 55 | } 56 | 57 | return a; 58 | } 59 | 60 | - (void)readPhotosInNewThread { 61 | 62 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 63 | 64 | NSArray *jpgPngPaths = [self jpgPngPaths]; 65 | 66 | NSEnumerator *e = [jpgPngPaths reverseObjectEnumerator]; 67 | 68 | NSAutoreleasePool *subpool = [[NSAutoreleasePool alloc] init]; 69 | 70 | NSString *s = nil; 71 | while(s = [e nextObject]) { 72 | [subpool release]; 73 | subpool = [[NSAutoreleasePool alloc] init]; 74 | 75 | CLLocationCoordinate2D coord = [UIImage coordinatesOfImageAtPath:s]; 76 | //if(coord.latitude == 0.0 && coord.longitude == 0.0) continue; 77 | 78 | NSNumber *lat = [NSNumber numberWithDouble:coord.latitude]; 79 | NSNumber *lon = [NSNumber numberWithDouble:coord.longitude]; 80 | [coordinates addObject:[NSArray arrayWithObjects:lat, lon, nil]]; 81 | 82 | NSString *coordString = (lat && lon) ? [NSString stringWithFormat:@"%@, %@", lat, lon] : nil; 83 | 84 | NSError *error = nil; 85 | NSDictionary *d = [[NSFileManager defaultManager] attributesOfItemAtPath:s error:&error]; 86 | if(!d) { 87 | NSLog(@"Error, can't read attributes of file at path %@, %@ %@", s, [error description], [error userInfo]); 88 | continue; 89 | } 90 | NSDate *date = [d fileModificationDate]; 91 | NSString *dateString = date ? [date description] : @""; 92 | 93 | SPImageAnnotation *annotation = [SPImageAnnotation annotationWithCoordinate:coord date:date path:s]; 94 | [annotations performSelectorOnMainThread:@selector(addObject:) withObject:annotation waitUntilDone:YES]; 95 | 96 | NSDictionary *cd = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:coordString] forKey:dateString]; 97 | [contentsDictionaries performSelectorOnMainThread:@selector(addObject:) withObject:cd waitUntilDone:YES]; 98 | 99 | [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; 100 | 101 | if([annotation hasValidCoordinates]) { 102 | [mapVC performSelectorOnMainThread:@selector(addAnnotation:) withObject:annotation waitUntilDone:YES]; 103 | } 104 | } 105 | 106 | [subpool release]; 107 | [pool release]; 108 | } 109 | 110 | - (void)loadData { 111 | 112 | if(contentsDictionaries) return; 113 | 114 | UIBarButtonItem *mapButton = [[UIBarButtonItem alloc] initWithTitle:@"Map" style:UIBarButtonItemStylePlain target:self action:@selector(mapButtonClicked:)]; 115 | super.navigationItem.rightBarButtonItem = mapButton; 116 | 117 | self.contentsDictionaries = [NSMutableArray array]; 118 | self.annotations = [NSMutableArray array]; 119 | 120 | [NSThread detachNewThreadSelector:@selector(readPhotosInNewThread) toTarget:self withObject:nil]; 121 | } 122 | 123 | - (void)dealloc { 124 | [annotations release]; 125 | [coordinates release]; 126 | [mapVC release]; 127 | [imageVC release]; 128 | [super dealloc]; 129 | } 130 | 131 | #pragma mark UITableViewDelegate 132 | 133 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 134 | 135 | if(indexPath.section >= [annotations count]) return; 136 | 137 | NSString *path = [[annotations objectAtIndex:indexPath.section] path]; 138 | 139 | NSString *imageName = [[path lastPathComponent] stringByDeletingPathExtension]; 140 | 141 | // NSString *thmPath = [NSString stringWithFormat:@"/var/mobile/Media/DCIM/110APPLE/.MISC/%@.THM", imageName]; 142 | 143 | imageVC.path = path; 144 | imageVC.title = imageName; 145 | [self.navigationController pushViewController:imageVC animated:YES]; 146 | } 147 | 148 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 149 | UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 150 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 151 | return cell; 152 | } 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /EXIF/EXFUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // EXFUtils.m 3 | // iphone-test 4 | // 5 | // Created by steve woodcock on 30/03/2008. 6 | // Copyright 2008 __MyCompanyName__. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "EXFUtils.h" 11 | #import "EXFConstants.h" 12 | 13 | @implementation EXFUtils 14 | 15 | /* Start of utility helper methods */ 16 | +(UInt32) read4Bytes:(UInt8**) bytePtr: (BOOL) bigEndianOrder 17 | { 18 | UInt8* ptr = *bytePtr; 19 | UInt32 val =0; 20 | if (bigEndianOrder) 21 | val= ((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]); 22 | else 23 | val = ((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]); 24 | return val; 25 | } 26 | 27 | 28 | 29 | +(SInt32) read4SignedBytes:(UInt8**) bytePtr: (BOOL) bigEndianOrder 30 | { 31 | UInt8* ptr = *bytePtr; 32 | SInt32 val =0; 33 | if (bigEndianOrder) 34 | val= ((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]); 35 | else 36 | val = ((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]); 37 | return val; 38 | } 39 | 40 | 41 | 42 | +(UInt16) read2Bytes:(UInt8**) bytePtr: (BOOL) bigEndianOrder 43 | { 44 | UInt8* ptr = *bytePtr; 45 | UInt16 val =0; 46 | 47 | if (bigEndianOrder){ 48 | 49 | val = ((ptr[0] << 8) | ptr[1]); 50 | }else{ 51 | val =((ptr[1] << 8) | ptr[0]); 52 | } 53 | return val; 54 | } 55 | 56 | +(SInt16) read2SignedBytes:(UInt8**) bytePtr: (BOOL) bigEndianOrder 57 | { 58 | UInt8* ptr = *bytePtr; 59 | SInt16 val =0; 60 | 61 | if (bigEndianOrder){ 62 | val = ((ptr[0] << 8) | ptr[1]); 63 | }else{ 64 | val =((ptr[1] << 8) | ptr[0]); 65 | } 66 | return val; 67 | } 68 | 69 | 70 | +(void) write4Bytes:(UInt8**) bytePtr: (id) value: (BOOL) bigEndianOrder{ 71 | UInt32 val = [((NSNumber*)value) unsignedLongValue]; 72 | 73 | UInt8* ptr = *bytePtr; 74 | 75 | if (bigEndianOrder){ 76 | ptr[0] = (UInt8) (val >> 24); 77 | ptr[1] = (UInt8) ( val >> 16); 78 | ptr[2] = (UInt8) (val >> 8); 79 | ptr[3] = (UInt8) (val); 80 | } 81 | else{ 82 | ptr[3] = (UInt8) (val >> 24); 83 | ptr[2] = (UInt8) (val >> 16); 84 | ptr[1] = (UInt8) (val >> 8); 85 | ptr[0] = (UInt8) (val ); 86 | } 87 | } 88 | 89 | +(void) write4SignedBytes:(UInt8**) bytePtr: (id) value: (BOOL) bigEndianOrder{ 90 | SInt32 val = [((NSNumber*)value) longValue]; 91 | 92 | UInt8* ptr = *bytePtr; 93 | 94 | if (bigEndianOrder){ 95 | ptr[0] = (UInt8) (val >> 24); 96 | ptr[1] = (UInt8) (val >> 16); 97 | ptr[2] = (UInt8) (val >> 8); 98 | ptr[3] = (UInt8) (val & 0xff); 99 | } 100 | else{ 101 | ptr[3] = (UInt8) (val >> 24); 102 | ptr[2] = (UInt8) (val >> 16); 103 | ptr[1] = (UInt8) (val >> 8); 104 | ptr[0] = (UInt8) (val & 0xff); 105 | } 106 | 107 | 108 | } 109 | 110 | +(void) write2Bytes:(UInt8**) bytePtr: (id) value:(BOOL) bigEndianOrder{ 111 | UInt16 val = [((NSNumber*)value) unsignedIntValue]; 112 | 113 | UInt8* ptr = *bytePtr; 114 | if (bigEndianOrder){ 115 | ptr[0] = (UInt8) (val >> 8); 116 | ptr[1] = (UInt8) (val & 0xff); 117 | ptr[2] = ptr[3] =0; 118 | } 119 | else{ 120 | ptr[1] = (UInt8) (val >> 8); 121 | ptr[0] = (UInt8) (val & 0xff); 122 | ptr[2] = ptr[3] =0; 123 | } 124 | 125 | } 126 | 127 | +(void) write1Byte:(UInt8**) bytePtr: (id) value:(BOOL) bigEndianOrder{ 128 | UInt16 val = [((NSNumber*)value) unsignedCharValue]; 129 | 130 | UInt8* ptr = *bytePtr; 131 | 132 | ptr[0] = (UInt8) (val & 0xff); 133 | ptr[1] = ptr[2] = ptr[3] =0; 134 | 135 | 136 | } 137 | 138 | +(void) write1SignedByte:(UInt8**) bytePtr: (id) value:(BOOL) bigEndianOrder{ 139 | UInt16 val = [((NSNumber*)value) intValue]; 140 | 141 | UInt8* ptr = *bytePtr; 142 | 143 | ptr[0] = (UInt8) (val & 0xff); 144 | ptr[1] = ptr[2] = ptr[3] =0; 145 | 146 | 147 | } 148 | 149 | +(void) write2SignedBytes:(UInt8**) bytePtr: (id) value: (BOOL) bigEndianOrder{ 150 | SInt16 val = [((NSNumber*)value) intValue]; 151 | UInt8* ptr = *bytePtr; 152 | 153 | if (bigEndianOrder){ 154 | ptr[0] = (UInt8) (val >> 8); 155 | ptr[1] = (UInt8) (val & 0xff); 156 | ptr[2] = ptr[3] =0; 157 | } 158 | else{ 159 | ptr[1] = (UInt8) (val >> 8); 160 | ptr[0] = (UInt8) (val & 0xff); 161 | ptr[2] = ptr[3] =0; 162 | } 163 | 164 | } 165 | 166 | +(NSString*)newStringFromBuffer:(UInt8**) ptr: (UInt32) byteCount: (NSStringEncoding) encoding{ 167 | 168 | NSString* result = [[NSString alloc] initWithBytes:*ptr length:byteCount encoding:encoding]; 169 | // Debug(@"Created string %@", result); 170 | return result; 171 | } 172 | 173 | +(void) appendRationalToData:( NSMutableData*) target: (NSNumber*) rational: (BOOL) bigEndianOrder { 174 | 175 | UInt8* bytes[4]; 176 | UInt8* bytePtr = (UInt8*)bytes; 177 | 178 | long temp[2] = {0.0L, 0.0L}; 179 | long* ptr = temp; 180 | [EXFUtils convertRationalToFraction:&ptr :rational]; 181 | 182 | [EXFUtils write4Bytes:&bytePtr :[NSNumber numberWithLong:temp[0]] :bigEndianOrder]; 183 | [target appendBytes:bytePtr length:4]; 184 | 185 | [EXFUtils write4Bytes:&bytePtr :[NSNumber numberWithLong:temp[1]] :bigEndianOrder]; 186 | [target appendBytes:bytePtr length:4]; 187 | } 188 | 189 | +(void) appendFractionToData:( NSMutableData*) target: (EXFraction*) fraction: (BOOL) bigEndianOrder { 190 | 191 | UInt8* bytes[4]; 192 | UInt8* bytePtr = (UInt8*)bytes; 193 | 194 | 195 | [EXFUtils write4Bytes:&bytePtr :[NSNumber numberWithLong:fraction.numerator] :bigEndianOrder]; 196 | [target appendBytes:bytePtr length:4]; 197 | 198 | [EXFUtils write4Bytes:&bytePtr :[NSNumber numberWithLong:fraction.denominator] :bigEndianOrder]; 199 | [target appendBytes:bytePtr length:4]; 200 | } 201 | 202 | +(long) ofr_gcd_euclid: (long) n: (long) m 203 | { 204 | /* 205 | Finds greatest divisor, d, of n and m: n%d==0, m%d==0 206 | Restate that as: n=n'*d, m=m'*d for some n', m',d; find d 207 | Note that if you have any numbers q,r such that q*m+r=n, then q*m+r=n'd --> r=(n'-q*m')d 208 | */ 209 | 210 | if (n < m) { 211 | long t = n; 212 | n = m; 213 | m = t; 214 | } 215 | for(;;) { 216 | // assert (n >= m); 217 | long r = n % m; 218 | if (r == 0) 219 | return m; /* n is a multiple of m */ 220 | n = m; 221 | m = r; 222 | } 223 | } 224 | 225 | 226 | 227 | +(void) convertRationalToFraction: (long**) numDenumArray: (NSNumber*) rational{ 228 | 229 | // see how many digits there are 230 | double originalNumber = [rational doubleValue]; 231 | double number = originalNumber; 232 | BOOL negative = FALSE; 233 | long long den =0; 234 | long long num =0; 235 | 236 | long* ptr = *numDenumArray; 237 | 238 | long long count =1; 239 | 240 | if (number <0){ 241 | negative = TRUE; 242 | 243 | } 244 | 245 | 246 | // we should now have number / thousands 247 | // now work out gcd; 248 | 249 | if (number == 0) { 250 | // set denominator to 1 to prevent divide by 0 issues 251 | den =1; 252 | } else if (number ==1){ 253 | // set all to 1 254 | den= num = 1; 255 | } else{ 256 | // count the number of digits 257 | while (number != ((long long)number)){ 258 | number *=10; 259 | count*=10; 260 | // overflow - restrict to 9 decimal places 261 | if (number <0 || count >=10000000){ 262 | count =1000000; 263 | number = (long long)(originalNumber * count); 264 | break; 265 | } 266 | } 267 | long gcd = [EXFUtils ofr_gcd_euclid: number: count]; 268 | num = number/gcd; 269 | den = count/gcd; 270 | } 271 | 272 | if (negative){ 273 | num = abs(num); 274 | } 275 | ptr[0] = num; 276 | ptr[1] = den; 277 | 278 | } 279 | 280 | 281 | @end 282 | -------------------------------------------------------------------------------- /Classes/SPSourcePhoneTVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPSourcePhoneTVC.m 3 | // SpyPhone 4 | // 5 | // Created by Nicolas Seriot on 11/15/09. 6 | // Copyright 2009. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | // 9 | 10 | #import "SPSourcePhoneTVC.h" 11 | #import "SPCell.h" 12 | #import 13 | #import "FMDatabase.h" 14 | #import "NSNumber+SP.h" 15 | #import 16 | #import 17 | 18 | @implementation SPSourcePhoneTVC 19 | 20 | @synthesize ICCID; 21 | //@synthesize IMEI; 22 | @synthesize IMSI; 23 | @synthesize phone; 24 | @synthesize UUID; 25 | @synthesize lastDialed; 26 | @synthesize lastContact; 27 | @synthesize lastForwardNumber; 28 | @synthesize callHistories; 29 | @synthesize prettyBytesSent; 30 | @synthesize prettyBytesReceived; 31 | 32 | - (NSString *)nameOfABPersonWithID:(NSUInteger)recordID { 33 | ABAddressBookRef addressBook = ABAddressBookCreate(); 34 | ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressBook, recordID); 35 | 36 | if(!person) { 37 | CFRelease(addressBook); 38 | return nil; 39 | } 40 | 41 | NSString *firstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); 42 | NSString *lastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty); 43 | 44 | NSString *fullName = nil; 45 | 46 | if(firstName && lastName) { 47 | fullName = [NSString stringWithFormat:@"%@ %@", firstName, lastName]; 48 | } else if (firstName) { 49 | fullName = [NSString stringWithString:firstName]; 50 | } else if (lastName) { 51 | fullName = [NSString stringWithString:lastName]; 52 | } 53 | 54 | [firstName release]; 55 | [lastName release]; 56 | CFRelease(addressBook); 57 | 58 | return fullName; 59 | } 60 | 61 | - (void)loadData { 62 | 63 | if(contentsDictionaries) return; 64 | 65 | NSString *path = @"/private/var/wireless/Library/Preferences/com.apple.commcenter.plist"; 66 | NSDictionary *d = [NSDictionary dictionaryWithContentsOfFile:path]; 67 | self.ICCID = [d valueForKey:@"ICCID"]; 68 | self.IMSI = [d valueForKey:@"IMSI"]; 69 | 70 | self.phone = [[NSUserDefaults standardUserDefaults] valueForKey:@"SBFormattedPhoneNumber"]; 71 | self.UUID = [[UIDevice currentDevice] uniqueIdentifier]; 72 | /* 73 | NSBundle *b = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/Message.framework"]; 74 | BOOL success = [b load]; 75 | if(success) { 76 | Class NetworkController = NSClassFromString(@"NetworkController"); 77 | id nc = [NetworkController sharedInstance]; 78 | if([nc respondsToSelector:@selector(IMEI)]) { 79 | self.IMEI = [nc IMEI]; 80 | } 81 | } 82 | if(!self.IMEI) self.IMEI = @""; 83 | */ 84 | path = @"/var/mobile/Library/Preferences/com.apple.mobilephone.settings.plist"; 85 | d = [NSDictionary dictionaryWithContentsOfFile:path]; 86 | 87 | NSString *callForwardingNumber = [d valueForKey:@"call-forwarding-number"]; 88 | self.lastForwardNumber = callForwardingNumber ? [NSString stringWithFormat:@"%@", callForwardingNumber] : nil; 89 | 90 | path = @"/var/mobile/Library/Preferences/com.apple.mobilephone.plist"; 91 | d = [NSDictionary dictionaryWithContentsOfFile:path]; 92 | NSString *s = [NSString stringWithFormat:@"%@", [d valueForKey:@"DialerSavedNumber"]]; 93 | self.lastDialed = [s length] == 0 ? nil : s; 94 | 95 | self.contentsDictionaries = [NSMutableArray array]; 96 | 97 | NSUInteger abId = [[d valueForKey:@"AddressBookLastDialedUid"] intValue]; 98 | NSString *fullName = [self nameOfABPersonWithID:abId]; 99 | self.lastContact = fullName; 100 | 101 | /**/ 102 | 103 | self.callHistories = [NSMutableArray array]; 104 | 105 | FMDatabase *db = [FMDatabase databaseWithPath:@"/private/var/wireless/Library/CallHistory/call_history.db"]; 106 | 107 | // NSLocale *usLocale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"] autorelease]; 108 | 109 | if([db open]) { 110 | FMResultSet *rs = [db executeQuery:@"select address, date, flags, duration from call order by date"]; 111 | while ([rs next]) { 112 | int dateInt = [rs intForColumn:@"date"]; 113 | NSDate *date = [NSDate dateWithTimeIntervalSince1970:dateInt]; 114 | NSDateFormatter *df = [[NSDateFormatter alloc] init]; 115 | [df setDateFormat:@"YYYY-MM-dd HH:mm"]; 116 | NSString *dateString = [df stringFromDate:date]; 117 | 118 | int flagsInt = [rs intForColumn:@"flags"]; 119 | NSString *flags = @"?"; 120 | switch (flagsInt) { 121 | case 4: flags = @"<-"; break; 122 | case 5: flags = @"->"; break; 123 | default: break; 124 | } 125 | 126 | int durationInt = [rs intForColumn:@"duration"]; 127 | NSString *duration = [NSString stringWithFormat:@"%d:%02d", durationInt / 60, durationInt % 60]; 128 | 129 | NSString *logLine = [NSString stringWithFormat:@"%@ %@ %@ (%@)", dateString, flags, [rs stringForColumn:@"address"], duration]; 130 | [callHistories addObject:logLine]; 131 | } 132 | [rs close]; 133 | 134 | rs = [db executeQuery:@"select bytes_rcvd, bytes_sent from data where pdp_ip = 0"]; 135 | while ([rs next]) { 136 | double bytes_sent = [rs doubleForColumn:@"bytes_sent"]; 137 | double bytes_rcvd = [rs doubleForColumn:@"bytes_rcvd"]; 138 | 139 | self.prettyBytesSent = [[NSNumber numberWithDouble:bytes_sent] prettyBytes]; 140 | self.prettyBytesReceived = [[NSNumber numberWithDouble:bytes_rcvd] prettyBytes]; 141 | } 142 | 143 | [rs close]; 144 | 145 | [db close]; 146 | } 147 | 148 | /**/ 149 | 150 | CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init]; 151 | CTCarrier *carrier = networkInfo.subscriberCellularProvider; 152 | [networkInfo release]; 153 | 154 | NSString *s1 = [NSString stringWithFormat:@"%@ %@", [carrier isoCountryCode], [carrier carrierName]]; 155 | NSString *s2 = [NSString stringWithFormat:@"country %@ network %@", [carrier mobileCountryCode], [carrier mobileNetworkCode]]; 156 | NSArray *carrierInfoArray = [NSArray arrayWithObjects:s1, s2, nil]; 157 | NSDictionary *carrierInfo = [NSDictionary dictionaryWithObjectsAndKeys:carrierInfoArray, @"Carrier Info", nil]; 158 | 159 | /**/ 160 | 161 | if(carrierInfo) { 162 | [self.contentsDictionaries addObject:carrierInfo]; 163 | } 164 | 165 | if(self.lastForwardNumber) { 166 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:self.lastForwardNumber], @"Call forwarding number", nil]; 167 | [self.contentsDictionaries addObject:dict]; 168 | } 169 | 170 | if(self.phone) { 171 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:self.phone], @"Phone number", nil]; 172 | [self.contentsDictionaries addObject:dict]; 173 | } 174 | 175 | if(self.lastContact) { 176 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:self.lastContact], @"Last contact called from list", nil]; 177 | [self.contentsDictionaries addObject:dict]; 178 | } 179 | 180 | if(self.lastDialed) { 181 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:self.lastDialed], @"Last dialed", nil]; 182 | [self.contentsDictionaries addObject:dict]; 183 | } 184 | 185 | if(self.ICCID) { 186 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:self.ICCID], @"ICCID (SIM card serial number)", nil]; 187 | [self.contentsDictionaries addObject:dict]; 188 | } 189 | 190 | if(self.IMSI) { 191 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:self.IMSI], @"IMSI (International Mobile Subscriber Identity)", nil]; 192 | [self.contentsDictionaries addObject:dict]; 193 | } 194 | 195 | if(self.UUID) { 196 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:self.UUID], @"Device UUID", nil]; 197 | [self.contentsDictionaries addObject:dict]; 198 | } 199 | 200 | if(prettyBytesSent) { 201 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:prettyBytesSent], @"Cellular Network - Bytes Sent", nil]; 202 | [self.contentsDictionaries addObject:dict]; 203 | } 204 | 205 | if(prettyBytesReceived) { 206 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:prettyBytesReceived], @"Cellular Network - Bytes Received", nil]; 207 | [self.contentsDictionaries addObject:dict]; 208 | } 209 | 210 | if(callHistories) { 211 | NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:callHistories, @"Call History", nil]; 212 | [self.contentsDictionaries addObject:dict]; 213 | } 214 | 215 | } 216 | 217 | - (void)didReceiveMemoryWarning { 218 | // Releases the view if it doesn't have a superview. 219 | [super didReceiveMemoryWarning]; 220 | 221 | // Release any cached data, images, etc that aren't in use. 222 | } 223 | 224 | - (void)dealloc { 225 | [ICCID release]; 226 | // [IMEI release]; 227 | [IMSI release]; 228 | [phone release]; 229 | [UUID release]; 230 | [lastForwardNumber release]; 231 | [lastDialed release]; 232 | [lastContact release]; 233 | [callHistories release]; 234 | [prettyBytesSent release]; 235 | [prettyBytesReceived release]; 236 | 237 | [super dealloc]; 238 | } 239 | 240 | @end 241 | -------------------------------------------------------------------------------- /Classes/TVOutManager_.m: -------------------------------------------------------------------------------- 1 | // 2 | // TVOutManager.m 3 | // TVOutOS4Test 4 | // 5 | // Created by Rob Terrell (rob@touchcentric.com) on 8/16/10. 6 | // Copyright 2010 TouchCentric LLC. All rights reserved. 7 | // 8 | // http://www.touchcentric.com/blog/ 9 | 10 | 11 | #import 12 | #import "TVOutManager.h" 13 | 14 | #define kFPS 15 15 | #define kUseBackgroundThread NO 16 | 17 | // 18 | // Warning: once again, we can't use UIGetScreenImage for shipping apps (as of late July 2010) 19 | // however, it gives a better result (shows the status bar, UIKit transitions, better fps) so 20 | // you may want to use it for non-app-store builds (i.e. private demo, trade show build, etc.) 21 | // Just uncomment both lines below. 22 | // 23 | #define USE_UIGETSCREENIMAGE 24 | CGImageRef UIGetScreenImage(); 25 | // 26 | 27 | @implementation TVOutManager 28 | 29 | @synthesize tvSafeMode; 30 | 31 | + (TVOutManager *)sharedInstance 32 | { 33 | static TVOutManager *sharedInstance; 34 | 35 | @synchronized(self) 36 | { 37 | if (!sharedInstance) 38 | sharedInstance = [[TVOutManager alloc] init]; 39 | return sharedInstance; 40 | } 41 | } 42 | 43 | 44 | - (id) init 45 | { 46 | self = [super init]; 47 | if (self) { 48 | // can't imagine why, but just in case 49 | [[NSNotificationCenter defaultCenter] removeObserver: self]; 50 | 51 | // catch screen-related notifications 52 | [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(screenDidConnectNotification:) name: UIScreenDidConnectNotification object: nil]; 53 | [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(screenDidDisconnectNotification:) name: UIScreenDidDisconnectNotification object: nil]; 54 | [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(screenModeDidChangeNotification:) name: UIScreenModeDidChangeNotification object: nil]; 55 | 56 | // catch orientation notifications 57 | [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 58 | [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object: nil]; 59 | } 60 | return self; 61 | } 62 | 63 | -(void) dealloc 64 | { 65 | [[NSNotificationCenter defaultCenter] removeObserver: self]; 66 | [super dealloc]; 67 | } 68 | 69 | -(void) setTvSafeMode:(BOOL) val 70 | { 71 | if (tvoutWindow) { 72 | if (tvSafeMode == YES && val == NO) { 73 | [UIView beginAnimations:@"zoomIn" context: nil]; 74 | tvoutWindow.transform = CGAffineTransformScale(tvoutWindow.transform, 1.25, 1.25); 75 | [UIView commitAnimations]; 76 | [tvoutWindow setNeedsDisplay]; 77 | } 78 | else if (tvSafeMode == NO && val == YES) { 79 | [UIView beginAnimations:@"zoomOut" context: nil]; 80 | tvoutWindow.transform = CGAffineTransformScale(tvoutWindow.transform, .8, .8); 81 | [UIView commitAnimations]; 82 | [tvoutWindow setNeedsDisplay]; 83 | } 84 | } 85 | tvSafeMode = val; 86 | } 87 | 88 | - (void) startTVOut 89 | { 90 | // you need to have a main window already open when you call start 91 | if ([[UIApplication sharedApplication] keyWindow] == nil) return; 92 | 93 | NSArray* screens = [UIScreen screens]; 94 | if ([screens count] <= 1) { 95 | NSLog(@"TVOutManager: startTVOut failed (no external screens detected)"); 96 | return; 97 | } 98 | 99 | if (tvoutWindow) { 100 | // tvoutWindow already exists, so this is a re-connected cable, or a mode chane 101 | [tvoutWindow release], tvoutWindow = nil; 102 | } 103 | 104 | if (!tvoutWindow) { 105 | deviceWindow = [[UIApplication sharedApplication] keyWindow]; 106 | 107 | CGSize max; 108 | max.width = 0; 109 | max.height = 0; 110 | UIScreenMode *maxScreenMode = nil; 111 | UIScreen *external = [[UIScreen screens] objectAtIndex: 1]; 112 | for(int i = 0; i < [[external availableModes] count]; i++) 113 | { 114 | UIScreenMode *current = [[[[UIScreen screens] objectAtIndex:1] availableModes] objectAtIndex: i]; 115 | if (current.size.width > max.width) 116 | { 117 | max = current.size; 118 | maxScreenMode = current; 119 | } 120 | } 121 | external.currentMode = maxScreenMode; 122 | 123 | tvoutWindow = [[UIWindow alloc] initWithFrame: CGRectMake(0,0, max.width, max.height)]; 124 | tvoutWindow.userInteractionEnabled = NO; 125 | tvoutWindow.screen = external; 126 | 127 | // size the mirrorView to expand to fit the external screen 128 | CGRect mirrorRect = [[UIScreen mainScreen] bounds]; 129 | CGFloat horiz = max.width / CGRectGetWidth(mirrorRect); 130 | CGFloat vert = max.height / CGRectGetHeight(mirrorRect); 131 | CGFloat bigScale = horiz < vert ? horiz : vert; 132 | mirrorRect = CGRectMake(mirrorRect.origin.x, mirrorRect.origin.y, mirrorRect.size.width * bigScale, mirrorRect.size.height * bigScale); 133 | 134 | mirrorView = [[UIImageView alloc] initWithFrame: mirrorRect]; 135 | mirrorView.center = tvoutWindow.center; 136 | 137 | // TV safe area -- scale the window by 20% -- for composite / component, not needed for VGA output 138 | if (tvSafeMode) tvoutWindow.transform = CGAffineTransformScale(tvoutWindow.transform, .8, .8); 139 | [tvoutWindow addSubview: mirrorView]; 140 | [mirrorView release]; 141 | [tvoutWindow makeKeyAndVisible]; 142 | tvoutWindow.hidden = NO; 143 | tvoutWindow.backgroundColor = [UIColor darkGrayColor]; 144 | 145 | // orient the view properly 146 | if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft) { 147 | mirrorView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * 1.5); 148 | } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight) { 149 | mirrorView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * -1.5); 150 | } 151 | startingTransform = mirrorView.transform; 152 | 153 | [deviceWindow makeKeyAndVisible]; 154 | 155 | [self updateTVOut]; 156 | 157 | if (kUseBackgroundThread) [NSThread detachNewThreadSelector:@selector(updateLoop) toTarget:self withObject:nil]; 158 | else { 159 | updateTimer = [NSTimer scheduledTimerWithTimeInterval: (1.0/kFPS) target: self selector: @selector(updateTVOut) userInfo: nil repeats: YES]; 160 | [updateTimer retain]; 161 | } 162 | 163 | } 164 | } 165 | 166 | - (void) stopTVOut; 167 | { 168 | done = YES; 169 | if (updateTimer) { 170 | [updateTimer invalidate]; 171 | [updateTimer release], updateTimer = nil; 172 | } 173 | if (tvoutWindow) { 174 | [tvoutWindow release], tvoutWindow = nil; 175 | mirrorView = nil; 176 | } 177 | } 178 | 179 | - (void) updateTVOut; 180 | { 181 | #ifdef USE_UIGETSCREENIMAGE 182 | // UIGetScreenImage() is no longer allowed in shipping apps, see https://devforums.apple.com/thread/61338 183 | // however, it's better for demos, since it includes the status bar and captures animated transitions 184 | 185 | CGImageRef cgScreen = UIGetScreenImage(); 186 | if (cgScreen) image = [UIImage imageWithCGImage:cgScreen]; 187 | mirrorView.image = image; 188 | CGImageRelease(cgScreen); 189 | 190 | #else 191 | 192 | // from http://developer.apple.com/iphone/library/qa/qa2010/qa1703.html 193 | // bonus, this works in the simulator; sadly, it doesn't capture the status bar 194 | // 195 | // if you are making an OpenGL app, use UIGetScreenImage() above or switch the 196 | // following code to match Apple's sample at http://developer.apple.com/iphone/library/qa/qa2010/qa1704.html 197 | // note that you'll need to pass in a reference to your eaglview to get that to work. 198 | 199 | UIGraphicsBeginImageContext(deviceWindow.bounds.size); 200 | CGContextRef context = UIGraphicsGetCurrentContext(); 201 | 202 | // get every window's contents (i.e. so you can see alerts, ads, etc.) 203 | for (UIWindow *window in [[UIApplication sharedApplication] windows]) 204 | { 205 | if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen]) 206 | { 207 | CGContextSaveGState(context); 208 | CGContextTranslateCTM(context, [window center].x, [window center].y); 209 | CGContextConcatCTM(context, [window transform]); 210 | CGContextTranslateCTM(context, -[window bounds].size.width * window.layer.anchorPoint.x, -[window bounds].size.height * window.layer.anchorPoint.y); 211 | [[window layer] renderInContext:context]; 212 | CGContextRestoreGState(context); 213 | } 214 | } 215 | image = UIGraphicsGetImageFromCurrentImageContext(); 216 | UIGraphicsEndImageContext(); 217 | mirrorView.image = image; 218 | 219 | #endif 220 | } 221 | 222 | 223 | - (void)updateLoop; 224 | { 225 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 226 | done = NO; 227 | 228 | while ( ! done ) 229 | { 230 | [self performSelectorOnMainThread:@selector(updateTVOut) withObject:nil waitUntilDone:NO]; 231 | [NSThread sleepForTimeInterval: (1.0/kFPS) ]; 232 | } 233 | [pool release]; 234 | } 235 | 236 | -(void) screenDidConnectNotification: (NSNotification*) notification 237 | { 238 | NSLog(@"Screen connected: %@", [notification object]); 239 | [self startTVOut]; 240 | } 241 | 242 | -(void) screenDidDisconnectNotification: (NSNotification*) notification 243 | { 244 | NSLog(@"Screen disconnected: %@", [notification object]); 245 | [self stopTVOut]; 246 | } 247 | 248 | -(void) screenModeDidChangeNotification: (NSNotification*) notification 249 | { 250 | NSLog(@"Screen mode changed: %@", [notification object]); 251 | [self startTVOut]; 252 | } 253 | 254 | -(void) deviceOrientationDidChange: (NSNotification*) notification 255 | { 256 | if (mirrorView == nil || done == YES) return; 257 | if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft) { 258 | [UIView beginAnimations:@"turnLeft" context:nil]; 259 | mirrorView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * 1.5); 260 | [UIView commitAnimations]; 261 | } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight) { 262 | [UIView beginAnimations:@"turnRight" context:nil]; 263 | mirrorView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * -1.5); 264 | [UIView commitAnimations]; 265 | } else { 266 | [UIView beginAnimations:@"turnUp" context:nil]; 267 | mirrorView.transform = CGAffineTransformIdentity; 268 | [UIView commitAnimations]; 269 | } 270 | } 271 | 272 | @end 273 | -------------------------------------------------------------------------------- /EXIF/EXFConstants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * EXFConstants.h 3 | * 4 | * 5 | * Created by steve woodcock on 30/03/2008. 6 | * Copyright 2008. 7 | // Licensed under GPL 2.0 http://www.gnu.org/licenses/gpl-2.0.txt 8 | * 9 | * Constants used in the EXIF library. 10 | * 11 | * 12 | */ 13 | /*! 14 | @header EXFConstants.h 15 | @abstract EXFConstants.h provides the definition of commonly used enums, definitions and basic interfaces. 16 | */ 17 | 18 | /* 19 | Type defs for some of the internal definitions 20 | */ 21 | /*! 22 | @typedef ByteArray 23 | */ 24 | typedef UInt8 ByteArray; 25 | 26 | /*! 27 | @typedef EXFTagId 28 | @discussion The data type for tag ids. 29 | */ 30 | typedef UInt16 EXFTagId; 31 | 32 | /*! 33 | @enum EXFDataType 34 | @abstract The possible types that an EXIF tag data can be specified as. 35 | @discussion These are the only legal types to be used in the EXFTagDefinition to determine the type of data to be read/written and the number 36 | of bytes that each data type will then occupy. 37 | */ 38 | enum EXFDataType { 39 | FMT_BYTE = 1, 40 | FMT_STRING = 2, 41 | FMT_USHORT = 3, 42 | FMT_ULONG = 4, 43 | FMT_URATIONAL = 5, 44 | FMT_SBYTE = 6, 45 | FMT_UNDEFINED = 7, 46 | FMT_SSHORT = 8, 47 | FMT_SLONG = 9, 48 | FMT_SRATIONAL =10, 49 | FMT_SINGLE =11, 50 | FMT_DOUBLE =12 51 | }; 52 | 53 | /*! 54 | @typedef EXFDataType 55 | */ 56 | 57 | typedef enum EXFDataType EXFDataType; 58 | 59 | 60 | /* 61 | EXF Tag Ids 62 | 63 | */ 64 | #define EXIF_ImageWidth 0x0100 65 | #define EXIF_ImageLength 0x0101 66 | #define EXIF_BitsPerSample 0x0102 67 | #define EXIF_Compression 0x0103 68 | #define EXIF_PhotometricInterpretation 0x0106 69 | #define EXIF_ImageDescription 0x010e 70 | #define EXIF_Make 0x010f 71 | #define EXIF_Model 0x0110 72 | #define EXIF_StripOffsets 0x0111 73 | #define EXIF_Orientation 0x0112 74 | #define EXIF_SamplesPerPixel 0x0115 75 | #define EXIF_RowsPerStrip 0x0116 76 | #define EXIF_StripByteCounts 0x0117 77 | #define EXIF_XResolution 0x011a 78 | #define EXIF_YResolution 0x011b 79 | #define EXIF_PlanarConfiguration 0x011c 80 | #define EXIF_ResolutionUnit 0x0128 81 | #define EXIF_Software 0x0131 82 | #define EXIF_DateTime 0x0132 83 | #define EXIF_Artist 0x013b 84 | #define EXIF_HostComputer 0x013c 85 | #define EXIF_Predictor 0x013d 86 | #define EXIF_WhitePoint 0x013e 87 | #define EXIF_PrimaryChromaticities 0x013f 88 | #define EXIF_JPEGInterchangeFormat 0x0201 89 | #define EXIF_JPEGInterchangeFormatLength 0x0202 90 | #define EXIF_YCbCrCoefficients 0x0211 91 | #define EXIF_YCbCrSubSampling 0x0212 92 | #define EXIF_YCbCrPositioning 0x0213 93 | #define EXIF_ReferenceBlackWhite 0x0214 94 | #define EXIF_Copyright 0x8298 95 | #define EXIF_Exif 0x8769 96 | #define EXIF_GPS 0x8825 97 | #define EXIF_SpectralSensitivity 0x8824 98 | #define EXIF_ExposureProgram 0x8822 99 | #define EXIF_ISOSpeedratings 0x8827 100 | #define EXIF_ExposureTime 0x829a 101 | #define EXIF_FNumber 0x829d 102 | #define EXIF_ExifVersion 0x9000 103 | #define EXIF_DateTimeOriginal 0x9003 104 | #define EXIF_DateTimeDigitized 0x9004 105 | #define EXIF_ComponentsConfiguration 0x9101 106 | #define EXIF_CompressedBitsPerPixel 0x9102 107 | #define EXIF_ShutterSpeedValue 0x9201 108 | #define EXIF_ApertureValue 0x9202 109 | #define EXIF_BrightnessValue 0x9203 110 | #define EXIF_ExposureBiasValue 0x9204 111 | #define EXIF_MaxApertureRatioValue 0x9205 112 | #define EXIF_SubjectDistance 0x9206 113 | #define EXIF_MeteringMode 0x9207 114 | #define EXIF_LightSource 0x9208 115 | #define EXIF_Flash 0x9209 116 | #define EXIF_FocalLength 0x920a 117 | #define EXIF_MakerNote 0x927c 118 | #define EXIF_UserComment 0x9286 119 | #define EXIF_SubSecTime 0x9290 120 | #define EXIF_SubSecTimeOriginal 0x9291 121 | #define EXIF_SubSecTimeDigitized 0x9292 122 | #define EXIF_FileSource 0xa300 123 | #define EXIF_SceneType 0xa301 124 | #define EXIF_CFAPattern 0xa302 125 | #define EXIF_FlashpixVersion 0xa000 126 | #define EXIF_ColorSpace 0xa001 127 | #define EXIF_PixelXDimension 0xa002 128 | #define EXIF_PixelYDimension 0xa003 129 | #define EXIF_FocalPlaneXResolution 0xa20e 130 | #define EXIF_FocalPlaneYResolution 0xa20f 131 | #define EXIF_FocalPlaneResolutionUnit 0xa210 132 | #define EXIF_SubjectLocation 0xa214 133 | #define EXIF_ExposureIndex 0xa215 134 | #define EXIF_SensingMethod 0xa217 135 | #define EXIF_CustomRendered 0xa401 136 | #define EXIF_ExposureMode 0xa402 137 | #define EXIF_WhiteBalance 0xa403 138 | #define EXIF_DigitalZoomRatio 0xa404 139 | #define EXIF_FocalLengthIn35mmFilm 0xa405 140 | #define EXIF_SceneCaptureType 0xa406 141 | #define EXIF_GainControl 0xa407 142 | #define EXIF_Contrast 0xa408 143 | #define EXIF_Saturation 0xa409 144 | #define EXIF_Sharpness 0xa40a 145 | #define EXIF_DeviceSettingDescription 0xa40b 146 | #define EXIF_SubjectDistanceRange 0xa40c 147 | #define EXIF_Gamma 0xa500 148 | #define EXIF_GPSVersion 0x0000 149 | #define EXIF_GPSLatitudeRef 0x0001 150 | #define EXIF_GPSLatitude 0x0002 151 | #define EXIF_GPSLongitudeRef 0x0003 152 | #define EXIF_GPSLongitude 0x0004 153 | #define EXIF_GPSAltitudeRef 0x0005 154 | #define EXIF_GPSAltitude 0x0006 155 | #define EXIF_GPSTimeStamp 0x0007 156 | #define EXIF_GPSSatellites 0x0008 157 | #define EXIF_GPSStatus 0x0009 158 | #define EXIF_GPSMeasureMode 0x000a 159 | #define EXIF_GPSDOP 0x000b 160 | #define EXIF_GPSSpeedRef 0x000c 161 | #define EXIF_GPSSpeed 0x000d 162 | #define EXIF_GPSTrackRef 0x000e 163 | #define EXIF_GPSTrack 0x000f 164 | #define EXIF_GPSImgDirectionRef 0x0010 165 | #define EXIF_GPSImgDirection 0x0011 166 | #define EXIF_GPSMapDatum 0x0012 167 | #define EXIF_GPSDestLatitudeRef 0x0013 168 | #define EXIF_GPSDestLatitude 0x0014 169 | #define EXIF_GPSDestLongitudeRef 0x0015 170 | #define EXIF_GPSDestLongitude 0x0016 171 | #define EXIF_GPSDestBearingRef 0x0017 172 | #define EXIF_GPSDestBearing 0x0018 173 | #define EXIF_GPSDestDistanceRef 0x0019 174 | #define EXIF_GPSDestDistance 0x001a 175 | 176 | 177 | 178 | 179 | /*! 180 | @class EXFraction 181 | @abstract A simple fraction class used to store all rational data types 182 | @discussion The fraction class is used to avoid precision issues when converting from the fraction format stored 183 | in the JPEG image. 184 | The image data is stored as two longs (numerator and denominator) 185 | */ 186 | 187 | @interface EXFraction: NSObject { 188 | 189 | long numerator; 190 | long denominator; 191 | } 192 | 193 | /*! 194 | @method initWith 195 | @abstract initialises the EXFraction with a numerator and denominator 196 | 197 | */ 198 | -(id) initWith: (long) numerator: (long) denominator; 199 | 200 | /*! 201 | @property numerator 202 | @abstract the numerator part of the fraction 203 | 204 | */ 205 | @property (readonly) long numerator; 206 | 207 | /*! 208 | @property denominator 209 | @abstract the denominator part of the fraction 210 | 211 | */ 212 | @property (readonly) long denominator; 213 | 214 | /*! 215 | @method description 216 | @abstract Returns a String representing the double format of the fraction. 217 | @discussion If a true representation of the Fraction is required use the accessor methods to retrieve the two 218 | longs and construct the required format. 219 | 220 | */ 221 | -(NSString*) description; 222 | 223 | @end 224 | 225 | 226 | /*! 227 | @class EXFTag 228 | @abstract Definition data of an EXF Tag 229 | @discussion The EXFTag consists of an tagId, dataType, shortName, parentTagId, whether it is user editable and the number of 230 | components that each tag consists of. 231 | 232 | The dataType can only be one of the valid EXFDataType enum values. 233 | The shortName is as specified in the EXF specification. If localised or more user readable names are required you should use these 234 | as the key values to the localised form. 235 | The parentTagId shows the hierarchical parent Tag of each EXFTag. This is required in order to work out which directory or subdirectory 236 | a tag value should be inserted into. 237 | Editable tags are those that can be altered or add by users of the library. Attempting to alter a non-writable tag will result in an exception. 238 | Components defines the number of instances of each data type. As each data type is a certain number of bytes the actual byte size occupied 239 | for each tag is components * dataType size. 240 | For more detail see the EXF specification http://www.exif.org/Exif2-2.PDF 241 | 242 | */ 243 | 244 | @interface EXFTag : NSObject { 245 | 246 | 247 | EXFTagId tagId; 248 | EXFDataType dataType; 249 | int parentTagId; 250 | NSString* name; 251 | BOOL editable; 252 | int components; 253 | 254 | } 255 | 256 | /*! 257 | @method initWith 258 | */ 259 | 260 | -(id) initWith: (EXFTagId) aTagId: (EXFDataType)aDataType: (NSString*) aName: (int) parentTagId: (BOOL)editable: (int) components; 261 | 262 | 263 | @property (readonly) EXFTagId tagId; 264 | @property (readonly) EXFDataType dataType; 265 | @property (readonly, retain) NSString* name; 266 | @property (readonly) int parentTagId; 267 | @property (readonly) BOOL editable; 268 | @property (readonly) int components; 269 | 270 | 271 | @end 272 | 273 | -------------------------------------------------------------------------------- /Classes/TVOutManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // TVOutManager.m 3 | // TVOutOS4Test 4 | // 5 | // Created by Rob Terrell (rob@touchcentric.com) on 8/16/10. 6 | // Copyright 2010 TouchCentric LLC. All rights reserved. 7 | // 8 | // http://www.touchcentric.com/blog/ 9 | 10 | // marco modifications 11 | // device orientation 12 | // display link sugegstion from github 13 | // CALayer 14 | // USE_UIGETSCREENIMAGE is defined 15 | // kFPS set to 30 16 | // commented NSLog 17 | 18 | 19 | #import 20 | 21 | 22 | #import "TVOutManager.h" 23 | 24 | #define USE_LAYER 25 | #define kFPS 30 26 | 27 | #define MethodBackgroundThread 0 28 | #define MethodDisplayLink 1 29 | #define MethodTimer 2 30 | 31 | #define SynchronizationMethod MethodDisplayLink 32 | 33 | // 34 | // Warning: once again, we can't use UIGetScreenImage for shipping apps (as of late July 2010) 35 | // however, it gives a better result (shows the status bar, UIKit transitions, better fps) so 36 | // you may want to use it for non-app-store builds (i.e. private demo, trade show build, etc.) 37 | // Just uncomment both lines below. 38 | // 39 | #define USE_UIGETSCREENIMAGE 40 | CGImageRef UIGetScreenImage(); 41 | // 42 | 43 | @implementation TVOutManager 44 | 45 | @synthesize tvSafeMode; 46 | 47 | + (TVOutManager *)sharedInstance 48 | { 49 | static TVOutManager *sharedInstance; 50 | 51 | @synchronized(self) 52 | { 53 | if (!sharedInstance) 54 | sharedInstance = [[TVOutManager alloc] init]; 55 | return sharedInstance; 56 | } 57 | } 58 | 59 | 60 | - (id) init 61 | { 62 | self = [super init]; 63 | // catch screen-related notifications 64 | [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(screenDidConnectNotification:) name: UIScreenDidConnectNotification object: nil]; 65 | [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(screenDidDisconnectNotification:) name: UIScreenDidDisconnectNotification object: nil]; 66 | [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(screenModeDidChangeNotification:) name: UIScreenModeDidChangeNotification object: nil]; 67 | 68 | // catch orientation notifications 69 | [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 70 | [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object: nil]; 71 | return self; 72 | } 73 | 74 | -(void) dealloc 75 | { 76 | [[NSNotificationCenter defaultCenter] removeObserver: self]; 77 | [super dealloc]; 78 | } 79 | 80 | -(void) setTvSafeMode:(BOOL) val 81 | { 82 | if (tvoutWindow) { 83 | if (tvSafeMode == YES && val == NO) { 84 | [UIView beginAnimations:@"zoomIn" context: nil]; 85 | tvoutWindow.transform = CGAffineTransformScale(tvoutWindow.transform, 1.25, 1.25); 86 | [UIView commitAnimations]; 87 | [tvoutWindow setNeedsDisplay]; 88 | } 89 | else if (tvSafeMode == NO && val == YES) { 90 | [UIView beginAnimations:@"zoomOut" context: nil]; 91 | tvoutWindow.transform = CGAffineTransformScale(tvoutWindow.transform, .8, .8); 92 | [UIView commitAnimations]; 93 | [tvoutWindow setNeedsDisplay]; 94 | } 95 | } 96 | tvSafeMode = val; 97 | } 98 | 99 | - (void) startTVOut 100 | { 101 | // you need to have a main window already open when you call start 102 | if ([[UIApplication sharedApplication] keyWindow] == nil) return; 103 | 104 | NSArray* screens = [UIScreen screens]; 105 | if ([screens count] <= 1) { 106 | // NSLog(@"TVOutManager: startTVOut failed (no external screens detected)"); 107 | return; 108 | } 109 | 110 | if (tvoutWindow) { 111 | // tvoutWindow already exists, so this is a re-connected cable, or a mode chane 112 | [tvoutWindow release], tvoutWindow = nil; 113 | } 114 | 115 | if (!tvoutWindow) { 116 | deviceWindow = [[UIApplication sharedApplication] keyWindow]; 117 | 118 | CGSize max; 119 | max.width = 0; 120 | max.height = 0; 121 | UIScreenMode *maxScreenMode = nil; 122 | UIScreen *external = [[UIScreen screens] objectAtIndex: 1]; 123 | for(int i = 0; i < [[external availableModes] count]; i++) 124 | { 125 | UIScreenMode *current = [[[[UIScreen screens] objectAtIndex:1] availableModes] objectAtIndex: i]; 126 | if (current.size.width > max.width) 127 | { 128 | max = current.size; 129 | maxScreenMode = current; 130 | } 131 | } 132 | external.currentMode = maxScreenMode; 133 | 134 | tvoutWindow = [[UIWindow alloc] initWithFrame: CGRectMake(0,0, max.width, max.height)]; 135 | tvoutWindow.userInteractionEnabled = NO; 136 | tvoutWindow.screen = external; 137 | 138 | // size the mirrorView to expand to fit the external screen 139 | CGRect mirrorRect = [[UIScreen mainScreen] bounds]; 140 | CGFloat horiz = max.width / CGRectGetWidth(mirrorRect); 141 | CGFloat vert = max.height / CGRectGetHeight(mirrorRect); 142 | CGFloat bigScale = horiz < vert ? horiz : vert; 143 | mirrorRect = CGRectMake(mirrorRect.origin.x, mirrorRect.origin.y, mirrorRect.size.width * bigScale, mirrorRect.size.height * bigScale); 144 | 145 | mirrorView = [[UIImageView alloc] initWithFrame: mirrorRect]; 146 | mirrorView.center = tvoutWindow.center; 147 | 148 | // TV safe area -- scale the window by 20% -- for composite / component, not needed for VGA output 149 | if (tvSafeMode) tvoutWindow.transform = CGAffineTransformScale(tvoutWindow.transform, .8, .8); 150 | [tvoutWindow addSubview: mirrorView]; 151 | [mirrorView release]; 152 | [tvoutWindow makeKeyAndVisible]; 153 | tvoutWindow.hidden = NO; 154 | tvoutWindow.backgroundColor = [UIColor darkGrayColor]; 155 | 156 | // orient the view properly 157 | if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft) { 158 | mirrorView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * 1.5); 159 | } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight) { 160 | mirrorView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * -1.5); 161 | } 162 | startingTransform = mirrorView.transform; 163 | 164 | [deviceWindow makeKeyAndVisible]; 165 | 166 | [self updateTVOut]; 167 | 168 | if (SynchronizationMethod == MethodBackgroundThread) { 169 | [NSThread detachNewThreadSelector:@selector(updateLoop) toTarget:self withObject:nil]; 170 | } 171 | else if (SynchronizationMethod == MethodDisplayLink) { 172 | [self performSelectorInBackground:@selector(startDisplayLink) withObject:nil]; 173 | } 174 | else { 175 | updateTimer = [NSTimer scheduledTimerWithTimeInterval: (1.0/kFPS) target: self selector: @selector(updateTVOut) userInfo: nil repeats: YES]; 176 | [updateTimer retain]; 177 | } 178 | 179 | } 180 | } 181 | 182 | - (void) stopTVOut; 183 | { 184 | done = YES; 185 | if (updateTimer) { 186 | [updateTimer invalidate]; 187 | [updateTimer release], updateTimer = nil; 188 | } 189 | if (tvoutWindow) { 190 | [tvoutWindow release], tvoutWindow = nil; 191 | mirrorView = nil; 192 | } 193 | } 194 | 195 | 196 | - (void) updateTVOutForDisplayLink 197 | { 198 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 199 | [self updateTVOut]; 200 | [pool release]; 201 | } 202 | 203 | 204 | - (void) startDisplayLink 205 | { 206 | done = NO; 207 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 208 | CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateTVOutForDisplayLink)]; 209 | [displayLink setFrameInterval:(60 / kFPS)]; 210 | [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; 211 | while (!done) { 212 | [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0f]]; 213 | } 214 | [displayLink invalidate]; 215 | [pool release]; 216 | } 217 | 218 | - (void) updateTVOut; 219 | { 220 | #ifdef USE_UIGETSCREENIMAGE 221 | // UIGetScreenImage() is no longer allowed in shipping apps, see https://devforums.apple.com/thread/61338 222 | // however, it's better for demos, since it includes the status bar and captures animated transitions 223 | 224 | CGImageRef cgScreen = UIGetScreenImage(); 225 | #ifdef USE_LAYER 226 | mirrorView.layer.contents = (id)cgScreen; 227 | #else 228 | if (cgScreen) image = [UIImage imageWithCGImage:cgScreen]; 229 | mirrorView.image = image; 230 | #endif 231 | CGImageRelease(cgScreen); 232 | #else 233 | 234 | // from http://developer.apple.com/iphone/library/qa/qa2010/qa1703.html 235 | // bonus, this works in the simulator; sadly, it doesn't capture the status bar 236 | // 237 | // if you are making an OpenGL app, use UIGetScreenImage() above or switch the 238 | // following code to match Apple's sample at http://developer.apple.com/iphone/library/qa/qa2010/qa1704.html 239 | // note that you'll need to pass in a reference to your eaglview to get that to work. 240 | 241 | UIGraphicsBeginImageContext(deviceWindow.bounds.size); 242 | CGContextRef context = UIGraphicsGetCurrentContext(); 243 | 244 | // get every window's contents (i.e. so you can see alerts, ads, etc.) 245 | for (UIWindow *window in [[UIApplication sharedApplication] windows]) 246 | { 247 | if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen]) 248 | { 249 | CGContextSaveGState(context); 250 | CGContextTranslateCTM(context, [window center].x, [window center].y); 251 | CGContextConcatCTM(context, [window transform]); 252 | CGContextTranslateCTM(context, -[window bounds].size.width * window.layer.anchorPoint.x, -[window bounds].size.height * window.layer.anchorPoint.y); 253 | [[window layer] renderInContext:context]; 254 | CGContextRestoreGState(context); 255 | } 256 | } 257 | image = UIGraphicsGetImageFromCurrentImageContext(); 258 | UIGraphicsEndImageContext(); 259 | mirrorView.image = image; 260 | 261 | #endif 262 | } 263 | 264 | 265 | - (void)updateLoop; 266 | { 267 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 268 | done = NO; 269 | 270 | while ( ! done ) 271 | { 272 | [self performSelectorOnMainThread:@selector(updateTVOut) withObject:nil waitUntilDone:NO]; 273 | [NSThread sleepForTimeInterval: (1.0/kFPS) ]; 274 | } 275 | [pool release]; 276 | } 277 | 278 | -(void) screenDidConnectNotification: (NSNotification*) notification 279 | { 280 | //NSLog(@"Screen connected: %@", [notification object]); 281 | [self startTVOut]; 282 | } 283 | 284 | -(void) screenDidDisconnectNotification: (NSNotification*) notification 285 | { 286 | //NSLog(@"Screen disconnected: %@", [notification object]); 287 | [self stopTVOut]; 288 | } 289 | 290 | -(void) screenModeDidChangeNotification: (NSNotification*) notification 291 | { 292 | //NSLog(@"Screen mode changed: %@", [notification object]); 293 | [self startTVOut]; 294 | } 295 | 296 | -(void) deviceOrientationDidChange: (NSNotification*) notification 297 | { 298 | if (mirrorView == nil || done == YES) return; 299 | if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft) { 300 | [UIView beginAnimations:@"turnLeft" context:nil]; 301 | mirrorView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * 1.5); 302 | [UIView commitAnimations]; 303 | } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight) { 304 | [UIView beginAnimations:@"turnRight" context:nil]; 305 | mirrorView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * -1.5); 306 | [UIView commitAnimations]; 307 | } else if (UIDeviceOrientationIsPortrait ([[UIDevice currentDevice] orientation])) { 308 | [UIView beginAnimations:@"turnUp" context:nil]; 309 | mirrorView.transform = CGAffineTransformIdentity; 310 | [UIView commitAnimations]; 311 | } 312 | } 313 | 314 | @end 315 | -------------------------------------------------------------------------------- /FMDB/FMResultSet.m: -------------------------------------------------------------------------------- 1 | #import "FMResultSet.h" 2 | #import "FMDatabase.h" 3 | #import "unistd.h" 4 | 5 | @interface FMResultSet (Private) 6 | - (NSMutableDictionary *)columnNameToIndexMap; 7 | - (void)setColumnNameToIndexMap:(NSMutableDictionary *)value; 8 | @end 9 | 10 | @implementation FMResultSet 11 | 12 | + (id)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB { 13 | 14 | FMResultSet *rs = [[FMResultSet alloc] init]; 15 | 16 | [rs setStatement:statement]; 17 | [rs setParentDB:aDB]; 18 | 19 | return [rs autorelease]; 20 | } 21 | 22 | - (void)dealloc { 23 | [self close]; 24 | 25 | [query release]; 26 | query = nil; 27 | 28 | [columnNameToIndexMap release]; 29 | columnNameToIndexMap = nil; 30 | 31 | [super dealloc]; 32 | } 33 | 34 | - (void)close { 35 | 36 | [statement reset]; 37 | [statement release]; 38 | statement = nil; 39 | 40 | // we don't need this anymore... (i think) 41 | //[parentDB setInUse:NO]; 42 | parentDB = nil; 43 | } 44 | 45 | - (void)setupColumnNames { 46 | 47 | if (!columnNameToIndexMap) { 48 | [self setColumnNameToIndexMap:[NSMutableDictionary dictionary]]; 49 | } 50 | 51 | int columnCount = sqlite3_column_count(statement.statement); 52 | 53 | int columnIdx = 0; 54 | for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { 55 | [columnNameToIndexMap setObject:[NSNumber numberWithInt:columnIdx] 56 | forKey:[[NSString stringWithUTF8String:sqlite3_column_name(statement.statement, columnIdx)] lowercaseString]]; 57 | } 58 | columnNamesSetup = YES; 59 | } 60 | 61 | - (void)kvcMagic:(id)object { 62 | 63 | int columnCount = sqlite3_column_count(statement.statement); 64 | 65 | int columnIdx = 0; 66 | for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { 67 | 68 | const char *c = (const char *)sqlite3_column_text(statement.statement, columnIdx); 69 | 70 | // check for a null row 71 | if (c) { 72 | NSString *s = [NSString stringWithUTF8String:c]; 73 | 74 | [object setValue:s forKey:[NSString stringWithUTF8String:sqlite3_column_name(statement.statement, columnIdx)]]; 75 | } 76 | } 77 | } 78 | 79 | - (NSDictionary *)resultDict { 80 | 81 | NSInteger num_cols = sqlite3_data_count(statement.statement); 82 | 83 | if (num_cols > 0) { 84 | NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols]; 85 | 86 | NSInteger i; 87 | for (i = 0; i < num_cols; i++) { 88 | 89 | const char *col_name = sqlite3_column_name(statement.statement, i); 90 | 91 | if (col_name) { 92 | NSString *colName = [NSString stringWithUTF8String:col_name]; 93 | id value = nil; 94 | 95 | // fetch according to type 96 | switch (sqlite3_column_type(statement.statement, i)) { 97 | case SQLITE_INTEGER: { 98 | value = [NSNumber numberWithInt:[self intForColumnIndex:i]]; 99 | break; 100 | } 101 | case SQLITE_FLOAT: { 102 | value = [NSNumber numberWithDouble:[self doubleForColumnIndex:i]]; 103 | break; 104 | } 105 | case SQLITE_TEXT: { 106 | value = [self stringForColumnIndex:i]; 107 | break; 108 | } 109 | case SQLITE_BLOB: { 110 | value = [self dataForColumnIndex:i]; 111 | break; 112 | } 113 | } 114 | 115 | // save to dict 116 | if (value) { 117 | [dict setObject:value forKey:colName]; 118 | } 119 | } 120 | } 121 | 122 | return [[dict copy] autorelease]; 123 | } 124 | else { 125 | NSLog(@"Warning: There seem to be no columns in this set."); 126 | } 127 | 128 | return nil; 129 | } 130 | 131 | - (BOOL)next { 132 | 133 | int rc; 134 | BOOL retry; 135 | int numberOfRetries = 0; 136 | do { 137 | retry = NO; 138 | 139 | rc = sqlite3_step(statement.statement); 140 | 141 | if (SQLITE_BUSY == rc) { 142 | // this will happen if the db is locked, like if we are doing an update or insert. 143 | // in that case, retry the step... and maybe wait just 10 milliseconds. 144 | retry = YES; 145 | usleep(20); 146 | 147 | if ([parentDB busyRetryTimeout] && (numberOfRetries++ > [parentDB busyRetryTimeout])) { 148 | 149 | NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [parentDB databasePath]); 150 | NSLog(@"Database busy"); 151 | break; 152 | } 153 | } 154 | else if (SQLITE_DONE == rc || SQLITE_ROW == rc) { 155 | // all is well, let's return. 156 | } 157 | else if (SQLITE_ERROR == rc) { 158 | NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle])); 159 | break; 160 | } 161 | else if (SQLITE_MISUSE == rc) { 162 | // uh oh. 163 | NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle])); 164 | break; 165 | } 166 | else { 167 | // wtf? 168 | NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle])); 169 | break; 170 | } 171 | 172 | } while (retry); 173 | 174 | 175 | if (rc != SQLITE_ROW) { 176 | [self close]; 177 | } 178 | 179 | return (rc == SQLITE_ROW); 180 | } 181 | 182 | - (BOOL)hasAnotherRow { 183 | return sqlite3_errcode([parentDB sqliteHandle]) == SQLITE_ROW; 184 | } 185 | 186 | - (int)columnIndexForName:(NSString*)columnName { 187 | 188 | if (!columnNamesSetup) { 189 | [self setupColumnNames]; 190 | } 191 | 192 | columnName = [columnName lowercaseString]; 193 | 194 | NSNumber *n = [columnNameToIndexMap objectForKey:columnName]; 195 | 196 | if (n) { 197 | return [n intValue]; 198 | } 199 | 200 | NSLog(@"Warning: I could not find the column named '%@'.", columnName); 201 | 202 | return -1; 203 | } 204 | 205 | 206 | 207 | - (int)intForColumn:(NSString*)columnName { 208 | return [self intForColumnIndex:[self columnIndexForName:columnName]]; 209 | } 210 | 211 | - (int)intForColumnIndex:(int)columnIdx { 212 | return sqlite3_column_int(statement.statement, columnIdx); 213 | } 214 | 215 | - (long)longForColumn:(NSString*)columnName { 216 | return [self longForColumnIndex:[self columnIndexForName:columnName]]; 217 | } 218 | 219 | - (long)longForColumnIndex:(int)columnIdx { 220 | return (long)sqlite3_column_int64(statement.statement, columnIdx); 221 | } 222 | 223 | - (long long int)longLongIntForColumn:(NSString*)columnName { 224 | return [self longLongIntForColumnIndex:[self columnIndexForName:columnName]]; 225 | } 226 | 227 | - (long long int)longLongIntForColumnIndex:(int)columnIdx { 228 | return sqlite3_column_int64(statement.statement, columnIdx); 229 | } 230 | 231 | - (BOOL)boolForColumn:(NSString*)columnName { 232 | return [self boolForColumnIndex:[self columnIndexForName:columnName]]; 233 | } 234 | 235 | - (BOOL)boolForColumnIndex:(int)columnIdx { 236 | return ([self intForColumnIndex:columnIdx] != 0); 237 | } 238 | 239 | - (double)doubleForColumn:(NSString*)columnName { 240 | return [self doubleForColumnIndex:[self columnIndexForName:columnName]]; 241 | } 242 | 243 | - (double)doubleForColumnIndex:(int)columnIdx { 244 | return sqlite3_column_double(statement.statement, columnIdx); 245 | } 246 | 247 | - (NSString*)stringForColumnIndex:(int)columnIdx { 248 | 249 | if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { 250 | return nil; 251 | } 252 | 253 | const char *c = (const char *)sqlite3_column_text(statement.statement, columnIdx); 254 | 255 | if (!c) { 256 | // null row. 257 | return nil; 258 | } 259 | 260 | return [NSString stringWithUTF8String:c]; 261 | } 262 | 263 | - (NSString*)stringForColumn:(NSString*)columnName { 264 | return [self stringForColumnIndex:[self columnIndexForName:columnName]]; 265 | } 266 | 267 | - (NSDate*)dateForColumn:(NSString*)columnName { 268 | return [self dateForColumnIndex:[self columnIndexForName:columnName]]; 269 | } 270 | 271 | - (NSDate*)dateForColumnIndex:(int)columnIdx { 272 | 273 | if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { 274 | return nil; 275 | } 276 | 277 | return [NSDate dateWithTimeIntervalSince1970:[self doubleForColumnIndex:columnIdx]]; 278 | } 279 | 280 | 281 | - (NSData*)dataForColumn:(NSString*)columnName { 282 | return [self dataForColumnIndex:[self columnIndexForName:columnName]]; 283 | } 284 | 285 | - (NSData*)dataForColumnIndex:(int)columnIdx { 286 | 287 | if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { 288 | return nil; 289 | } 290 | 291 | int dataSize = sqlite3_column_bytes(statement.statement, columnIdx); 292 | 293 | NSMutableData *data = [NSMutableData dataWithLength:dataSize]; 294 | 295 | memcpy([data mutableBytes], sqlite3_column_blob(statement.statement, columnIdx), dataSize); 296 | 297 | return data; 298 | } 299 | 300 | 301 | - (NSData*)dataNoCopyForColumn:(NSString*)columnName { 302 | return [self dataNoCopyForColumnIndex:[self columnIndexForName:columnName]]; 303 | } 304 | 305 | - (NSData*)dataNoCopyForColumnIndex:(int)columnIdx { 306 | 307 | if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { 308 | return nil; 309 | } 310 | 311 | int dataSize = sqlite3_column_bytes(statement.statement, columnIdx); 312 | 313 | NSData *data = [NSData dataWithBytesNoCopy:(void *)sqlite3_column_blob(statement.statement, columnIdx) length:dataSize freeWhenDone:NO]; 314 | 315 | return data; 316 | } 317 | 318 | 319 | - (BOOL)columnIndexIsNull:(int)columnIdx { 320 | return sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL; 321 | } 322 | 323 | - (BOOL)columnIsNull:(NSString*)columnName { 324 | return [self columnIndexIsNull:[self columnIndexForName:columnName]]; 325 | } 326 | 327 | - (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx { 328 | 329 | if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) { 330 | return nil; 331 | } 332 | 333 | return sqlite3_column_text(statement.statement, columnIdx); 334 | } 335 | 336 | - (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName { 337 | return [self UTF8StringForColumnIndex:[self columnIndexForName:columnName]]; 338 | } 339 | 340 | 341 | // returns autoreleased NSString containing the name of the column in the result set 342 | - (NSString*)columnNameForIndex:(int)columnIdx { 343 | return [NSString stringWithUTF8String: sqlite3_column_name(statement.statement, columnIdx)]; 344 | } 345 | 346 | - (void)setParentDB:(FMDatabase *)newDb { 347 | parentDB = newDb; 348 | } 349 | 350 | 351 | - (NSString *)query { 352 | return query; 353 | } 354 | 355 | - (void)setQuery:(NSString *)value { 356 | [value retain]; 357 | [query release]; 358 | query = value; 359 | } 360 | 361 | - (NSMutableDictionary *)columnNameToIndexMap { 362 | return columnNameToIndexMap; 363 | } 364 | 365 | - (void)setColumnNameToIndexMap:(NSMutableDictionary *)value { 366 | [value retain]; 367 | [columnNameToIndexMap release]; 368 | columnNameToIndexMap = value; 369 | } 370 | 371 | - (FMStatement *)statement { 372 | return statement; 373 | } 374 | 375 | - (void)setStatement:(FMStatement *)value { 376 | if (statement != value) { 377 | [statement release]; 378 | statement = [value retain]; 379 | } 380 | } 381 | 382 | 383 | 384 | @end 385 | --------------------------------------------------------------------------------